Browse code

v4l2: add libv4l2 support.

Clément Bœsch authored on 2011/10/30 11:21:55
Showing 4 changed files
... ...
@@ -75,6 +75,7 @@ easier to use. The changes are:
75 75
 - new ffmpeg option: -map_channel
76 76
 - volume audio filter added
77 77
 - earwax audio filter added
78
+- libv4l2 support (--enable-libv4l2)
78 79
 
79 80
 
80 81
 version 0.8:
... ...
@@ -187,6 +187,7 @@ External library support:
187 187
   --enable-libstagefright-h264  enable H.264 decoding via libstagefright [no]
188 188
   --enable-libtheora       enable Theora encoding via libtheora [no]
189 189
   --enable-libutvideo      enable Ut Video decoding via libutvideo [no]
190
+  --enable-libv4l2         enable libv4l2/v4l-utils [no]
190 191
   --enable-libvo-aacenc    enable AAC encoding via libvo-aacenc [no]
191 192
   --enable-libvo-amrwbenc  enable AMR-WB encoding via libvo-amrwbenc [no]
192 193
   --enable-libvorbis       enable Vorbis encoding via libvorbis,
... ...
@@ -1022,6 +1023,7 @@ CONFIG_LIST="
1022 1022
     libstagefright_h264
1023 1023
     libtheora
1024 1024
     libutvideo
1025
+    libv4l2
1025 1026
     libvo_aacenc
1026 1027
     libvo_amrwbenc
1027 1028
     libvorbis
... ...
@@ -1568,6 +1570,7 @@ jack_indev_deps="jack_jack_h sem_timedwait"
1568 1568
 lavfi_indev_deps="avfilter"
1569 1569
 libcdio_indev_deps="libcdio"
1570 1570
 libdc1394_indev_deps="libdc1394"
1571
+libv4l2_indev_deps="libv4l2"
1571 1572
 openal_indev_deps="openal"
1572 1573
 oss_indev_deps_any="soundcard_h sys_soundcard_h"
1573 1574
 oss_outdev_deps_any="soundcard_h sys_soundcard_h"
... ...
@@ -3055,6 +3058,7 @@ enabled libstagefright_h264  && require_cpp libstagefright_h264 "binder/ProcessS
3055 3055
     media/stagefright/OMXClient.h media/stagefright/OMXCodec.h" android::OMXClient -lstagefright -lmedia -lutils -lbinder
3056 3056
 enabled libtheora  && require  libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg
3057 3057
 enabled libutvideo    && require_cpp utvideo "stdint.h stdlib.h utvideo/utvideo.h utvideo/Codec.h" 'CCodec*' -lutvideo -lstdc++
3058
+enabled libv4l2    && require_pkg_config libv4l2 libv4l2.h v4l2_ioctl
3058 3059
 enabled libvo_aacenc && require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI -lvo-aacenc
3059 3060
 enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc
3060 3061
 enabled libvorbis  && require  libvorbis vorbis/vorbisenc.h vorbis_info_init -lvorbisenc -lvorbis -logg
... ...
@@ -3383,6 +3387,7 @@ echo "libspeex enabled          ${libspeex-no}"
3383 3383
 echo "libstagefright-h264 enabled    ${libstagefright_h264-no}"
3384 3384
 echo "libtheora enabled         ${libtheora-no}"
3385 3385
 echo "libutvideo enabled        ${libutvideo-no}"
3386
+echo "libv4l2 enabled           ${libv4l2-no}"
3386 3387
 echo "libvo-aacenc support      ${libvo_aacenc-no}"
3387 3388
 echo "libvo-amrwbenc support    ${libvo_amrwbenc-no}"
3388 3389
 echo "libvorbis enabled         ${libvorbis-no}"
... ...
@@ -513,6 +513,9 @@ input device will use the frame rate value already set in the driver.
513 513
 Video4Linux support is deprecated since Linux 2.6.30, and will be
514 514
 dropped in later versions.
515 515
 
516
+Note that if FFmpeg is build with v4l-utils support ("--enable-libv4l2"
517
+option), it will always be used.
518
+
516 519
 Follow some usage examples of the video4linux devices with the ff*
517 520
 tools.
518 521
 @example
... ...
@@ -52,6 +52,18 @@
52 52
 #include "libavutil/pixdesc.h"
53 53
 #include "libavutil/avstring.h"
54 54
 
55
+#if CONFIG_LIBV4L2
56
+#include <libv4l2.h>
57
+#else
58
+#define v4l2_open   open
59
+#define v4l2_close  close
60
+#define v4l2_dup    dup
61
+#define v4l2_ioctl  ioctl
62
+#define v4l2_read   read
63
+#define v4l2_mmap   mmap
64
+#define v4l2_munmap munmap
65
+#endif
66
+
55 67
 static const int desired_video_buffers = 256;
56 68
 
