v4l2.c 28.5 KB
Newer Older
Luca Abeni's avatar
Luca Abeni committed
1 2
/*
 * Video4Linux2 grab interface
3 4
 * Copyright (c) 2000,2001 Fabrice Bellard
 * Copyright (c) 2006 Luca Abeni
Luca Abeni's avatar
Luca Abeni committed
5 6 7 8 9
 *
 * Part of this file is based on the V4L2 video capture example
 * (http://v4l2spec.bytesex.org/v4l2spec/capture.c)
 *
 * Thanks to Michael Niedermayer for providing the mapping between
10
 * V4L2_PIX_FMT_* and AV_PIX_FMT_*
Luca Abeni's avatar
Luca Abeni committed
11 12
 *
 *
13
 * This file is part of Libav.
14
 *
15
 * Libav is free software; you can redistribute it and/or
Luca Abeni's avatar
Luca Abeni committed
16 17
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
18
 * version 2.1 of the License, or (at your option) any later version.
Luca Abeni's avatar
Luca Abeni committed
19
 *
20
 * Libav is distributed in the hope that it will be useful,
Luca Abeni's avatar
Luca Abeni committed
21 22 23 24 25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
26
 * License along with Libav; if not, write to the Free Software
Luca Abeni's avatar
Luca Abeni committed
27 28
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
29

30
#undef __STRICT_ANSI__ //workaround due to broken kernel headers
31
#include "config.h"
32
#include "libavformat/avformat.h"
33
#include "libavformat/internal.h"
Luca Abeni's avatar
Luca Abeni committed
34 35 36 37 38
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
Luca Barbato's avatar
Luca Barbato committed
39
#include <poll.h>
40
#if HAVE_SYS_VIDEOIO_H
41 42
#include <sys/videoio.h>
#else
43
#include <linux/videodev2.h>
44
#endif
45 46
#include "libavutil/atomic.h"
#include "libavutil/avassert.h"
47
#include "libavutil/imgutils.h"
48
#include "libavutil/internal.h"
49 50
#include "libavutil/log.h"
#include "libavutil/opt.h"
51
#include "libavutil/parseutils.h"
52
#include "libavutil/pixdesc.h"
53
#include "libavutil/avstring.h"
Luca Barbato's avatar
Luca Barbato committed
54
#include "libavutil/mathematics.h"
Luca Abeni's avatar
Luca Abeni committed
55 56 57

static const int desired_video_buffers = 256;

Luca Barbato's avatar
Luca Barbato committed
58 59 60 61
#define V4L_ALLFORMATS  3
#define V4L_RAWFORMATS  1
#define V4L_COMPFORMATS 2

Luca Abeni's avatar
Luca Abeni committed
62
struct video_data {
63
    AVClass *class;
Luca Abeni's avatar
Luca Abeni committed
64 65 66 67
    int fd;
    int frame_format; /* V4L2_PIX_FMT_* */
    int width, height;
    int frame_size;
Luca Barbato's avatar
Luca Barbato committed
68
    int timeout;
69
    int interlaced;
Luca Abeni's avatar
Luca Abeni committed
70 71 72
    int top_field_first;

    int buffers;
73
    volatile int buffers_queued;
Luca Abeni's avatar
Luca Abeni committed
74 75
    void **buf_start;
    unsigned int *buf_len;
76
    char *standard;
77
    int channel;
Luca Barbato's avatar
Luca Barbato committed
78 79
    char *video_size;   /**< String describing video size,
                             set by a private option. */
80
    char *pixel_format; /**< Set by a private option. */
Luca Barbato's avatar
Luca Barbato committed
81
    int list_format;    /**< Set by a private option. */
82
    char *framerate;    /**< Set by a private option. */
Luca Abeni's avatar
Luca Abeni committed
83 84
};

85
struct buff_data {
86
    struct video_data *s;
87 88 89 90
    int index;
    int fd;
};

Luca Abeni's avatar
Luca Abeni committed
91
struct fmt_map {
92
    enum AVPixelFormat ff_fmt;
93
    enum AVCodecID codec_id;
94
    uint32_t v4l2_fmt;
Luca Abeni's avatar
Luca Abeni committed
95 96 97
};

