Statistics
| Branch: | Revision:

ffmpeg / libavdevice / v4l2.c @ 1b6e8b73

History | View | Annotate | Download (17.2 KB)

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

    
30
#undef __STRICT_ANSI__ //workaround due to broken kernel headers
31
#include "config.h"
32
#include "libavformat/avformat.h"
33
#include <unistd.h>
34
#include <fcntl.h>
35
#include <sys/ioctl.h>
36
#include <sys/mman.h>
37
#include <sys/time.h>
38
#ifdef HAVE_SYS_VIDEOIO_H
39
#include <sys/videoio.h>
40
#else
41
#include <asm/types.h>
42
#include <linux/videodev2.h>
43
#endif
44
#include <time.h>
45
#include <strings.h>
46

    
47
static const int desired_video_buffers = 256;
48

    
49
enum io_method {
50
    io_read,
51
    io_mmap,
52
    io_userptr
53
};
54

    
55
struct video_data {
56
    int fd;
57
    int frame_format; /* V4L2_PIX_FMT_* */
58
    enum io_method io_method;
59
    int width, height;
60
    int frame_rate;
61
    int frame_rate_base;
62
    int frame_size;
63
    int top_field_first;
64

    
65
    int buffers;
66
    void **buf_start;
67
    unsigned int *buf_len;
68
};
69

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

    
75
struct fmt_map {
76
    enum PixelFormat ff_fmt;
77
    int32_t v4l2_fmt;
78
};
79

    
80
static struct fmt_map fmt_conversion_table[] = {
81
    {
82
        .ff_fmt = PIX_FMT_YUV420P,
83
        .v4l2_fmt = V4L2_PIX_FMT_YUV420,
84
    },
85
    {
86
        .ff_fmt = PIX_FMT_YUV422P,
87
        .v4l2_fmt = V4L2_PIX_FMT_YUV422P,
88
    },
89
    {
90
        .ff_fmt = PIX_FMT_YUYV422,
91
        .v4l2_fmt = V4L2_PIX_FMT_YUYV,
92
    },
93
    {
94
        .ff_fmt = PIX_FMT_UYVY422,
95
        .v4l2_fmt = V4L2_PIX_FMT_UYVY,
96
    },
97
    {
98
        .ff_fmt = PIX_FMT_YUV411P,
99
        .v4l2_fmt = V4L2_PIX_FMT_YUV411P,
100
    },
101
    {
102
        .ff_fmt = PIX_FMT_YUV410P,
103
        .v4l2_fmt = V4L2_PIX_FMT_YUV410,
104
    },
105
    {
106
        .ff_fmt = PIX_FMT_RGB555,
107
        .v4l2_fmt = V4L2_PIX_FMT_RGB555,
108
    },
109
    {
110
        .ff_fmt = PIX_FMT_RGB565,
111
        .v4l2_fmt = V4L2_PIX_FMT_RGB565,
112
    },
113
    {
114
        .ff_fmt = PIX_FMT_BGR24,
115
        .v4l2_fmt = V4L2_PIX_FMT_BGR24,
116
    },
117
    {
118
        .ff_fmt = PIX_FMT_RGB24,
119
        .v4l2_fmt = V4L2_PIX_FMT_RGB24,
120
    },
121
    {
122
        .ff_fmt = PIX_FMT_BGRA,
123
        .v4l2_fmt = V4L2_PIX_FMT_BGR32,
124
    },
125
    {
126
        .ff_fmt = PIX_FMT_GRAY8,
127
        .v4l2_fmt = V4L2_PIX_FMT_GREY,
128
    },
129
};
130

    
131
static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
132
{
133
    struct v4l2_capability cap;
134
    int fd;
135
    int res;
136
    int flags = O_RDWR;
137

    
138
    if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
139
        flags |= O_NONBLOCK;
140
    }
141
    fd = open(ctx->filename, flags, 0);
142
    if (fd < 0) {
143
        av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
144
                 ctx->filename, strerror(errno));
145

    
146
        return -1;
147
    }
148

    
149
    res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
150
    // ENOIOCTLCMD definition only availble on __KERNEL__
151
    if (res < 0 && errno == 515)
152
    {
153
        av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
154
        close(fd);
155

    
156
        return -1;
157
    }
158
    if (res < 0) {
159
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
160
                 strerror(errno));
161
        close(fd);
162

    
163
        return -1;
164
    }
165
    if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
166
        av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
167
        close(fd);
168

    
169
        return -1;
170
    }
171
    *capabilities = cap.capabilities;
172

    
173
    return fd;
