v4l2.c 28.7 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 Barbato's avatar
Luca Barbato committed
114 115 116
#ifdef V4L2_PIX_FMT_H264
    { AV_PIX_FMT_NONE,    AV_CODEC_ID_H264,     V4L2_PIX_FMT_H264    },
#endif
Luca Abeni's avatar
Luca Abeni committed
117 118
};

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

127 128 129
    if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
        flags |= O_NONBLOCK;
    }
Luca Barbato's avatar
Luca Barbato committed
130

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

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

Tristan Matthews's avatar
Tristan Matthews committed
139
        return err;
Luca Abeni's avatar
Luca Abeni committed
140 141 142 143
    }

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

Luca Barbato's avatar
Luca Barbato committed
149
        goto fail;
Luca Abeni's avatar
Luca Abeni committed
150
    }
Luca Barbato's avatar
Luca Barbato committed
151

Luca Barbato's avatar
Luca Barbato committed
152 153 154 155 156
    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
157
        err = AVERROR(ENODEV);
Luca Abeni's avatar
Luca Abeni committed
158

Luca Barbato's avatar
Luca Barbato committed
159
        goto fail;
Luca Abeni's avatar
Luca Abeni committed
160
    }
Luca Barbato's avatar
Luca Barbato committed
161

Luca Barbato's avatar
Luca Barbato committed
162 163 164
    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
165
        err = AVERROR(ENOSYS);
Luca Barbato's avatar
Luca Barbato committed
166 167 168

        goto fail;
    }
Luca Abeni's avatar
Luca Abeni committed
169 170

    return fd;
Luca Barbato's avatar
Luca Barbato committed
171 172 173

fail:
    close(fd);
Luca Barbato's avatar
Luca Barbato committed
174
    return err;
Luca Abeni's avatar
Luca Abeni committed
175 176
}

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

185
    int res;
Luca Abeni's avatar
Luca Abeni committed
186

Luca Barbato's avatar
Luca Barbato committed
187 188 189 190 191
    pix->width = *width;
    pix->height = *height;
    pix->pixelformat = pix_fmt;
    pix->field = V4L2_FIELD_ANY;

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

194
    if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
Luca Barbato's avatar
Luca Barbato committed
195 196 197
        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);
198 199 200 201
        *width = fmt.fmt.pix.width;
        *height = fmt.fmt.pix.height;
    }

202
    if (pix_fmt != fmt.fmt.pix.pixelformat) {
Luca Barbato's avatar
Luca Barbato committed
203 204 205 206
        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);
207 208 209
        res = -1;
    }

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

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

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;
}

234
static uint32_t fmt_ff2v4l(enum AVPixelFormat pix_fmt, enum AVCodecID codec_id)
Luca Abeni's avatar
Luca Abeni committed
235 236 237
{
    int i;

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

    return 0;
}

250
static enum AVPixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum AVCodecID codec_id)
Luca Abeni's avatar
Luca Abeni committed
251 252 253
{
    int i;

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

261
    return AV_PIX_FMT_NONE;
Luca Abeni's avatar
Luca Abeni committed
262 263
}

264
static enum AVCodecID fmt_v4l2codec(uint32_t v4l2_fmt)
265 266 267 268 269 270 271 272 273
{
    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;
        }
    }

274
    return AV_CODEC_ID_NONE;
275 276
}

Luca Barbato's avatar
Luca Barbato committed
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 305 306 307
#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)) {
308
        enum AVCodecID codec_id = fmt_v4l2codec(vfd.pixelformat);
309
        enum AVPixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id);
Luca Barbato's avatar
Luca Barbato committed
310 311 312 313 314 315 316 317 318 319 320

        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) {
321
            const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
Luca Barbato's avatar
Luca Barbato committed
322
            av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :",
323
                   desc ? desc->name : "Unsupported",
Luca Barbato's avatar
Luca Barbato committed
324 325 326 327 328
                   vfd.description);
        } else {
            continue;
        }

329
#ifdef V4L2_FMT_FLAG_EMULATED
Luca Barbato's avatar
Luca Barbato committed
330 331 332 333
        if (vfd.flags & V4L2_FMT_FLAG_EMULATED) {
            av_log(ctx, AV_LOG_WARNING, "%s", "Emulated");
            continue;
        }
334
#endif
Luca Barbato's avatar
Luca Barbato committed
335 336 337 338 339 340 341
#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
342
static int mmap_init(AVFormatContext *ctx)
Luca Abeni's avatar
Luca Abeni committed
343 344
{
    int i, res;
345 346 347 348 349 350
    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
351

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

361
        return res;
Luca Abeni's avatar
Luca Abeni committed
362 363 364
    }

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

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

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

381
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
382 383 384
    }

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

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

Luca Barbato's avatar
Luca Barbato committed
396
            return res;
Luca Abeni's avatar
Luca Abeni committed
397 398 399
        }

        s->buf_len[i] = buf.length;
400
        if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
Luca Barbato's avatar
Luca Barbato committed
401 402 403
            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
404 405 406

            return -1;
        }
Luca Barbato's avatar
Luca Barbato committed
407 408 409 410
        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
411
        if (s->buf_start[i] == MAP_FAILED) {
Tristan Matthews's avatar
Tristan Matthews committed
412
            char errbuf[128];
Luca Barbato's avatar
Luca Barbato committed
413 414
            res = AVERROR(errno);
            av_strerror(res, errbuf, sizeof(errbuf));
Tristan Matthews's avatar
Tristan Matthews committed
415
            av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", errbuf);
Luca Abeni's avatar
Luca Abeni committed
416

Luca Barbato's avatar
Luca Barbato committed
417
            return res;
Luca Abeni's avatar
Luca Abeni committed
418 419 420 421 422 423
        }
    }

    return 0;
}