static struct fmt_map fmt_conversion_table[] = {
98
    //ff_fmt           codec_id           v4l2_fmt
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    { AV_PIX_FMT_YUV420P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV420  },
    { AV_PIX_FMT_YUV422P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV422P },
    { AV_PIX_FMT_YUYV422, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUYV    },
    { AV_PIX_FMT_UYVY422, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_UYVY    },
    { AV_PIX_FMT_YUV411P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV411P },
    { AV_PIX_FMT_YUV410P, AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_YUV410  },
    { AV_PIX_FMT_RGB555,  AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB555  },
    { AV_PIX_FMT_RGB565,  AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB565  },
    { AV_PIX_FMT_BGR24,   AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR24   },
    { AV_PIX_FMT_RGB24,   AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_RGB24   },
    { AV_PIX_FMT_BGRA,    AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_BGR32   },
    { AV_PIX_FMT_GRAY8,   AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_GREY    },
    { AV_PIX_FMT_NV12,    AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12    },
    { AV_PIX_FMT_NONE,    AV_CODEC_ID_MJPEG,    V4L2_PIX_FMT_MJPEG   },
    { AV_PIX_FMT_NONE,    AV_CODEC_ID_MJPEG,    V4L2_PIX_FMT_JPEG    },
Luca Abeni's avatar
Luca Abeni committed
114 115
};

Luca Barbato's avatar
Luca Barbato committed
116
static int device_open(AVFormatContext *ctx)
Luca Abeni's avatar
Luca Abeni committed
117 118 119
{
    struct v4l2_capability cap;
    int fd;
120
    int res, err;
121
    int flags = O_RDWR;
Tristan Matthews's avatar
Tristan Matthews committed
122
    char errbuf[128];
Luca Abeni's avatar
Luca Abeni committed
123

124 125 126
    if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
        flags |= O_NONBLOCK;
    }
Luca Barbato's avatar
Luca Barbato committed
127

128
    fd = avpriv_open(ctx->filename, flags);
Luca Abeni's avatar
Luca Abeni committed
129
    if (fd < 0) {
Tristan Matthews's avatar
Tristan Matthews committed
130 131
        err = AVERROR(errno);
        av_strerror(err, errbuf, sizeof(errbuf));
Luca Barbato's avatar
Luca Barbato committed
132

Luca Abeni's avatar
Luca Abeni committed
133
        av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
134
               ctx->filename, errbuf);
Luca Abeni's avatar
Luca Abeni committed
135

Tristan Matthews's avatar
Tristan Matthews committed
136
        return err;
Luca Abeni's avatar
Luca Abeni committed
137 138 139 140
    }

    res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
    if (res < 0) {
Luca Barbato's avatar
Luca Barbato committed
141 142
        err = AVERROR(errno);
        av_strerror(err, errbuf, sizeof(errbuf));
Luca Abeni's avatar
Luca Abeni committed
143
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
144
               errbuf);
Luca Abeni's avatar
Luca Abeni committed
145

Luca Barbato's avatar
Luca Barbato committed
146
        goto fail;
Luca Abeni's avatar
Luca Abeni committed
147
    }
Luca Barbato's avatar
Luca Barbato committed
148

Luca Barbato's avatar
Luca Barbato committed
149 150 151 152 153
    av_log(ctx, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n",
           fd, cap.capabilities);

    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n");
Luca Barbato's avatar
Luca Barbato committed
154
        err = AVERROR(ENODEV);
Luca Abeni's avatar
Luca Abeni committed
155

Luca Barbato's avatar
Luca Barbato committed
156
        goto fail;
Luca Abeni's avatar
Luca Abeni committed
157
    }
Luca Barbato's avatar
Luca Barbato committed
158

Luca Barbato's avatar
Luca Barbato committed
159 160 161
    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
        av_log(ctx, AV_LOG_ERROR,
               "The device does not support the streaming I/O method.\n");
Luca Barbato's avatar
Luca Barbato committed
162
        err = AVERROR(ENOSYS);
Luca Barbato's avatar
Luca Barbato committed
163 164 165

        goto fail;
    }
Luca Abeni's avatar
Luca Abeni committed
166 167

    return fd;
Luca Barbato's avatar
Luca Barbato committed
168 169 170

fail:
    close(fd);
Luca Barbato's avatar
Luca Barbato committed
171
    return err;
Luca Abeni's avatar
Luca Abeni committed
172 173
}

Luca Barbato's avatar
Luca Barbato committed
174 175
static int device_init(AVFormatContext *ctx, int *width, int *height,
                       uint32_t pix_fmt)