174
}
175

    
176
static int device_init(AVFormatContext *ctx, int *width, int *height, int pix_fmt)
177
{
178
    struct video_data *s = ctx->priv_data;
179
    int fd = s->fd;
180
    struct v4l2_format fmt;
181
    int res;
182

    
183
    memset(&fmt, 0, sizeof(struct v4l2_format));
184
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
185
    fmt.fmt.pix.width = *width;
186
    fmt.fmt.pix.height = *height;
187
    fmt.fmt.pix.pixelformat = pix_fmt;
188
    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
189
    res = ioctl(fd, VIDIOC_S_FMT, &fmt);
190
    if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
191
        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);
192
        *width = fmt.fmt.pix.width;
193
        *height = fmt.fmt.pix.height;
194
    }
195

    
196
    return res;
197
}
198

    
199
static int first_field(int fd)
200
{
201
    int res;
202
    v4l2_std_id std;
203

    
204
    res = ioctl(fd, VIDIOC_G_STD, &std);
205
    if (res < 0) {
206
        return 0;
207
    }
208
    if (std & V4L2_STD_NTSC) {
209
        return 0;
210
    }
211

    
212
    return 1;
213
}
214

    
215
static uint32_t fmt_ff2v4l(enum PixelFormat pix_fmt)
216
{
217
    int i;
218

    
219
    for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
220
        if (fmt_conversion_table[i].ff_fmt == pix_fmt) {
221
            return fmt_conversion_table[i].v4l2_fmt;
222
        }
223
    }
224

    
225
    return 0;
226
}
227

    
228
static enum PixelFormat fmt_v4l2ff(uint32_t pix_fmt)
229
{
230
    int i;
231

    
232
    for (i = 0; i < sizeof(fmt_conversion_table) / sizeof(struct fmt_map); i++) {
233
        if (fmt_conversion_table[i].v4l2_fmt == pix_fmt) {
234
            return fmt_conversion_table[i].ff_fmt;
235
        }
236
    }
237

    
238
    return PIX_FMT_NONE;
239
}
240

    
241
static int mmap_init(AVFormatContext *ctx)
242
{
243
    struct video_data *s = ctx->priv_data;
244
    struct v4l2_requestbuffers req;
245
    int i, res;
246

    
247
    memset(&req, 0, sizeof(struct v4l2_requestbuffers));
248
    req.count = desired_video_buffers;
249
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
250
    req.memory = V4L2_MEMORY_MMAP;
251
    res = ioctl (s->fd, VIDIOC_REQBUFS, &req);
252
    if (res < 0) {
253
        if (errno == EINVAL) {
254
            av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
255
        } else {
256
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_REQBUFS)\n");
257
        }
258

    
259
        return -1;
260
    }
261

    
262
    if (req.count < 2) {
263
        av_log(ctx, AV_LOG_ERROR, "Insufficient buffer memory\n");
264

    
265
        return -1;
266
    }
267
    s->buffers = req.count;
268
    s->buf_start = av_malloc(sizeof(void *) * s->buffers);
269
    if (s->buf_start == NULL) {
270
        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n");
271

    
272
        return -1;
273
    }
274
    s->buf_len = av_malloc(sizeof(unsigned int) * s->buffers);
275
    if (s->buf_len == NULL) {
276
        av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n");
277
        av_free(s->buf_start);
278

    
279
        return -1;
280
    }
281

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

    
285
        memset(&buf, 0, sizeof(struct v4l2_buffer));
286
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
287
        buf.memory = V4L2_MEMORY_MMAP;
288
        buf.index = i;
289
        res = ioctl (s->fd, VIDIOC_QUERYBUF, &buf);
290
        if (res < 0) {
291
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
292

    
293
            return -1;
294
        }
295

    
296
        s->buf_len[i] = buf.length;
297
        if (s->buf_len[i] < s->frame_size) {
298
            av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size);
299

    
300
            return -1;
301
        }
302
        s->buf_start[i] = mmap (NULL, buf.length,
303
                        PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
304
        if (s->buf_start[i] == MAP_FAILED) {
305
            av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
306

    
307
            return -1;
308
        }
309
    }
310

    
311
    return 0;
312
}
313

    
314
static int read_init(AVFormatContext *ctx)
315
{
316
    return -1;
317
}
318

    
319
static void mmap_release_buffer(AVPacket *pkt)
320
{
321
    struct v4l2_buffer buf;
322
    int res, fd;
323
    struct buff_data *buf_descriptor = pkt->priv;
324

    
325
    memset(&buf, 0, sizeof(struct v4l2_buffer));
326
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
327
    buf.memory = V4L2_MEMORY_MMAP;
328
    buf.index = buf_descriptor->index;
329
    fd = buf_descriptor->fd;
330
    av_free(buf_descriptor);
331

    
332
    res = ioctl (fd, VIDIOC_QBUF, &buf);
333
    if (res < 0) {
334
        av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF)\n");
335
    }
336
    pkt->data = NULL;
