v4l2.c 19.6 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 10 11 12
 *
 * 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
 * V4L2_PIX_FMT_* and PIX_FMT_*
 *
 *
13 14 15
 * This file is part of FFmpeg.
 *
 * FFmpeg 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
 * FFmpeg 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 FFmpeg; 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"
Luca Abeni's avatar
Luca Abeni committed
33 34 35 36 37
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
38
#if HAVE_SYS_VIDEOIO_H
39 40
#include <sys/videoio.h>
#else
41 42
#include <asm/types.h>
#include <linux/videodev2.h>
43
#endif
Luca Abeni's avatar
Luca Abeni committed
44
#include <time.h>
45
#include <strings.h>
46
#include "libavcore/imgutils.h"
Luca Abeni's avatar
Luca Abeni committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

static const int desired_video_buffers = 256;

enum io_method {
    io_read,
    io_mmap,
    io_userptr
};

struct video_data {
    int fd;
    int frame_format; /* V4L2_PIX_FMT_* */
    enum io_method io_method;
    int width, height;
    int frame_size;
    int top_field_first;

    int buffers;
    void **buf_start;
    unsigned int *buf_len;
};

69 70 71 72 73
struct buff_data {
    int index;
    int fd;
};

Luca Abeni's avatar
Luca Abeni committed
74 75
struct fmt_map {
    enum PixelFormat ff_fmt;
76
    enum CodecID codec_id;
77
    uint32_t v4l2_fmt;
Luca Abeni's avatar
Luca Abeni committed
78 79 80 81 82
};

static struct fmt_map fmt_conversion_table[] = {
    {
        .ff_fmt = PIX_FMT_YUV420P,
83
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
84 85 86 87
        .v4l2_fmt = V4L2_PIX_FMT_YUV420,
    },
    {
        .ff_fmt = PIX_FMT_YUV422P,
88
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
89 90 91
        .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
    },
    {
92
        .ff_fmt = PIX_FMT_YUYV422,
93
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
94 95 96 97
        .v4l2_fmt = V4L2_PIX_FMT_YUYV,
    },
    {
        .ff_fmt = PIX_FMT_UYVY422,
98
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
99 100 101 102
        .v4l2_fmt = V4L2_PIX_FMT_UYVY,
    },
    {
        .ff_fmt = PIX_FMT_YUV411P,
103
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
104 105 106 107
        .v4l2_fmt = V4L2_PIX_FMT_YUV411P,
    },
    {
        .ff_fmt = PIX_FMT_YUV410P,
108
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
109 110
        .v4l2_fmt = V4L2_PIX_FMT_YUV410,
    },
111 112
    {
        .ff_fmt = PIX_FMT_RGB555,
113
        .codec_id = CODEC_ID_RAWVIDEO,
114 115 116 117
        .v4l2_fmt = V4L2_PIX_FMT_RGB555,
    },
    {
        .ff_fmt = PIX_FMT_RGB565,
118
        .codec_id = CODEC_ID_RAWVIDEO,
119 120
        .v4l2_fmt = V4L2_PIX_FMT_RGB565,
    },
Luca Abeni's avatar
Luca Abeni committed
121 122
    {
        .ff_fmt = PIX_FMT_BGR24,
123
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
124 125 126 127
        .v4l2_fmt = V4L2_PIX_FMT_BGR24,
    },
    {
        .ff_fmt = PIX_FMT_RGB24,
128
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
129 130 131
        .v4l2_fmt = V4L2_PIX_FMT_RGB24,
    },
    {
132
        .ff_fmt = PIX_FMT_BGRA,
133
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
134 135 136 137
        .v4l2_fmt = V4L2_PIX_FMT_BGR32,
    },
    {
        .ff_fmt = PIX_FMT_GRAY8,
138
        .codec_id = CODEC_ID_RAWVIDEO,
Luca Abeni's avatar
Luca Abeni committed
139 140
        .v4l2_fmt = V4L2_PIX_FMT_GREY,
    },
141 142 143 144 145
    {
        .ff_fmt = PIX_FMT_NV12,
        .codec_id = CODEC_ID_RAWVIDEO,
        .v4l2_fmt = V4L2_PIX_FMT_NV12,
    },
146 147 148 149 150 151 152 153 154 155
    {
        .ff_fmt = PIX_FMT_NONE,
        .codec_id = CODEC_ID_MJPEG,
        .v4l2_fmt = V4L2_PIX_FMT_MJPEG,
    },
    {
        .ff_fmt = PIX_FMT_NONE,
        .codec_id = CODEC_ID_MJPEG,
        .v4l2_fmt = V4L2_PIX_FMT_JPEG,
    },
Luca Abeni's avatar
Luca Abeni committed
156 157
};