Luca Abeni's avatar
Luca Abeni committed
176
{
Luca Abeni's avatar
Luca Abeni committed
177 178
    struct video_data *s = ctx->priv_data;
    int fd = s->fd;
179
    struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
Luca Barbato's avatar
Luca Barbato committed
180 181
    struct v4l2_pix_format *pix = &fmt.fmt.pix;

182
    int res;
Luca Abeni's avatar
Luca Abeni committed
183

Luca Barbato's avatar
Luca Barbato committed
184 185 186 187 188
    pix->width = *width;
    pix->height = *height;
    pix->pixelformat = pix_fmt;
    pix->field = V4L2_FIELD_ANY;

189
    res = ioctl(fd, VIDIOC_S_FMT, &fmt);
Luca Barbato's avatar
Luca Barbato committed
190

191
    if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
Luca Barbato's avatar
Luca Barbato committed
192 193 194
        av_log(ctx, AV_LOG_INFO,
               "The V4L2 driver changed the video from %dx%d to %dx%d\n",
               *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height);
195 196 197 198
        *width = fmt.fmt.pix.width;
        *height = fmt.fmt.pix.height;
    }

199
    if (pix_fmt != fmt.fmt.pix.pixelformat) {
Luca Barbato's avatar
Luca Barbato committed
200 201 202 203
        av_log(ctx, AV_LOG_DEBUG,
               "The V4L2 driver changed the pixel format "
               "from 0x%08X to 0x%08X\n",
               pix_fmt, fmt.fmt.pix.pixelformat);
204 205 206
        res = -1;
    }

207 208 209 210 211
    if (fmt.fmt.pix.field == V4L2_FIELD_INTERLACED) {
        av_log(ctx, AV_LOG_DEBUG, "The V4L2 driver using the interlaced mode");
        s->interlaced = 1;
    }

212
    return res;
Luca Abeni's avatar
Luca Abeni committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
}

static int first_field(int fd)
{
    int res;
    v4l2_std_id std;

    res = ioctl(fd, VIDIOC_G_STD, &std);
    if (res < 0) {
        return 0;
    }
    if (std & V4L2_STD_NTSC) {
        return 0;
    }

    return 1;
}

231
static uint32_t fmt_ff2v4l(enum AVPixelFormat pix_fmt, enum AVCodecID codec_id)
Luca Abeni's avatar
Luca Abeni committed
232 233 234
{
    int i;

235
    for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
236
        if ((codec_id == AV_CODEC_ID_NONE ||
237
             fmt_conversion_table[i].codec_id == codec_id) &&
238
            (pix_fmt == AV_PIX_FMT_NONE ||
239
             fmt_conversion_table[i].ff_fmt == pix_fmt)) {
Luca Abeni's avatar
Luca Abeni committed
240 241 242 243 244 245 246
            return fmt_conversion_table[i].v4l2_fmt;
        }
    }

    return 0;
}

247
static enum AVPixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum AVCodecID codec_id)
Luca Abeni's avatar
Luca Abeni committed
248 249 250
{
    int i;

251
    for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
252 253
        if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt &&
            fmt_conversion_table[i].codec_id == codec_id) {
Luca Abeni's avatar
Luca Abeni committed
254 255 256 257
            return fmt_conversion_table[i].ff_fmt;
        }
    }

258
    return AV_PIX_FMT_NONE;
Luca Abeni's avatar
Luca Abeni committed
259 260
}

261
static enum AVCodecID fmt_v4l2codec(uint32_t v4l2_fmt)
262 263 264 265 266 267 268 269 270
{
    int i;

    for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
        if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt) {
            return fmt_conversion_table[i].codec_id;
        }
    }

271
    return AV_CODEC_ID_NONE;
272 273
}

Luca Barbato's avatar
Luca Barbato committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat)
{
    struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat };

    while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) {
        switch (vfse.type) {
        case V4L2_FRMSIZE_TYPE_DISCRETE:
            av_log(ctx, AV_LOG_INFO, " %ux%u",
                   vfse.discrete.width, vfse.discrete.height);
        break;
        case V4L2_FRMSIZE_TYPE_CONTINUOUS:
        case V4L2_FRMSIZE_TYPE_STEPWISE:
            av_log(ctx, AV_LOG_INFO, " {%u-%u, %u}x{%u-%u, %u}",
                   vfse.stepwise.min_width,
                   vfse.stepwise.max_width,
                   vfse.stepwise.step_width,
                   vfse.stepwise.min_height,
                   vfse.stepwise.max_height,
                   vfse.stepwise.step_height);
        }
        vfse.index++;
    }
}
#endif

static void list_formats(AVFormatContext *ctx, int fd, int type)
{
    struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };

    while(!ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) {
305
        enum AVCodecID codec_id = fmt_v4l2codec(vfd.pixelformat);
306
        enum AVPixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id);