424 425 426 427 428 429 430 431
#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)
432
{
433
    struct v4l2_buffer buf = { 0 };
434
    int res, fd;
435 436
    struct buff_data *buf_descriptor = opaque;
    struct video_data *s = buf_descriptor->s;
Tristan Matthews's avatar
Tristan Matthews committed
437
    char errbuf[128];
438

439 440 441 442 443 444
    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);

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

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

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

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

Luca Barbato's avatar
Luca Barbato committed
485
        return res;
Luca Abeni's avatar
Luca Abeni committed
486
    }
487 488 489 490 491

    if (buf.index >= s->buffers) {
        av_log(ctx, AV_LOG_ERROR, "Invalid buffer index received.\n");
        return AVERROR(EINVAL);
    }
492 493 494
    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);
495

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

501
        return AVERROR_INVALIDDATA;
502 503
    }

Luca Abeni's avatar
Luca Abeni committed
504
    /* Image is at s->buff_start[buf.index] */
505
    if (avpriv_atomic_int_get(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) {
Diego Biurrun's avatar
Diego Biurrun committed
506
        /* when we start getting low on queued buffers, fall back on copying data */
507 508 509 510 511 512 513
        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);

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

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

        buf_descriptor = av_malloc(sizeof(struct buff_data));
534
        if (!buf_descriptor) {
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
            /* 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
553
    }
554
    pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
Luca Abeni's avatar
Luca Abeni committed
555 556 557 558

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

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

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

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

Tristan Matthews's avatar
Tristan Matthews committed
580
            return err;
Luca Abeni's avatar
Luca Abeni committed
581 582
        }
    }
583
    s->buffers_queued = s->buffers;
Luca Abeni's avatar
Luca Abeni committed
584 585

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

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

    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);
}

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

626 627
    streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

Luca Barbato's avatar
Luca Barbato committed
628 629 630 631
    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);
632 633
        return ret;
    }
634

Anton Khirnov's avatar
Anton Khirnov committed
635 636 637 638 639 640
    /* 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);
    }
641

Anton Khirnov's avatar
Anton Khirnov committed
642 643 644
    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
645 646
        av_log(s1, AV_LOG_ERROR,
               "The V4L2 driver ioctl set input(%d) failed\n",
Anton Khirnov's avatar
Anton Khirnov committed
647 648 649
                s->channel);
        return AVERROR(EIO);
    }
650

651
    if (s->standard) {
Luca Abeni's avatar
Luca Abeni committed
652
        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
653
               s->standard);
Luca Abeni's avatar
Luca Abeni committed
654 655 656 657
        /* 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
658 659
                av_log(s1, AV_LOG_ERROR,
                       "The V4L2 driver ioctl set standard(%s) failed\n",
660
                       s->standard);
661
                return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
662 663
            }

664
            if (!av_strcasecmp(standard.name, s->standard)) {
Luca Abeni's avatar
Luca Abeni committed
665 666 667 668
                break;
            }
        }

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

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

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

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

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

718 719 720
    return 0;
}

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

    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++) {
735
            if (s1->video_codec_id == AV_CODEC_ID_NONE ||
736
                fmt_conversion_table[i].codec_id == s1->video_codec_id) {
737 738 739 740 741 742 743 744
                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
745

746 747
    if (desired_format != 0) {
        *codec_id = fmt_v4l2codec(desired_format);
748
        assert(*codec_id != AV_CODEC_ID_NONE);
749 750 751 752 753
    }

    return desired_format;
}

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

763
    st = avformat_new_stream(s1, NULL);
764 765
    if (!st)
        return AVERROR(ENOMEM);
Luca Barbato's avatar
Luca Barbato committed
766

Luca Barbato's avatar
Luca Barbato committed
767
    s->fd = device_open(s1);
768 769
    if (s->fd < 0)
        return s->fd;
Luca Barbato's avatar
Luca Barbato committed
770

Luca Barbato's avatar
Luca Barbato committed
771 772
    if (s->list_format) {
        list_formats(s1, s->fd, s->list_format);
773
        return AVERROR_EXIT;
Luca Barbato's avatar
Luca Barbato committed
774 775
    }

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

Luca Barbato's avatar
Luca Barbato committed
778 779 780 781
    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);
782
        return res;
783
    }
Luca Barbato's avatar
Luca Barbato committed
784 785

    if (s->pixel_format) {
786 787
        AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format);

Luca Barbato's avatar
Luca Barbato committed
788
        if (codec) {
789
            s1->video_codec_id = codec->id;
Luca Barbato's avatar
Luca Barbato committed
790 791
            st->need_parsing   = AVSTREAM_PARSE_HEADERS;
        }
Luca Barbato's avatar
Luca Barbato committed
792 793 794

        pix_fmt = av_get_pix_fmt(s->pixel_format);

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

799
            return AVERROR(EINVAL);
Luca Barbato's avatar
Luca Barbato committed
800
        }
801
    }
Luca Abeni's avatar
Luca Abeni committed
802

803 804 805
    if (!s->width && !s->height) {
        struct v4l2_format fmt;

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

818 819
        s->width  = fmt.fmt.pix.width;
        s->height = fmt.fmt.pix.height;
Luca Barbato's avatar
Luca Barbato committed
820 821
        av_log(s1, AV_LOG_VERBOSE,
               "Setting frame size to %dx%d\n", s->width, s->height);
822 823
    }

Luca Barbato's avatar
Luca Barbato committed
824 825
    desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height,
                                     &codec_id);
Luca Abeni's avatar
Luca Abeni committed
826
    if (desired_format == 0) {
827
        av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
828
               "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt);
Luca Abeni's avatar
Luca Abeni committed
829 830
        close(s->fd);

831
        return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
832
    }