summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/indevs.texi4
-rw-r--r--libavdevice/v4l2.c58
-rw-r--r--libavdevice/version.h2
3 files changed, 49 insertions, 15 deletions
diff --git a/doc/indevs.texi b/doc/indevs.texi
index 5e8d215f6b..5cc03f9e49 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
-@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
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index 90985e35f3..1f43f0727f 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,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 },
};
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 6fd8d357f4..2aab5208c5 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, \