158
static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
Luca Abeni's avatar
Luca Abeni committed
159 160 161
{
    struct v4l2_capability cap;
    int fd;
162
    int res, err;
163
    int flags = O_RDWR;
Luca Abeni's avatar
Luca Abeni committed
164

165 166 167 168
    if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
        flags |= O_NONBLOCK;
    }
    fd = open(ctx->filename, flags, 0);
Luca Abeni's avatar
Luca Abeni committed
169
    if (fd < 0) {
Luca Abeni's avatar
Luca Abeni committed
170
        av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
171
                 ctx->filename, strerror(errno));
Luca Abeni's avatar
Luca Abeni committed
172

173
        return AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
174 175 176
    }

    res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
177
    // ENOIOCTLCMD definition only availble on __KERNEL__
178
    if (res < 0 && ((err = errno) == 515)) {
Luca Abeni's avatar
Luca Abeni committed
179
        av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
180
        close(fd);
181

182
        return AVERROR(515);
183
    }
Luca Abeni's avatar
Luca Abeni committed
184
    if (res < 0) {
Luca Abeni's avatar
Luca Abeni committed
185
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
Luca Abeni's avatar
Luca Abeni committed
186
                 strerror(errno));
187
        close(fd);
Luca Abeni's avatar
Luca Abeni committed
188

189
        return AVERROR(err);
Luca Abeni's avatar
Luca Abeni committed
190 191
    }
    if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
Luca Abeni's avatar
Luca Abeni committed
192
        av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
193
        close(fd);
Luca Abeni's avatar
Luca Abeni committed
194

195
        return AVERROR(ENODEV);
Luca Abeni's avatar
Luca Abeni committed
196 197 198 199 200 201
    }
    *capabilities = cap.capabilities;

    return fd;
}

202
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pix_fmt)
Luca Abeni's avatar
Luca Abeni committed
203
{
Luca Abeni's avatar
Luca Abeni committed
204 205
    struct video_data *s = ctx->priv_data;
    int fd = s->fd;
Luca Abeni's avatar
Luca Abeni committed
206
    struct v4l2_format fmt;
207
    int res;
Luca Abeni's avatar
Luca Abeni committed
208 209 210

    memset(&fmt, 0, sizeof(struct v4l2_format));
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
211 212
    fmt.fmt.pix.width = *width;
    fmt.fmt.pix.height = *height;
Luca Abeni's avatar
Luca Abeni committed
213 214
    fmt.fmt.pix.pixelformat = pix_fmt;
    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
215 216
    res = ioctl(fd, VIDIOC_S_FMT, &fmt);
    if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
Luca Abeni's avatar
Luca Abeni committed
217
        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);
218 219 220 221
        *width = fmt.fmt.pix.width;
        *height = fmt.fmt.pix.height;
    }

222 223 224 225 226
    if (pix_fmt != fmt.fmt.pix.pixelformat) {
        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);
        res = -1;
    }

227
    return res;
Luca Abeni's avatar
Luca Abeni committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
}

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