337
    pkt->size = 0;
338
}
339

    
340
static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
341
{
342
    struct video_data *s = ctx->priv_data;
343
    struct v4l2_buffer buf;
344
    struct buff_data *buf_descriptor;
345
    int res;
346

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

    
351
    /* FIXME: Some special treatment might be needed in case of loss of signal... */
352
    while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
353
    if (res < 0) {
354
        if (errno == EAGAIN) {
355
            pkt->size = 0;
356

    
357
            return AVERROR(EAGAIN);
358
        }
359
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno));
360

    
361
        return -1;
362
    }
363
    assert (buf.index < s->buffers);
364
    if (buf.bytesused != s->frame_size) {
365
        av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size);
366

    
367
        return -1;
368
    }
369

    
370
    /* Image is at s->buff_start[buf.index] */
371
    pkt->data= s->buf_start[buf.index];
372
    pkt->size = buf.bytesused;
373
    pkt->pts = buf.timestamp.tv_sec * INT64_C(1000000) + buf.timestamp.tv_usec;
374
    pkt->destruct = mmap_release_buffer;
375
    buf_descriptor = av_malloc(sizeof(struct buff_data));
376
    if (buf_descriptor == NULL) {
377
        /* Something went wrong... Since av_malloc() failed, we cannot even
378
         * allocate a buffer for memcopying into it
379
         */
380
        av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
381
        res = ioctl (s->fd, VIDIOC_QBUF, &buf);
382

    
383
        return -1;
384
    }
385
    buf_descriptor->fd = s->fd;
386
    buf_descriptor->index = buf.index;
387
    pkt->priv = buf_descriptor;
388

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

    
392
static int read_frame(AVFormatContext *ctx, AVPacket *pkt)
393
{
394
    return -1;
395
}
396

    
397
static int mmap_start(AVFormatContext *ctx)
398
{
399
    struct video_data *s = ctx->priv_data;
400
    enum v4l2_buf_type type;
401
    int i, res;
402

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

    
406
        memset(&buf, 0, sizeof(struct v4l2_buffer));
407
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
408
        buf.memory = V4L2_MEMORY_MMAP;
409
        buf.index  = i;
410

    
411
        res = ioctl (s->fd, VIDIOC_QBUF, &buf);
412
        if (res < 0) {
413
            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
414

    
415
            return -1;
416
        }
417
    }
418

    
419
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
420
    res = ioctl (s->fd, VIDIOC_STREAMON, &type);
421
    if (res < 0) {
422
        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
423

    
424
        return -1;
425
    }
426

    
427
    return 0;
428
}
429

    
430
static void mmap_close(struct video_data *s)
431
{
432
    enum v4l2_buf_type type;
433
    int i;
434

    
435
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
436
    /* We do not check for the result, because we could
437
     * not do anything about it anyway...
438
     */
439
    ioctl(s->fd, VIDIOC_STREAMOFF, &type);
440
    for (i = 0; i < s->buffers; i++) {
441
        munmap(s->buf_start[i], s->buf_len[i]);
442
    }
443
    av_free(s->buf_start);
444
    av_free(s->buf_len);
445
}
446

    
447
static int v4l2_set_parameters( AVFormatContext *s1, AVFormatParameters *ap )
448
{
449
    struct video_data *s = s1->priv_data;
450
    struct v4l2_input input;
451
    struct v4l2_standard standard;
452
    int i;
453

    
454
    if(ap->channel>=0) {
455
        /* set tv video input */
456
        memset (&input, 0, sizeof (input));
457
        input.index = ap->channel;
458
        if(ioctl (s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
459
            av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
460
            return AVERROR(EIO);
461
        }
462

    
463
        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
464
               ap->channel, input.name);
465
        if(ioctl (s->fd, VIDIOC_S_INPUT, &input.index) < 0 ) {
466
            av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n",
467
                   ap->channel);
468
            return AVERROR(EIO);
469
        }
470
    }
471

    
472
    if(ap->standard) {
473
        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n",
474
               ap->standard );
475
        /* set tv standard */
476
        memset (&standard, 0, sizeof (standard));
477
        for(i=0;;i++) {
478
            standard.index = i;
479
            if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) {
480
                av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
481
                       ap->standard);
482
                return AVERROR(EIO);
483
            }
484

    
485
            if(!strcasecmp(standard.name, ap->standard)) {
486
                break;
487
            }
488
        }
489

    
490
        av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
491
               ap->standard, standard.id);
492
        if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
493
            av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
494
                   ap->standard);
495
            return AVERROR(EIO);
496
        }
497
    }
498

    
499
    return 0;