Luca Barbato's avatar
Luca Barbato committed
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325

        vfd.index++;

        if (!(vfd.flags & V4L2_FMT_FLAG_COMPRESSED) &&
            type & V4L_RAWFORMATS) {
            const char *fmt_name = av_get_pix_fmt_name(pix_fmt);
            av_log(ctx, AV_LOG_INFO, "R : %9s : %20s :",
                   fmt_name ? fmt_name : "Unsupported",
                   vfd.description);
        } else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED &&
                   type & V4L_COMPFORMATS) {
            AVCodec *codec = avcodec_find_encoder(codec_id);
            av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :",
                   codec ? codec->name : "Unsupported",
                   vfd.description);
        } else {
            continue;
        }

326
#ifdef V4L2_FMT_FLAG_EMULATED
Luca Barbato's avatar
Luca Barbato committed
327 328 329 330
        if (vfd.flags & V4L2_FMT_FLAG_EMULATED) {
            av_log(ctx, AV_LOG_WARNING, "%s", "Emulated");
            continue;
        }
331
#endif
Luca Barbato's avatar
Luca Barbato committed
332 333 334 335 336 337 338
#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
        list_framesizes(ctx, fd, vfd.pixelformat);
#endif
        av_log(ctx, AV_LOG_INFO, "\n");
    }
}

Luca Abeni's avatar
Luca Abeni committed
339
static int mmap_init(AVFormatContext *ctx)
Luca Abeni's avatar
Luca Abeni committed
340 341
{
    int i, res;
342 343 344 345 346 347
    struct video_data *s = ctx->priv_data;
    struct v4l2_requestbuffers req = {
        .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
        .count  = desired_video_buffers,
        .memory = V4L2_MEMORY_MMAP
    };
Luca Abeni's avatar
Luca Abeni committed
348

349
    res = ioctl(s->fd, VIDIOC_REQBUFS, &req);
Luca Abeni's avatar
Luca Abeni committed
350
    if (res < 0) {
Luca Barbato's avatar
Luca Barbato committed
351
        res = errno;
Luca Abeni's avatar
Luca Abeni committed
352
        if (errno == EINVAL) {
Luca Abeni's avatar
Luca Abeni committed
353
            av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
Luca Abeni's avatar
Luca Abeni committed
354
        } else {
Luca Abeni's avatar
Luca Abeni committed
355
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
Luca Abeni's avatar
Luca Abeni committed
356 357
        }

Luca Barbato's avatar
Luca Barbato committed
358
        return AVERROR(res);
Luca Abeni's avatar
Luca Abeni committed
359 360 361
    }

    if (req.count < 2) {
Luca Abeni's avatar
Luca Abeni committed
362
        av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
Luca Abeni's avatar
Luca Abeni committed
363

364
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
365 366 367
    }
    s->buffers = req.count;
    s->buf_start = av_malloc(sizeof(void *) * s->buffers);
368
    if (!s->buf_start) {
Luca Abeni's avatar
Luca Abeni committed
369
        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
Luca Abeni's avatar
Luca Abeni committed
370

371
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
372 373
    }
    s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
374
    if (!s->buf_len) {
Luca Abeni's avatar
Luca Abeni committed
375
        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
Luca Abeni's avatar
Luca Abeni committed
376 377
        av_free(s->buf_start);

378
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
379 380 381
    }

    for (i = 0; i < req.count; i++) {
382 383 384 385 386
        struct v4l2_buffer buf = {
            .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
            .index  = i,
            .memory = V4L2_MEMORY_MMAP
        };
Luca Abeni's avatar
Luca Abeni committed
387

388
        res = ioctl(s->fd, VIDIOC_QUERYBUF, &buf);
Luca Abeni's avatar
Luca Abeni committed
389
        if (res < 0) {
Luca Barbato's avatar
Luca Barbato committed
390
            res = AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
391
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
Luca Abeni's avatar
Luca Abeni committed
392

Luca Barbato's avatar
Luca Barbato committed
393
            return res;
Luca Abeni's avatar
Luca Abeni committed
394 395 396
        }

        s->buf_len[i] = buf.length;
397
        if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
Luca Barbato's avatar
Luca Barbato committed
398 399 400
            av_log(ctx, AV_LOG_ERROR,
                   "Buffer len [%d] = %d != %d\n",
                   i, s->buf_len[i], s->frame_size);
Luca Abeni's avatar
Luca Abeni committed
401 402 403

            return -1;
        }
Luca Barbato's avatar
Luca Barbato committed
404 405 406 407
        s->buf_start[i] = mmap(NULL, buf.length,
                               PROT_READ | PROT_WRITE, MAP_SHARED,
                               s->fd, buf.m.offset);

Luca Abeni's avatar
Luca Abeni committed
408
        if (s->buf_start[i] == MAP_FAILED) {
Tristan Matthews's avatar
Tristan Matthews committed
409
            char errbuf[128];
Luca Barbato's avatar
Luca Barbato committed
410 411
            res = AVERROR(errno);
            av_strerror(res, errbuf, sizeof(errbuf));
Tristan Matthews's avatar
Tristan Matthews committed
412
            av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", errbuf);
Luca Abeni's avatar
Luca Abeni committed
413

Luca Barbato's avatar
Luca Barbato committed
414
            return res;
Luca Abeni's avatar
Luca Abeni committed
415 416 417 418 419 420
        }
    }

    return 0;
}