246
static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt, enum CodecID codec_id)
Luca Abeni's avatar
Luca Abeni committed
247 248 249
{
    int i;

250
    for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
251 252 253 254
        if ((codec_id == CODEC_ID_NONE ||
             fmt_conversion_table[i].codec_id == codec_id) &&
            (pix_fmt == PIX_FMT_NONE ||
             fmt_conversion_table[i].ff_fmt == pix_fmt)) {
Luca Abeni's avatar
Luca Abeni committed
255 256 257 258 259 260 261
            return fmt_conversion_table[i].v4l2_fmt;
        }
    }

    return 0;
}

262
static enum PixelFormat fmt_v4l2ff(uint32_t v4l2_fmt, enum CodecID codec_id)
Luca Abeni's avatar
Luca Abeni committed
263 264 265
{
    int i;

266
    for (i = 0; i < FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
267 268
        if (fmt_conversion_table[i].v4l2_fmt == v4l2_fmt &&
            fmt_conversion_table[i].codec_id == codec_id) {
Luca Abeni's avatar
Luca Abeni committed
269 270 271 272
            return fmt_conversion_table[i].ff_fmt;
        }
    }

273
    return PIX_FMT_NONE;
Luca Abeni's avatar
Luca Abeni committed
274 275
}

276 277 278 279 280 281 282 283 284 285 286 287 288
static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt)
{
    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;
        }
    }

    return CODEC_ID_NONE;
}

Luca Abeni's avatar
Luca Abeni committed
289
static int mmap_init(AVFormatContext *ctx)
Luca Abeni's avatar
Luca Abeni committed
290
{
Luca Abeni's avatar
Luca Abeni committed
291
    struct video_data *s = ctx->priv_data;
Luca Abeni's avatar
Luca Abeni committed
292 293 294 295 296 297 298 299 300 301
    struct v4l2_requestbuffers req;
    int i, res;

    memset(&req, 0, sizeof(struct v4l2_requestbuffers));
    req.count = desired_video_buffers;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;
    res = ioctl (s->fd, VIDIOC_REQBUFS, &req);
    if (res < 0) {
        if (errno == EINVAL) {
Luca Abeni's avatar
Luca Abeni committed
302
            av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
Luca Abeni's avatar
Luca Abeni committed
303
        } else {
Luca Abeni's avatar
Luca Abeni committed
304
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
Luca Abeni's avatar
Luca Abeni committed
305 306
        }

307
        return AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
308 309 310
    }

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

313
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
314 315 316 317
    }
    s->buffers = req.count;
    s->buf_start = av_malloc(sizeof(void *) * s->buffers);
    if (s->buf_start == NULL) {
Luca Abeni's avatar
Luca Abeni committed
318
        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
Luca Abeni's avatar
Luca Abeni committed
319

320
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
321 322 323
    }
    s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
    if (s->buf_len == NULL) {
Luca Abeni's avatar
Luca Abeni committed
324
        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
Luca Abeni's avatar
Luca Abeni committed
325 326
        av_free(s->buf_start);

327
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
328 329 330 331 332 333 334 335 336 337 338
    }

    for (i = 0; i < req.count; i++) {
        struct v4l2_buffer buf;

        memset(&buf, 0, sizeof(struct v4l2_buffer));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = i;
        res = ioctl (s->fd, VIDIOC_QUERYBUF, &buf);
        if (res < 0) {
Luca Abeni's avatar
Luca Abeni committed
339
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
Luca Abeni's avatar
Luca Abeni committed
340

341
            return AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
342 343 344
        }

        s->buf_len[i] = buf.length;
345
        if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) {
Luca Abeni's avatar
Luca Abeni committed
346
            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
347 348 349 350 351 352

            return -1;
        }
        s->buf_start[i] = mmap (NULL, buf.length,
                        PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
        if (s->buf_start[i] == MAP_FAILED) {
Luca Abeni's avatar
Luca Abeni committed
353
            av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
Luca Abeni's avatar
Luca Abeni committed
354

355
            return AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
356 357 358 359 360 361
        }
    }

    return 0;
}

Luca Abeni's avatar
Luca Abeni committed
362
static int read_init(AVFormatContext *ctx)
Luca Abeni's avatar
Luca Abeni committed
363 364 365 366
{
    return -1;
}