57 69
 enum io_method {
... ...
@@ -113,36 +125,49 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
113 113
 {
114 114
     struct v4l2_capability cap;
115 115
     int fd;
116
+#if CONFIG_LIBV4L2
117
+    int fd_libv4l;
118
+#endif
116 119
     int res, err;
117 120
     int flags = O_RDWR;
118 121
 
119 122
     if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
120 123
         flags |= O_NONBLOCK;
121 124
     }
122
-    fd = open(ctx->filename, flags, 0);
125
+    fd = v4l2_open(ctx->filename, flags, 0);
123 126
     if (fd < 0) {
124 127
         av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
125 128
                  ctx->filename, strerror(errno));
126 129
         return AVERROR(errno);
127 130
     }
131
+#if CONFIG_LIBV4L2
132
+    fd_libv4l = v4l2_fd_open(fd, 0);
133
+    if (fd < 0) {
134
+        err = AVERROR(errno);
135
+        av_log(ctx, AV_LOG_ERROR, "Cannot open video device with libv4l neither %s : %s\n",
136
+               ctx->filename, strerror(errno));
137
+        return err;
138
+    }
139
+    fd = fd_libv4l;
140
+#endif
128 141
 
129
-    res = ioctl(fd, VIDIOC_QUERYCAP, &cap);
142
+    res = v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap);
130 143
     // ENOIOCTLCMD definition only availble on __KERNEL__
131 144
     if (res < 0 && ((err = errno) == 515)) {
132 145
         av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n");
133
-        close(fd);
146
+        v4l2_close(fd);
134 147
 
135 148
         return AVERROR(515);
136 149
     }
137 150
     if (res < 0) {
138 151
         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
139 152
                  strerror(errno));
140
-        close(fd);
153
+        v4l2_close(fd);
141 154
         return AVERROR(err);
142 155
     }
143 156
     if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
144 157
         av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n");
145
-        close(fd);
158
+        v4l2_close(fd);
146 159
         return AVERROR(ENODEV);
147 160
     }
148 161
     *capabilities = cap.capabilities;
... ...
@@ -162,7 +187,7 @@ static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t p
162 162
     fmt.fmt.pix.height = *height;
163 163
     fmt.fmt.pix.pixelformat = pix_fmt;
164 164
     fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
165
-    res = ioctl(fd, VIDIOC_S_FMT, &fmt);
165
+    res = v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt);
166 166
     if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) {
167 167
         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);
168 168
         *width = fmt.fmt.pix.width;
... ...
@@ -182,7 +207,7 @@ static int first_field(int fd)
182 182
     int res;
183 183
     v4l2_std_id std;
184 184
 
185
-    res = ioctl(fd, VIDIOC_G_STD, &std);
185
+    res = v4l2_ioctl(fd, VIDIOC_G_STD, &std);
186 186
     if (res < 0) {
187 187
         return 0;
188 188
     }
... ...
@@ -245,7 +270,7 @@ static int mmap_init(AVFormatContext *ctx)
245 245
     req.count = desired_video_buffers;
246 246
     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
247 247
     req.memory = V4L2_MEMORY_MMAP;
248
-    res = ioctl(s->fd, VIDIOC_REQBUFS, &req);
248
+    res = v4l2_ioctl(s->fd, VIDIOC_REQBUFS, &req);
249 249
     if (res < 0) {
250 250
         if (errno == EINVAL) {
251 251
             av_log(ctx, AV_LOG_ERROR, "Device does not support mmap\n");
... ...
@@ -278,7 +303,7 @@ static int mmap_init(AVFormatContext *ctx)
278 278
         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
279 279
         buf.memory = V4L2_MEMORY_MMAP;
280 280
         buf.index = i;
281
-        res = ioctl(s->fd, VIDIOC_QUERYBUF, &buf);
281
+        res = v4l2_ioctl(s->fd, VIDIOC_QUERYBUF, &buf);
282 282
         if (res < 0) {
283 283
             av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYBUF)\n");
284 284
             return AVERROR(errno);
... ...
@@ -290,7 +315,7 @@ static int mmap_init(AVFormatContext *ctx)
290 290
 
291 291
             return -1;
292 292
         }
293
-        s->buf_start[i] = mmap (NULL, buf.length,
293
+        s->buf_start[i] = v4l2_mmap(NULL, buf.length,
294 294
                         PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);
295 295
         if (s->buf_start[i] == MAP_FAILED) {
296 296
             av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
... ...
@@ -322,7 +347,7 @@ static void mmap_release_buffer(AVPacket *pkt)
322 322
     fd = buf_descriptor->fd;
323 323
     av_free(buf_descriptor);
324 324
 
325
-    res = ioctl(fd, VIDIOC_QBUF, &buf);
325
+    res = v4l2_ioctl(fd, VIDIOC_QBUF, &buf);
326 326
     if (res < 0) {
327 327
         av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
328 328
     }
... ...
@@ -341,7 +366,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
341 341
     buf.memory = V4L2_MEMORY_MMAP;
342 342
 
343 343
     /* FIXME: Some special treatment might be needed in case of loss of signal... */
344
-    while ((res = ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
344
+    while ((res = v4l2_ioctl(s->fd, VIDIOC_DQBUF, &buf)) < 0 && (errno == EINTR));
345 345
     if (res < 0) {
346 346
         if (errno == EAGAIN) {
347 347
             pkt->size = 0;
... ...
@@ -368,7 +393,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
368 368
          * allocate a buffer for memcopying into it
369 369
          */
370 370
         av_log(ctx, AV_LOG_ERROR, "Failed to allocate a buffer descriptor\n");
371
-        res = ioctl(s->fd, VIDIOC_QBUF, &buf);
371
+        res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf);
372 372
 
373 373
         return AVERROR(ENOMEM);
374 374
     }
... ...
@@ -397,7 +422,7 @@ static int mmap_start(AVFormatContext *ctx)
397 397
         buf.memory = V4L2_MEMORY_MMAP;
398 398
         buf.index  = i;
399 399
 
400
-        res = ioctl(s->fd, VIDIOC_QBUF, &buf);
400
+        res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf);
401 401
         if (res < 0) {
402 402
             av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno));
403 403
             return AVERROR(errno);
... ...
@@ -405,7 +430,7 @@ static int mmap_start(AVFormatContext *ctx)
405 405
     }
406 406
 
407 407
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
408
-    res = ioctl(s->fd, VIDIOC_STREAMON, &type);
408
+    res = v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type);
409 409
     if (res < 0) {
410 410
         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno));