421 422 423 424 425 426 427 428
#if FF_API_DESTRUCT_PACKET
static void dummy_release_buffer(AVPacket *pkt)
{
    av_assert0(0);
}
#endif

static void mmap_release_buffer(void *opaque, uint8_t *data)
429
{
430
    struct v4l2_buffer buf = { 0 };
431
    int res, fd;
432 433
    struct buff_data *buf_descriptor = opaque;
    struct video_data *s = buf_descriptor->s;
Tristan Matthews's avatar
Tristan Matthews committed
434
    char errbuf[128];
435

436 437 438 439 440 441
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = buf_descriptor->index;
    fd = buf_descriptor->fd;
    av_free(buf_descriptor);

442
    res = ioctl(fd, VIDIOC_QBUF, &buf);
Tristan Matthews's avatar
Tristan Matthews committed
443 444
    if (res < 0) {
        av_strerror(AVERROR(errno), errbuf, sizeof(errbuf));
Luca Barbato's avatar
Luca Barbato committed
445
        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
446 447
               errbuf);
    }
448
    avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
449 450 451
}

static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
Luca Abeni's avatar
Luca Abeni committed
452
{
Luca Abeni's avatar
Luca Abeni committed
453
    struct video_data *s = ctx->priv_data;
454 455 456 457
    struct v4l2_buffer buf = {
        .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
        .memory = V4L2_MEMORY_MMAP
    };
Luca Barbato's avatar
Luca Barbato committed
458
    struct pollfd p = { .fd = s->fd, .events = POLLIN };
Luca Abeni's avatar
Luca Abeni committed
459 460
    int res;

Luca Barbato's avatar
Luca Barbato committed
461 462 463 464 465 466 467
    res = poll(&p, 1, s->timeout);
    if (res < 0)
        return AVERROR(errno);

    if (!(p.revents & (POLLIN | POLLERR | POLLHUP)))
        return AVERROR(EAGAIN);

Luca Abeni's avatar
Luca Abeni committed
468
    /* FIXME: Some special treatment might be needed in case of loss of signal... */
469
    while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
Luca Abeni's avatar
Luca Abeni committed
470
    if (res < 0) {
Tristan Matthews's avatar
Tristan Matthews committed
471
        char errbuf[128];
472 473 474 475 476
        if (errno == EAGAIN) {
            pkt->size = 0;

            return AVERROR(EAGAIN);
        }
Luca Barbato's avatar
Luca Barbato committed
477 478
        res = AVERROR(errno);
        av_strerror(res, errbuf, sizeof(errbuf));
Luca Barbato's avatar
Luca Barbato committed
479
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
480
               errbuf);
Luca Abeni's avatar
Luca Abeni committed
481

Luca Barbato's avatar
Luca Barbato committed
482
        return res;
Luca Abeni's avatar
Luca Abeni committed
483
    }
484 485 486 487 488

    if (buf.index >= s->buffers) {
        av_log(ctx, AV_LOG_ERROR, "Invalid buffer index received.\n");
        return AVERROR(EINVAL);
    }
489 490 491
    avpriv_atomic_int_add_and_fetch(&s->buffers_queued, -1);
    // always keep at least one buffer queued
    av_assert0(avpriv_atomic_int_get(&s->buffers_queued) >= 1);
492

493
    if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
Luca Barbato's avatar
Luca Barbato committed
494 495 496
        av_log(ctx, AV_LOG_ERROR,
               "The v4l2 frame is %d bytes, but %d bytes are expected\n",
               buf.bytesused, s->frame_size);
497

498
        return AVERROR_INVALIDDATA;
499 500
    }

Luca Abeni's avatar
Luca Abeni committed
501
    /* Image is at s->buff_start[buf.index] */