367 368 369 370 371 372
static void mmap_release_buffer(AVPacket *pkt)
{
    struct v4l2_buffer buf;
    int res, fd;
    struct buff_data *buf_descriptor = pkt->priv;

373 374 375 376
    if (pkt->data == NULL) {
         return;
    }

377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
    memset(&buf, 0, sizeof(struct v4l2_buffer));
    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);

    res = ioctl (fd, VIDIOC_QBUF, &buf);
    if (res < 0) {
        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
    }
    pkt->data = NULL;
    pkt->size = 0;
}

static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
Luca Abeni's avatar
Luca Abeni committed
393
{
Luca Abeni's avatar
Luca Abeni committed
394
    struct video_data *s = ctx->priv_data;
Luca Abeni's avatar
Luca Abeni committed
395
    struct v4l2_buffer buf;
396
    struct buff_data *buf_descriptor;
Luca Abeni's avatar
Luca Abeni committed
397 398 399 400 401 402 403
    int res;

    memset(&buf, 0, sizeof(struct v4l2_buffer));
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    /* FIXME: Some special treatment might be needed in case of loss of signal... */
404
    while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
Luca Abeni's avatar
Luca Abeni committed
405
    if (res < 0) {
406 407 408 409 410
        if (errno == EAGAIN) {
            pkt->size = 0;

            return AVERROR(EAGAIN);
        }
Luca Abeni's avatar
Luca Abeni committed
411
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
Luca Abeni's avatar
Luca Abeni committed
412

413
        return AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
414 415
    }
    assert (buf.index < s->buffers);
416
    if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
Luca Abeni's avatar
Luca Abeni committed
417
        av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
418

419
        return AVERROR_INVALIDDATA;
420 421
    }

Luca Abeni's avatar
Luca Abeni committed
422
    /* Image is at s->buff_start[buf.index] */
423 424 425 426 427 428 429 430 431 432 433
    pkt->data= s->buf_start[buf.index];
    pkt->size = buf.bytesused;
    pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
    pkt->destruct = mmap_release_buffer;
    buf_descriptor = av_malloc(sizeof(struct buff_data));
    if (buf_descriptor == NULL) {
        /* Something went wrong... Since av_malloc() failed, we cannot even
         * allocate a buffer for memcopying into it
         */
        av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
        res = ioctl (s->fd, VIDIOC_QBUF, &buf);
Luca Abeni's avatar
Luca Abeni committed
434

435
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
436
    }
437 438 439
    buf_descriptor->fd = s->fd;
    buf_descriptor->index = buf.index;
    pkt->priv = buf_descriptor;
Luca Abeni's avatar
Luca Abeni committed
440 441 442 443

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

444
static int read_frame(AVFormatContext *ctx, AVPacket *pkt)
Luca Abeni's avatar
Luca Abeni committed
445 446 447 448
{
    return -1;
}

