v4l2: make possible to disable libv4l2 at runtime.
authorClément Bœsch <ubitux@gmail.com>
Mon, 20 May 2013 13:43:31 +0000 (15:43 +0200)
committerClément Bœsch <ubitux@gmail.com>
Wed, 22 May 2013 17:49:29 +0000 (19:49 +0200)
Also disable it by default since it looks currently buggy. The
usefulness of such library is mostly limited to backward compatibility
with very old devices.

doc/indevs.texi
libavdevice/v4l2.c
libavdevice/version.h

index 5e8d215..5cc03f9 100644 (file)
@@ -590,8 +590,8 @@ Video4Linux2 input video device.
 "v4l2" can be used as alias for "video4linux2".
 
 If FFmpeg is built with v4l-utils support (by using the
-@code{--enable-libv4l2} configure option), the device will always rely
-on libv4l2.
+@code{--enable-libv4l2} configure option), it is possible to use it with the
+@code{-use_libv4l2} input device option.
 
 The name of the device to grab is a file device node, usually Linux
 systems tend to automatically create such nodes when the device
index 90985e3..1f43f07 100644 (file)
 
 #if CONFIG_LIBV4L2
 #include <libv4l2.h>
-#else
-#define v4l2_open   open
-#define v4l2_close  close
-#define v4l2_dup    dup
-#define v4l2_ioctl  ioctl
-#define v4l2_read   read
-#define v4l2_mmap   mmap
-#define v4l2_munmap munmap
 #endif
 
 static const int desired_video_buffers = 256;
@@ -95,6 +87,15 @@ struct video_data {
     int list_format;    /**< Set by a private option. */
     int list_standard;  /**< Set by a private option. */
     char *framerate;    /**< Set by a private option. */
+
+    int use_libv4l2;
+    int (*open_f)(const char *file, int oflag, ...);
+    int (*close_f)(int fd);
+    int (*dup_f)(int fd);
+    int (*ioctl_f)(int fd, unsigned long int request, ...);
+    ssize_t (*read_f)(int fd, void *buffer, size_t n);
+    void *(*mmap_f)(void *start, size_t length, int prot, int flags, int fd, int64_t offset);
+    int (*munmap_f)(void *_start, size_t length);
 };
 
 struct buff_data {
@@ -104,11 +105,41 @@ struct buff_data {
 
 static int device_open(AVFormatContext *ctx)
 {
+    struct video_data *s = ctx->priv_data;
     struct v4l2_capability cap;
     int fd;
     int ret;
     int flags = O_RDWR;
 
+#define SET_WRAPPERS(prefix) do {       \
+    s->open_f   = prefix ## open;       \
+    s->close_f  = prefix ## close;      \
+    s->dup_f    = prefix ## dup;        \
+    s->ioctl_f  = prefix ## ioctl;      \
+    s->read_f   = prefix ## read;       \
+    s->mmap_f   = prefix ## mmap;       \
+    s->munmap_f = prefix ## munmap;     \
+} while (0)
+
+    if (s->use_libv4l2) {
+#if CONFIG_LIBV4L2
+        SET_WRAPPERS(v4l2_);
+#else
+        av_log(ctx, AV_LOG_ERROR, "libavdevice is not build with libv4l2 support.\n");
+        return AVERROR(EINVAL);
+#endif
+    } else {
+        SET_WRAPPERS();
+    }
+
+#define v4l2_open   s->open_f
+#define v4l2_close  s->close_f
+#define v4l2_dup    s->dup_f
+#define v4l2_ioctl  s->ioctl_f
+#define v4l2_read   s->read_f
+#define v4l2_mmap   s->mmap_f
+#define v4l2_munmap s->munmap_f
+
     if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
         flags |= O_NONBLOCK;
     }
@@ -194,7 +225,7 @@ static int device_init(AVFormatContext *ctx, int *width, int *height,
     return res;
 }
 
-static int first_field(int fd)
+static int first_field(const struct video_data *s, int fd)
 {
     int res;
     v4l2_std_id std;
@@ -213,6 +244,7 @@ static int first_field(int fd)
 #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE
 static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat)
 {
+    const struct video_data *s = ctx->priv_data;
     struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat };
 
     while(!v4l2_ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) {
@@ -238,6 +270,7 @@ static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat)
 
 static void list_formats(AVFormatContext *ctx, int fd, int type)
 {
+    const struct video_data *s = ctx->priv_data;
     struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
 
     while(!v4l2_ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) {
@@ -777,7 +810,8 @@ static int v4l2_read_header(AVFormatContext *s1)
 #if CONFIG_LIBV4L2
     /* silence libv4l2 logging. if fopen() fails v4l2_log_file will be NULL
        and errors will get sent to stderr */
-    v4l2_log_file = fopen("/dev/null", "w");
+    if (s->use_libv4l2)
+        v4l2_log_file = fopen("/dev/null", "w");
 #endif
 
     s->fd = device_open(s1);
@@ -888,7 +922,7 @@ static int v4l2_read_header(AVFormatContext *s1)
         return res;
     }
 
-    s->top_field_first = first_field(s->fd);
+    s->top_field_first = first_field(s, s->fd);
 
     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
     st->codec->codec_id = codec_id;
@@ -963,7 +997,7 @@ static const AVOption options[] = {
     { "default",      "use timestamps from the kernel",                           OFFSET(ts_mode),      AV_OPT_TYPE_CONST,  {.i64 = V4L_TS_DEFAULT  }, 0, 2, DEC, "timestamps" },
     { "abs",          "use absolute timestamps (wall clock)",                     OFFSET(ts_mode),      AV_OPT_TYPE_CONST,  {.i64 = V4L_TS_ABS      }, 0, 2, DEC, "timestamps" },
     { "mono2abs",     "force conversion from monotonic to absolute timestamps",   OFFSET(ts_mode),      AV_OPT_TYPE_CONST,  {.i64 = V4L_TS_MONO2ABS }, 0, 2, DEC, "timestamps" },
-
+    { "use_libv4l2",  "use libv4l2 (v4l-utils) convertion functions",             OFFSET(use_libv4l2),  AV_OPT_TYPE_INT,    {.i64 = 0}, 0, 1, DEC },
     { NULL },
 };
 
index 6fd8d35..2aab520 100644 (file)
@@ -29,7 +29,7 @@
 
 #define LIBAVDEVICE_VERSION_MAJOR  55
 #define LIBAVDEVICE_VERSION_MINOR   1
-#define LIBAVDEVICE_VERSION_MICRO 100
+#define LIBAVDEVICE_VERSION_MICRO 101
 
 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
                                                LIBAVDEVICE_VERSION_MINOR, \