[FFmpeg-devel] [PATCH] v4l2: make possible to disable libv4l2 at runtime.

Clément Bœsch ubitux at gmail.com
Mon May 20 15:48:25 CEST 2013


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       |  4 ++--
 libavdevice/v4l2.c    | 52 +++++++++++++++++++++++++++++++++++++++------------
 libavdevice/version.h |  2 +-
 3 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/doc/indevs.texi b/doc/indevs.texi
index 5e8d215..5cc03f9 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -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
- at code{--enable-libv4l2} configure option), the device will always rely
-on libv4l2.
+ at code{--enable-libv4l2} configure option), it is possible to use it with the
+ at 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
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index 90985e3..7c69132 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -34,14 +34,6 @@
 
 #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,35 @@ 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 (CONFIG_LIBV4L2 && s->use_libv4l2)
+        SET_WRAPPERS(v4l2_);
+    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 +219,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 +238,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 +264,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 +804,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 +916,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 +991,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 = 1}, 0, 1, DEC },
     { NULL },
 };
 
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 6fd8d35..2aab520 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -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, \
-- 
1.8.2.3



More information about the ffmpeg-devel mailing list