Luca Abeni's avatar
Luca Abeni committed
449
static int mmap_start(AVFormatContext *ctx)
Luca Abeni's avatar
Luca Abeni committed
450
{
Luca Abeni's avatar
Luca Abeni committed
451
    struct video_data *s = ctx->priv_data;
Luca Abeni's avatar
Luca Abeni committed
452 453 454 455 456 457 458 459 460 461 462 463 464
    enum v4l2_buf_type type;
    int i, res;

    for (i = 0; i < s->buffers; i++) {
        struct v4l2_buffer buf;

        memset(&buf, 0, sizeof(struct v4l2_buffer));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index  = i;

        res = ioctl (s->fd, VIDIOC_QBUF, &buf);
        if (res < 0) {
Luca Abeni's avatar
Luca Abeni committed
465
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
Luca Abeni's avatar
Luca Abeni committed
466

467
            return AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
468 469 470 471 472 473
        }
    }

    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    res = ioctl (s->fd, VIDIOC_STREAMON, &type);
    if (res < 0) {
Luca Abeni's avatar
Luca Abeni committed
474
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
Luca Abeni's avatar
Luca Abeni committed
475

476
        return AVERROR(errno);
Luca Abeni's avatar
Luca Abeni committed
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
    }

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

499 500 501 502 503 504 505
static int v4l2_set_parameters( AVFormatContext *s1, AVFormatParameters *ap )
{
    struct video_data *s = s1->priv_data;
    struct v4l2_input input;
    struct v4l2_standard standard;
    int i;

506
    if(ap->channel>=0) {
Luca Abeni's avatar
Luca Abeni committed
507 508 509 510 511
        /* set tv video input */
        memset (&input, 0, sizeof (input));
        input.index = ap->channel;
        if(ioctl (s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
            av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
512
            return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
513
        }
514

Luca Abeni's avatar
Luca Abeni committed
515 516 517 518 519
        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
               ap->channel, input.name);
        if(ioctl (s->fd, VIDIOC_S_INPUT, &input.index) < 0 ) {
            av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n",
                   ap->channel);
520
            return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
521
        }
522
    }
523

524
    if(ap->standard) {
Luca Abeni's avatar
Luca Abeni committed
525 526 527 528 529 530 531 532 533
        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
               ap->standard );
        /* set tv standard */
        memset (&standard, 0, sizeof (standard));
        for(i=0;;i++) {
            standard.index = i;
            if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
                av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
                       ap->standard);
534
                return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
535 536 537 538 539 540 541 542
            }

            if(!strcasecmp(standard.name, ap->standard)) {
                break;
            }
        }

        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
543
               ap->standard, (uint64_t)standard.id);
Luca Abeni's avatar
Luca Abeni committed
544
        if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
545 546
            av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
                   ap->standard);
547
            return AVERROR(EIO);
548
        }
549
    }
550 551 552 553

    return 0;
}

554 555 556 557 558
static uint32_t device_try_init(AVFormatContext *s1,
                                const AVFormatParameters *ap,
                                int *width,
                                int *height,
                                enum CodecID *codec_id)
559
{
560
    uint32_t desired_format = fmt_ff2v4l(ap->pix_fmt, s1->video_codec_id);
561 562 563 564 565 566 567

    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++) {
568 569
            if (s1->video_codec_id == CODEC_ID_NONE ||
                fmt_conversion_table[i].codec_id == s1->video_codec_id) {
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
                desired_format = fmt_conversion_table[i].v4l2_fmt;
                if (device_init(s1, width, height, desired_format) >= 0) {
                    break;
                }
                desired_format = 0;
            }
        }
    }
    if (desired_format != 0) {
        *codec_id = fmt_v4l2codec(desired_format);
        assert(*codec_id != CODEC_ID_NONE);
    }

    return desired_format;
}

Luca Abeni's avatar
Luca Abeni committed
586 587 588 589
static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
{
    struct video_data *s = s1->priv_data;
    AVStream *st;
590
    int res;
Luca Abeni's avatar
Luca Abeni committed
591
    uint32_t desired_format, capabilities;
592
    enum CodecID codec_id;
Luca Abeni's avatar
Luca Abeni committed
593 594 595

    st = av_new_stream(s1, 0);
    if (!st) {
596
        return AVERROR(ENOMEM);
Luca Abeni's avatar
Luca Abeni committed
597 598 599
    }
    av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */

600 601
    s->width  = ap->width;
    s->height = ap->height;
Luca Abeni's avatar
Luca Abeni committed
602 603

    capabilities = 0;
604
    s->fd = device_open(s1, &capabilities);
Luca Abeni's avatar
Luca Abeni committed
605
    if (s->fd < 0) {
606
        return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
607
    }
608
    av_log(s1, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", s->fd, capabilities);
Luca Abeni's avatar
Luca Abeni committed
609

610 611 612
    if (!s->width && !s->height) {
        struct v4l2_format fmt;

613
        av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n");
614 615 616 617 618 619 620
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno));
            return AVERROR(errno);
        }
        s->width  = fmt.fmt.pix.width;
        s->height = fmt.fmt.pix.height;