411 411
         return AVERROR(errno);
... ...
@@ -423,9 +448,9 @@ static void mmap_close(struct video_data *s)
423 423
     /* We do not check for the result, because we could
424 424
      * not do anything about it anyway...
425 425
      */
426
-    ioctl(s->fd, VIDIOC_STREAMOFF, &type);
426
+    v4l2_ioctl(s->fd, VIDIOC_STREAMOFF, &type);
427 427
     for (i = 0; i < s->buffers; i++) {
428
-        munmap(s->buf_start[i], s->buf_len[i]);
428
+        v4l2_munmap(s->buf_start[i], s->buf_len[i]);
429 429
     }
430 430
     av_free(s->buf_start);
431 431
     av_free(s->buf_len);
... ...
@@ -450,14 +475,14 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
450 450
 
451 451
     /* set tv video input */
452 452
     input.index = s->channel;
453
-    if (ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
453
+    if (v4l2_ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) {
454 454
         av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n");
455 455
         return AVERROR(EIO);
456 456
     }
457 457
 
458 458
     av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n",
459 459
             s->channel, input.name);
460
-    if (ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) {
460
+    if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) {
461 461
         av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n",
462 462
                 s->channel);
463 463
         return AVERROR(EIO);
... ...
@@ -469,7 +494,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
469 469
         /* set tv standard */
470 470
         for (i = 0;; i++) {
471 471
             standard.index = i;
472
-            ret = ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
472
+            ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
473 473
             if (ret < 0 || !av_strcasecmp(standard.name, s->standard))
474 474
                 break;
475 475
         }
... ...
@@ -480,7 +505,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
480 480
 
481 481
         av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
482 482
                s->standard, (uint64_t)standard.id);
483
-        if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
483
+        if (v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
484 484
             av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n",
485 485
                    s->standard);
486 486
             return AVERROR(EIO);
... ...
@@ -492,7 +517,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
492 492
                framerate_q.den, framerate_q.num);
493 493
         tpf->numerator   = framerate_q.den;
494 494
         tpf->denominator = framerate_q.num;
495
-        if (ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) {
495
+        if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) {
496 496
             av_log(s1, AV_LOG_ERROR,
497 497
                    "ioctl set time per frame(%d/%d) failed\n",
498 498
                    framerate_q.den, framerate_q.num);
... ...
@@ -508,7 +533,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap)
508 508
         }
509 509
     } else {
510 510
         /* if timebase value is not set, read the timebase value from the driver */
511
-        if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) {
511
+        if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) {
512 512
             av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno));
513 513
             return AVERROR(errno);
514 514
         }
... ...
@@ -590,7 +615,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
590 590
 
591 591
         av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n");
592 592
         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
593
-        if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
593
+        if (v4l2_ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
594 594
             av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno));
595 595
             res = AVERROR(errno);
596 596
             goto out;
... ...
@@ -604,7 +629,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
604 604
     if (desired_format == 0) {
605 605
         av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
606 606
                "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt);
607
-        close(s->fd);
607
+        v4l2_close(s->fd);
608 608
 
609 609
         res = AVERROR(EIO);
610 610
         goto out;
... ...
@@ -629,7 +654,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
629 629
         res = read_init(s1);
630 630
     }
631 631
     if (res < 0) {
632
-        close(s->fd);
632
+        v4l2_close(s->fd);
633 633
         res = AVERROR(EIO);
634 634
         goto out;
635 635
     }
... ...
@@ -681,7 +706,7 @@ static int v4l2_read_close(AVFormatContext *s1)
681 681
         mmap_close(s);
682 682
     }
683 683
 
684
-    close(s->fd);
684
+    v4l2_close(s->fd);
685 685
     return 0;
686 686
 }
687 687