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 -#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, \