621
        av_log(s1, AV_LOG_VERBOSE, "Setting frame size to %dx%d\n", s->width, s->height);
622 623
    }

624
    desired_format = device_try_init(s1, ap, &s->width, &s->height, &codec_id);
Luca Abeni's avatar
Luca Abeni committed
625
    if (desired_format == 0) {
626
        av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
627
               "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, ap->pix_fmt);
Luca Abeni's avatar
Luca Abeni committed
628 629
        close(s->fd);

630
        return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
631
    }
632
    if (av_image_check_size(s->width, s->height, 0, s1) < 0)
633
        return AVERROR(EINVAL);
Luca Abeni's avatar
Luca Abeni committed
634 635
    s->frame_format = desired_format;

636
    if( v4l2_set_parameters( s1, ap ) < 0 )
637
        return AVERROR(EIO);
638

639
    st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id);
640
    s->frame_size = avpicture_get_size(st->codec->pix_fmt, s->width, s->height);
Luca Abeni's avatar
Luca Abeni committed
641 642
    if (capabilities & V4L2_CAP_STREAMING) {
        s->io_method = io_mmap;
Luca Abeni's avatar
Luca Abeni committed
643
        res = mmap_init(s1);
R. Brian Anderson's avatar
R. Brian Anderson committed
644
        if (res == 0) {
Luca Abeni's avatar
Luca Abeni committed
645
            res = mmap_start(s1);
R. Brian Anderson's avatar
R. Brian Anderson committed
646
        }
Luca Abeni's avatar
Luca Abeni committed
647 648
    } else {
        s->io_method = io_read;
Luca Abeni's avatar
Luca Abeni committed
649
        res = read_init(s1);
Luca Abeni's avatar
Luca Abeni committed
650 651 652 653
    }
    if (res < 0) {
        close(s->fd);

654
        return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
655 656 657
    }
    s->top_field_first = first_field(s->fd);

658
    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
659
    st->codec->codec_id = codec_id;
660 661
    st->codec->width = s->width;
    st->codec->height = s->height;
662 663
    st->codec->time_base.den = ap->time_base.den;
    st->codec->time_base.num = ap->time_base.num;
Luca Abeni's avatar
Luca Abeni committed
664 665 666 667 668 669 670 671 672 673 674
    st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;

    return 0;
}

static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
    struct video_data *s = s1->priv_data;
    int res;

    if (s->io_method == io_mmap) {
675 676
        av_init_packet(pkt);
        res = mmap_read_frame(s1, pkt);
Luca Abeni's avatar
Luca Abeni committed
677
    } else if (s->io_method == io_read) {
678
        if (av_new_packet(pkt, s->frame_size) < 0)
679
            return AVERROR(EIO);
680 681

        res = read_frame(s1, pkt);
Luca Abeni's avatar
Luca Abeni committed
682
    } else {
683
        return AVERROR(EIO);
Luca Abeni's avatar
Luca Abeni committed
684 685
    }
    if (res < 0) {
686
        return res;
Luca Abeni's avatar
Luca Abeni committed
687 688 689 690 691 692 693
    }

    if (s1->streams[0]->codec->coded_frame) {
        s1->streams[0]->codec->coded_frame->interlaced_frame = 1;
        s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first;
    }

694
    return pkt->size;
Luca Abeni's avatar
Luca Abeni committed
695 696 697 698 699 700 701 702 703 704 705 706 707 708
}

static int v4l2_read_close(AVFormatContext *s1)
{
    struct video_data *s = s1->priv_data;

    if (s->io_method == io_mmap) {
        mmap_close(s);
    }

    close(s->fd);
    return 0;
}

709
AVInputFormat v4l2_demuxer = {
Luca Abeni's avatar
Luca Abeni committed
710
    "video4linux2",
711
    NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
Luca Abeni's avatar
Luca Abeni committed
712 713 714 715 716 717 718
    sizeof(struct video_data),
    NULL,
    v4l2_read_header,
    v4l2_read_packet,
    v4l2_read_close,
    .flags = AVFMT_NOFILE,
};