502
    if (avpriv_atomic_int_get(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) {
Diego Biurrun's avatar
Diego Biurrun committed
503
        /* when we start getting low on queued buffers, fall back on copying data */
504 505 506 507 508 509 510
        res = av_new_packet(pkt, buf.bytesused);
        if (res < 0) {
            av_log(ctx, AV_LOG_ERROR, "Error allocating a packet.\n");
            return res;
        }
        memcpy(pkt->data, s->buf_start[buf.index], buf.bytesused);

511
        res = ioctl(s->fd, VIDIOC_QBUF, &buf);
512
        if (res < 0) {
Luca Barbato's avatar
Luca Barbato committed
513
            res = AVERROR(errno);
514 515
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
            av_free_packet(pkt);
Luca Barbato's avatar
Luca Barbato committed
516
            return res;
517 518 519 520
        }
        avpriv_atomic_int_add_and_fetch(&s->buffers_queued, 1);
    } else {
        struct buff_data *buf_descriptor;
Luca Abeni's avatar
Luca Abeni committed
521

522 523 524
        pkt->data     = s->buf_start[buf.index];
        pkt->size     = buf.bytesused;
#if FF_API_DESTRUCT_PACKET
525
FF_DISABLE_DEPRECATION_WARNINGS
526
        pkt->destruct = dummy_release_buffer;
527
FF_ENABLE_DEPRECATION_WARNINGS
528 529 530
#endif

        buf_descriptor = av_malloc(sizeof(struct buff_data));
531
        if (!buf_descriptor) {
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
            /* Something went wrong... Since av_malloc() failed, we cannot even
             * allocate a buffer for memcpying into it
             */
            av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
            res = ioctl(s->fd, VIDIOC_QBUF, &buf);

            return AVERROR(ENOMEM);
        }
        buf_descriptor->fd    = s->fd;
        buf_descriptor->index = buf.index;
        buf_descriptor->s     = s;

        pkt->buf = av_buffer_create(pkt->data, pkt->size, mmap_release_buffer,
                                    buf_descriptor, 0);
        if (!pkt->buf) {
            av_freep(&buf_descriptor);
            return AVERROR(ENOMEM);
        }
Luca Abeni's avatar
Luca Abeni committed
550
    }
551
    pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
Luca Abeni's avatar
Luca Abeni committed
552 553 554 555

    return s->buf_len[buf.index];
}

Luca Abeni's avatar
Luca Abeni committed
556
static int mmap_start(AVFormatContext *ctx)
Luca Abeni's avatar
Luca Abeni committed
557
{
Luca Abeni's avatar
Luca Abeni committed
558
    struct video_data *s = ctx->priv_data;
Luca Abeni's avatar
Luca Abeni committed
559
    enum v4l2_buf_type type;
Tristan Matthews's avatar
Tristan Matthews committed
560 561
    int i, res, err;
    char errbuf[128];
Luca Abeni's avatar
Luca Abeni committed
562 563

    for (i = 0; i < s->buffers; i++) {
564 565 566 567 568
        struct v4l2_buffer buf = {
            .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
            .index  = i,
            .memory = V4L2_MEMORY_MMAP
        };
Luca Abeni's avatar
Luca Abeni committed
569

570
        res = ioctl(s->fd, VIDIOC_QBUF, &buf);
Luca Abeni's avatar
Luca Abeni committed
571
        if (res < 0) {
Tristan Matthews's avatar
Tristan Matthews committed
572 573
            err = AVERROR(errno);
            av_strerror(err, errbuf, sizeof(errbuf));
Luca Barbato's avatar
Luca Barbato committed
574
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
575
                   errbuf);
Luca Abeni's avatar
Luca Abeni committed
576

Tristan Matthews's avatar
Tristan Matthews committed
577
            return err;
Luca Abeni's avatar
Luca Abeni committed
578 579
        }
    }
580
    s->buffers_queued = s->buffers;
Luca Abeni's avatar
Luca Abeni committed
581 582

    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
583
    res = ioctl(s->fd, VIDIOC_STREAMON, &type);
Luca Abeni's avatar
Luca Abeni committed
584
    if (res < 0) {
Tristan Matthews's avatar
Tristan Matthews committed
585 586
        err = AVERROR(errno);
        av_strerror(err, errbuf, sizeof(errbuf));
Luca Barbato's avatar
Luca Barbato committed
587
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
588
               errbuf);
Luca Abeni's avatar
Luca Abeni committed
589

Tristan Matthews's avatar
Tristan Matthews committed
590
        return err;
Luca Abeni's avatar
Luca Abeni committed
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
    }

    return 0;
}

static void mmap_close(struct video_data *s)
{
    enum v4l2_buf_type type;
    int i;

    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    /* We do not check for the result, because we could
     * not do anything about it anyway...
     */
    ioctl(s->fd, VIDIOC_STREAMOFF, &type);
    for (i = 0; i < s->buffers; i++) {
        munmap(s->buf_start[i], s->buf_len[i]);
    }
    av_free(s->buf_start);
    av_free(s->buf_len);
}