500
}
501

    
502
static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
503
{
504
    struct video_data *s = s1->priv_data;
505
    AVStream *st;
506
    int width, height;
507
    int res, frame_rate, frame_rate_base;
508
    uint32_t desired_format, capabilities;
509

    
510
    if (ap->width <= 0 || ap->height <= 0) {
511
        av_log(s1, AV_LOG_ERROR, "Wrong size (%dx%d)\n", ap->width, ap->height);
512
        return -1;
513
    }
514
    if (ap->time_base.den <= 0) {
515
        av_log(s1, AV_LOG_ERROR, "Wrong time base (%d)\n", ap->time_base.den);
516
        return -1;
517
    }
518

    
519
    width = ap->width;
520
    height = ap->height;
521
    frame_rate = ap->time_base.den;
522
    frame_rate_base = ap->time_base.num;
523

    
524
    if((unsigned)width > 32767 || (unsigned)height > 32767) {
525
        av_log(s1, AV_LOG_ERROR, "Wrong size (%dx%d)\n", width, height);
526

    
527
        return -1;
528
    }
529

    
530
    st = av_new_stream(s1, 0);
531
    if (!st) {
532
        return AVERROR(ENOMEM);
533
    }
534
    av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
535

    
536
    s->width = width;
537
    s->height = height;
538
    s->frame_rate      = frame_rate;
539
    s->frame_rate_base = frame_rate_base;
540

    
541
    capabilities = 0;
542
    s->fd = device_open(s1, &capabilities);
543
    if (s->fd < 0) {
544
        return AVERROR(EIO);
545
    }
546
    av_log(s1, AV_LOG_INFO, "[%d]Capabilities: %x\n", s->fd, capabilities);
547

    
548
    desired_format = fmt_ff2v4l(ap->pix_fmt);
549
    if (desired_format == 0 || (device_init(s1, &width, &height, desired_format) < 0)) {
550
        int i, done;
551

    
552
        done = 0; i = 0;
553
        while (!done) {
554
            desired_format = fmt_conversion_table[i].v4l2_fmt;
555
            if (device_init(s1, &width, &height, desired_format) < 0) {
556
                desired_format = 0;
557
                i++;
558
            } else {
559
               done = 1;
560
            }
561
            if (i == sizeof(fmt_conversion_table) / sizeof(struct fmt_map)) {
562
               done = 1;
563
            }
564
        }
565
    }
566
    if (desired_format == 0) {
567
        av_log(s1, AV_LOG_ERROR, "Cannot find a proper format.\n");
568
        close(s->fd);
569

    
570
        return AVERROR(EIO);
571
    }
572
    s->frame_format = desired_format;
573

    
574
    if( v4l2_set_parameters( s1, ap ) < 0 )
575
        return AVERROR(EIO);
576

    
577
    st->codec->pix_fmt = fmt_v4l2ff(desired_format);
578
    s->frame_size = avpicture_get_size(st->codec->pix_fmt, width, height);
579
    if (capabilities & V4L2_CAP_STREAMING) {
580
        s->io_method = io_mmap;
581
        res = mmap_init(s1);
582
        if (res == 0) {
583
            res = mmap_start(s1);
584
        }
585
    } else {
586
        s->io_method = io_read;
587
        res = read_init(s1);
588
    }
589
    if (res < 0) {
590
        close(s->fd);
591

    
592
        return AVERROR(EIO);
593
    }
594
    s->top_field_first = first_field(s->fd);
595

    
596
    st->codec->codec_type = CODEC_TYPE_VIDEO;
597
    st->codec->codec_id = CODEC_ID_RAWVIDEO;
598
    st->codec->width = width;
599
    st->codec->height = height;
600
    st->codec->time_base.den = frame_rate;
601
    st->codec->time_base.num = frame_rate_base;
602
    st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
603

    
604
    return 0;
605
}
606

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

    
612
    if (s->io_method == io_mmap) {
613
        av_init_packet(pkt);
614
        res = mmap_read_frame(s1, pkt);
615
    } else if (s->io_method == io_read) {
616
        if (av_new_packet(pkt, s->frame_size) < 0)
617
            return AVERROR(EIO);
618

    
619
        res = read_frame(s1, pkt);
620
    } else {
621
        return AVERROR(EIO);
622
    }
623
    if (res < 0) {
624
        return res;
625
    }
626

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

    
632
    return s->frame_size;
633
}
634

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

    
639
    if (s->io_method == io_mmap) {
640
        mmap_close(s);
641
    }
642

    
643
    close(s->fd);
644
    return 0;
645
}
646

    
647
AVInputFormat v4l2_demuxer = {
648
    "video4linux2",
649
    NULL_IF_CONFIG_SMALL("video grab"),
650
    sizeof(struct video_data),
651
    NULL,
652
    v4l2_read_header,
653
    v4l2_read_packet,
654
    v4l2_read_close,
655
    .flags = AVFMT_NOFILE,
656
};