613
static int v4l2_set_parameters(AVFormatContext *s1)
614 615
{
    struct video_data *s = s1->priv_data;
616 617
    struct v4l2_input input = { 0 };
    struct v4l2_standard standard = { 0 };
618 619
    struct v4l2_streamparm streamparm = { 0 };
    struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe;
620
    AVRational framerate_q = { 0 };
621
    int i, ret;
622

623 624
    streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

Luca Barbato's avatar
Luca Barbato committed
625 626 627 628
    if (s->framerate &&
        (ret = av_parse_video_rate(&framerate_q, s->framerate)) < 0) {
        av_log(s1, AV_LOG_ERROR, "Could not parse framerate '%s'.\n",
               s->framerate);
629 630
        return ret;
    }
631

Anton Khirnov's avatar
Anton Khirnov committed
632 633 634 635 636 637
    /* set tv video input */
    input.index = s->channel;
    if (ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
        av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
        return AVERROR(EIO);
    }
638

Anton Khirnov's avatar
Anton Khirnov committed
639 640 641
    av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
            s->channel, input.name);
    if (ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) {
Luca Barbato's avatar
Luca Barbato committed
642 643
        av_log(s1, AV_LOG_ERROR,
               "The V4L2 driver ioctl set input(%d) failed\n",
Anton Khirnov's avatar
Anton Khirnov committed
644 645 646
                s->channel);
        return AVERROR(EIO);
    }
647

648
    if (s->standard) {
Luca Abeni's avatar
Luca Abeni committed
649
        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
650
               s->standard);
Luca Abeni's avatar
Luca Abeni committed
651 652 653 654
        /* set tv standard */
        for(i=0;;i++) {
            standard.index = i;
            if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
Luca Barbato's avatar
Luca Barbato committed
655 656
                av_log(s1, AV_LOG_ERROR,
                       "The V4L2 driver ioctl set standard(%s) failed\n",
657
                       s->standard);
658
                return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
659 660
            }

661
            if (!av_strcasecmp(standard.name, s->standard)) {
Luca Abeni's avatar
Luca Abeni committed
662 663 664 665
                break;
            }
        }

Luca Barbato's avatar
Luca Barbato committed
666 667
        av_log(s1, AV_LOG_DEBUG,
               "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
668
               s->standard, (uint64_t)standard.id);
Luca Abeni's avatar
Luca Abeni committed
669
        if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
Luca Barbato's avatar
Luca Barbato committed
670 671
            av_log(s1, AV_LOG_ERROR,
                   "The V4L2 driver ioctl set standard(%s) failed\n",
672
                   s->standard);
673
            return AVERROR(EIO);
674
        }
675
    }
676

677
    if (framerate_q.num && framerate_q.den) {
678
        av_log(s1, AV_LOG_DEBUG, "Setting time per frame to %d/%d\n",
679 680 681
               framerate_q.den, framerate_q.num);
        tpf->numerator   = framerate_q.den;
        tpf->denominator = framerate_q.num;
Luca Barbato's avatar
Luca Barbato committed
682

683 684 685
        if (ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) {
            av_log(s1, AV_LOG_ERROR,
                   "ioctl set time per frame(%d/%d) failed\n",
686
                   framerate_q.den, framerate_q.num);
687 688 689
            return AVERROR(EIO);
        }

690 691
        if (framerate_q.num != tpf->denominator ||
            framerate_q.den != tpf->numerator) {
692
            av_log(s1, AV_LOG_INFO,
Luca Barbato's avatar
Luca Barbato committed
693 694
                   "The driver changed the time per frame from "
                   "%d/%d to %d/%d\n",
695
                   framerate_q.den, framerate_q.num,
696 697
                   tpf->numerator, tpf->denominator);
        }
698 699
    } else {
        if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) {
Tristan Matthews's avatar
Tristan Matthews committed
700
            char errbuf[128];
Luca Barbato's avatar
Luca Barbato committed
701 702
            ret = AVERROR(errno);
            av_strerror(ret, errbuf, sizeof(errbuf));
Luca Barbato's avatar
Luca Barbato committed
703
            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
704
                   errbuf);
Luca Barbato's avatar
Luca Barbato committed
705
            return ret;
706
        }
707
    }
708 709
    s1->streams[0]->avg_frame_rate.num = tpf->denominator;
    s1->streams[0]->avg_frame_rate.den = tpf->numerator;
710

Luca Barbato's avatar
Luca Barbato committed
711
    s->timeout = 100 +
712
        av_rescale_q(1, s1->streams[0]->avg_frame_rate,
Luca Barbato's avatar
Luca Barbato committed
713 714
                        (AVRational){1, 1000});

715 716 717
    return 0;
}

718
static uint32_t device_try_init(AVFormatContext *s1,
719
                                enum AVPixelFormat pix_fmt,
720 721
                                int *width,
                                int *height,
722
                                enum AVCodecID *codec_id)
723
{
724
    uint32_t desired_format = fmt_ff2v4l(pix_fmt, s1->video_codec_id);
725 726 727 728 729 730 731

    if (desired_format == 0 ||
        device_init(s1, width, height, desired_format) < 0) {
        int i;

        desired_format = 0;
        for (i = 0; i<FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
732
            if (s1->video_codec_id == AV_CODEC_ID_NONE ||
733
                fmt_conversion_table[i].codec_id == s1->video_codec_id) {
734 735 736 737 738 739 740 741
                desired_format = fmt_conversion_table[i].v4l2_fmt;
                if (device_init(s1, width, height, desired_format) >= 0) {
                    break;
                }
                desired_format = 0;
            }
        }
    }
Luca Barbato's avatar
Luca Barbato committed
742

743 744
    if (desired_format != 0) {
        *codec_id = fmt_v4l2codec(desired_format);
745
        assert(*codec_id != AV_CODEC_ID_NONE);
746 747 748 749 750
    }

    return desired_format;
}

751
static int v4l2_read_header(AVFormatContext *s1)
Luca Abeni's avatar
Luca Abeni committed
752 753 754
{
    struct video_data *s = s1->priv_data;
    AVStream *st;
755
    int res = 0;
Luca Barbato's avatar
Luca Barbato committed
756
    uint32_t desired_format;
757
    enum AVCodecID codec_id;
758
    enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE;
Luca Abeni's avatar
Luca Abeni committed
759

760
    st = avformat_new_stream(s1, NULL);
761 762
    if (!st)
        return AVERROR(ENOMEM);
Luca Barbato's avatar
Luca Barbato committed
763

Luca Barbato's avatar
Luca Barbato committed
764
    s->fd = device_open(s1);
765 766
    if (s->fd < 0)
        return s->fd;
Luca Barbato's avatar
Luca Barbato committed
767

Luca Barbato's avatar
Luca Barbato committed
768 769
    if (s->list_format) {
        list_formats(s1, s->fd, s->list_format);
770
        return AVERROR_EXIT;
Luca Barbato's avatar
Luca Barbato committed
771 772
    }

773
    avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
Luca Abeni's avatar
Luca Abeni committed
774

Luca Barbato's avatar
Luca Barbato committed
775 776 777 778
    if (s->video_size &&
        (res = av_parse_video_size(&s->width, &s->height, s->video_size)) < 0) {
        av_log(s1, AV_LOG_ERROR, "Could not parse video size '%s'.\n",
               s->video_size);
779
        return res;
780
    }
Luca Barbato's avatar
Luca Barbato committed
781 782

    if (s->pixel_format) {
783 784 785 786
        AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format);

        if (codec)
            s1->video_codec_id = codec->id;
Luca Barbato's avatar
Luca Barbato committed
787 788 789

        pix_fmt = av_get_pix_fmt(s->pixel_format);

790
        if (pix_fmt == AV_PIX_FMT_NONE && !codec) {
791
            av_log(s1, AV_LOG_ERROR, "No such input format: %s.\n",
Luca Barbato's avatar
Luca Barbato committed
792 793
                   s->pixel_format);

794
            return AVERROR(EINVAL);
Luca Barbato's avatar
Luca Barbato committed
795
        }
796
    }
Luca Abeni's avatar
Luca Abeni committed
797

798 799 800
    if (!s->width && !s->height) {
        struct v4l2_format fmt;

Luca Barbato's avatar
Luca Barbato committed
801 802
        av_log(s1, AV_LOG_VERBOSE,
               "Querying the device for the current frame size\n");
803 804
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
Tristan Matthews's avatar
Tristan Matthews committed
805
            char errbuf[128];
Luca Barbato's avatar
Luca Barbato committed
806 807
            res = AVERROR(errno);
            av_strerror(res, errbuf, sizeof(errbuf));
Luca Barbato's avatar
Luca Barbato committed
808
            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n",
Tristan Matthews's avatar
Tristan Matthews committed
809
                   errbuf);
Luca Barbato's avatar
Luca Barbato committed
810
            return res;
811
        }
Luca Barbato's avatar
Luca Barbato committed
812

813 814