Commit 31d8a1d9 authored by Nicolas Dufresne's avatar Nicolas Dufresne

v4l2: Add run-time environment to enable libv4l2

The library has started preventing a lot of interesting use cases,
like CREATE_BUFS, DMABuf, usage of TRY_FMT. As the libv4l2 is totally
inactive and not maintained, we decided to disable it. As a convenience
we added a run-time environment that let you enable it for testing.

  GST_V4L2_USE_LIBV4L2=1

This of course only works if you have enabled libv4l2 at build time.
parent ab3b289b
This diff is collapsed.
...@@ -50,6 +50,7 @@ typedef struct _GstV4l2MemoryGroup GstV4l2MemoryGroup; ...@@ -50,6 +50,7 @@ typedef struct _GstV4l2MemoryGroup GstV4l2MemoryGroup;
typedef struct _GstV4l2Memory GstV4l2Memory; typedef struct _GstV4l2Memory GstV4l2Memory;
typedef enum _GstV4l2Capabilities GstV4l2Capabilities; typedef enum _GstV4l2Capabilities GstV4l2Capabilities;
typedef enum _GstV4l2Return GstV4l2Return; typedef enum _GstV4l2Return GstV4l2Return;
typedef struct _GstV4l2Object GstV4l2Object;
enum _GstV4l2AllocatorFlags enum _GstV4l2AllocatorFlags
{ {
...@@ -89,11 +90,9 @@ struct _GstV4l2MemoryGroup ...@@ -89,11 +90,9 @@ struct _GstV4l2MemoryGroup
struct _GstV4l2Allocator struct _GstV4l2Allocator
{ {
GstAllocator parent; GstAllocator parent;
gint video_fd; GstV4l2Object *obj;
guint32 count; guint32 count;
guint32 type;
guint32 memory; guint32 memory;
struct v4l2_format format;
gboolean can_allocate; gboolean can_allocate;
gboolean active; gboolean active;
...@@ -117,8 +116,7 @@ gboolean gst_v4l2_allocator_is_active (GstV4l2Allocator * alloc ...@@ -117,8 +116,7 @@ gboolean gst_v4l2_allocator_is_active (GstV4l2Allocator * alloc
guint gst_v4l2_allocator_get_size (GstV4l2Allocator * allocator); guint gst_v4l2_allocator_get_size (GstV4l2Allocator * allocator);
GstV4l2Allocator* gst_v4l2_allocator_new (GstObject *parent, gint video_fd, GstV4l2Allocator* gst_v4l2_allocator_new (GstObject *parent, GstV4l2Object * obj);
struct v4l2_format * format);
guint gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint gst_v4l2_allocator_start (GstV4l2Allocator * allocator,
guint32 count, guint32 memory); guint32 count, guint32 memory);
......
...@@ -621,7 +621,7 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool) ...@@ -621,7 +621,7 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_DMABUF:
case GST_V4L2_IO_DMABUF_IMPORT: case GST_V4L2_IO_DMABUF_IMPORT:
if (!pool->streaming) { if (!pool->streaming) {
if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0) if (obj->ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
goto streamon_failed; goto streamon_failed;
pool->streaming = TRUE; pool->streaming = TRUE;
...@@ -654,7 +654,7 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool) ...@@ -654,7 +654,7 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_DMABUF:
case GST_V4L2_IO_DMABUF_IMPORT: case GST_V4L2_IO_DMABUF_IMPORT:
if (pool->streaming) { if (pool->streaming) {
if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0) if (obj->ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)", GST_WARNING_OBJECT (pool, "STREAMOFF failed with errno %d (%s)",
errno, g_strerror (errno)); errno, g_strerror (errno));
...@@ -728,7 +728,7 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool) ...@@ -728,7 +728,7 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
* queue to be initialized now. We only do this if we have a streaming * queue to be initialized now. We only do this if we have a streaming
* driver. */ * driver. */
if (obj->device_caps & V4L2_CAP_STREAMING) if (obj->device_caps & V4L2_CAP_STREAMING)
v4l2_read (obj->video_fd, NULL, 0); obj->read (obj->video_fd, NULL, 0);
#endif #endif
break; break;
case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_DMABUF:
...@@ -1609,8 +1609,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps) ...@@ -1609,8 +1609,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
pool->obj = obj; pool->obj = obj;
pool->can_poll_device = TRUE; pool->can_poll_device = TRUE;
pool->vallocator = pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj);
gst_v4l2_allocator_new (GST_OBJECT (pool), obj->video_fd, &obj->format);
if (pool->vallocator == NULL) if (pool->vallocator == NULL)
goto allocator_failed; goto allocator_failed;
...@@ -1657,7 +1656,7 @@ gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf) ...@@ -1657,7 +1656,7 @@ gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK) if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK)
goto poll_error; goto poll_error;
amount = v4l2_read (obj->video_fd, map.data, toread); amount = obj->read (obj->video_fd, map.data, toread);
if (amount == toread) { if (amount == toread) {
break; break;
......
...@@ -329,7 +329,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s, ...@@ -329,7 +329,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
if (control.value < 0) if (control.value < 0)
continue; continue;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
GST_WARNING_OBJECT (ctx->self, "Failed to set H264 profile: '%s'", GST_WARNING_OBJECT (ctx->self, "Failed to set H264 profile: '%s'",
g_strerror (errno)); g_strerror (errno));
break; break;
...@@ -371,7 +371,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s, ...@@ -371,7 +371,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s,
if (control.value < 0) if (control.value < 0)
continue; continue;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
GST_WARNING_OBJECT (ctx->self, "Failed to set H264 level: '%s'", GST_WARNING_OBJECT (ctx->self, "Failed to set H264 level: '%s'",
g_strerror (errno)); g_strerror (errno));
break; break;
...@@ -436,7 +436,7 @@ gst_v4l2_h264_enc_negotiate (GstVideoEncoder * encoder) ...@@ -436,7 +436,7 @@ gst_v4l2_h264_enc_negotiate (GstVideoEncoder * encoder)
control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
goto g_ctrl_failed; goto g_ctrl_failed;
ctx.profile = v4l2_profile_to_string (control.value); ctx.profile = v4l2_profile_to_string (control.value);
...@@ -447,7 +447,7 @@ gst_v4l2_h264_enc_negotiate (GstVideoEncoder * encoder) ...@@ -447,7 +447,7 @@ gst_v4l2_h264_enc_negotiate (GstVideoEncoder * encoder)
control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0)
goto g_ctrl_failed; goto g_ctrl_failed;
ctx.level = v4l2_level_to_string (control.value); ctx.level = v4l2_level_to_string (control.value);
......
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#ifdef HAVE_GUDEV #ifdef HAVE_GUDEV
#include <gudev/gudev.h> #include <gudev/gudev.h>
...@@ -490,6 +493,28 @@ gst_v4l2_object_new (GstElement * element, ...@@ -490,6 +493,28 @@ gst_v4l2_object_new (GstElement * element,
v4l2object->no_initial_format = FALSE; v4l2object->no_initial_format = FALSE;
/* We now disable libv4l2 by default, but have an env to enable it. */
#ifdef HAVE_LIBV4L2
if (g_getenv ("GST_V4L2_USE_LIBV4L2")) {
v4l2object->fd_open = v4l2_fd_open;
v4l2object->close = v4l2_close;
v4l2object->dup = v4l2_dup;
v4l2object->ioctl = v4l2_ioctl;
v4l2object->read = v4l2_read;
v4l2object->mmap = v4l2_mmap;
v4l2object->munmap = v4l2_munmap;
} else
#endif
{
v4l2object->fd_open = NULL;
v4l2object->close = close;
v4l2object->dup = dup;
v4l2object->ioctl = ioctl;
v4l2object->read = read;
v4l2object->mmap = mmap;
v4l2object->munmap = munmap;
}
return v4l2object; return v4l2object;
} }
...@@ -775,7 +800,7 @@ gst_v4l2_get_driver_min_buffers (GstV4l2Object * v4l2object) ...@@ -775,7 +800,7 @@ gst_v4l2_get_driver_min_buffers (GstV4l2Object * v4l2object)
else else
control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) == 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) == 0) {
GST_DEBUG_OBJECT (v4l2object->element, GST_DEBUG_OBJECT (v4l2object->element,
"driver requires a minimum of %d buffers", control.value); "driver requires a minimum of %d buffers", control.value);
v4l2object->min_buffers = control.value; v4l2object->min_buffers = control.value;
...@@ -1113,7 +1138,7 @@ gst_v4l2_object_fill_format_list (GstV4l2Object * v4l2object, ...@@ -1113,7 +1138,7 @@ gst_v4l2_object_fill_format_list (GstV4l2Object * v4l2object,
format->index = n; format->index = n;
format->type = type; format->type = type;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
if (errno == EINVAL) { if (errno == EINVAL) {
g_free (format); g_free (format);
break; /* end of enumeration */ break; /* end of enumeration */
...@@ -2065,7 +2090,7 @@ gst_v4l2_object_try_fmt (GstV4l2Object * v4l2object, ...@@ -2065,7 +2090,7 @@ gst_v4l2_object_try_fmt (GstV4l2Object * v4l2object,
int r; int r;
memcpy (&fmt, try_fmt, sizeof (fmt)); memcpy (&fmt, try_fmt, sizeof (fmt));
r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt); r = v4l2object->ioctl (fd, VIDIOC_TRY_FMT, &fmt);
if (r < 0 && errno == ENOTTY) { if (r < 0 && errno == ENOTTY) {
/* The driver might not implement TRY_FMT, in which case we will try /* The driver might not implement TRY_FMT, in which case we will try
...@@ -2074,7 +2099,7 @@ gst_v4l2_object_try_fmt (GstV4l2Object * v4l2object, ...@@ -2074,7 +2099,7 @@ gst_v4l2_object_try_fmt (GstV4l2Object * v4l2object,
goto error; goto error;
memcpy (&fmt, try_fmt, sizeof (fmt)); memcpy (&fmt, try_fmt, sizeof (fmt));
r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt); r = v4l2object->ioctl (fd, VIDIOC_S_FMT, &fmt);
} }
memcpy (try_fmt, &fmt, sizeof (fmt)); memcpy (try_fmt, &fmt, sizeof (fmt));
...@@ -2269,7 +2294,7 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object, ...@@ -2269,7 +2294,7 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
/* keep in mind that v4l2 gives us frame intervals (durations); we invert the /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
* fraction to get framerate */ * fraction to get framerate */
if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0) if (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
goto enum_frameintervals_failed; goto enum_frameintervals_failed;
if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
...@@ -2296,7 +2321,7 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object, ...@@ -2296,7 +2321,7 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
gst_value_list_append_value (&rates, &rate); gst_value_list_append_value (&rates, &rate);
ival.index++; ival.index++;
} while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0); } while (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
} else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
GValue min = { 0, }; GValue min = { 0, };
GValue step = { 0, }; GValue step = { 0, };
...@@ -2535,7 +2560,7 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object, ...@@ -2535,7 +2560,7 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
"Enumerating frame sizes for %" GST_FOURCC_FORMAT, "Enumerating frame sizes for %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (pixelformat)); GST_FOURCC_ARGS (pixelformat));
if (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) if (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
goto enum_framesizes_failed; goto enum_framesizes_failed;
if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
...@@ -2556,7 +2581,7 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object, ...@@ -2556,7 +2581,7 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
} }
size.index++; size.index++;
} while (v4l2_ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0); } while (v4l2object->ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
GST_DEBUG_OBJECT (v4l2object->element, GST_DEBUG_OBJECT (v4l2object->element,
"done iterating discrete frame sizes"); "done iterating discrete frame sizes");
} else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
...@@ -3369,10 +3394,10 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, ...@@ -3369,10 +3394,10 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
} }
if (try_only) { if (try_only) {
if (v4l2_ioctl (fd, VIDIOC_TRY_FMT, &format) < 0) if (v4l2object->ioctl (fd, VIDIOC_TRY_FMT, &format) < 0)
goto try_fmt_failed; goto try_fmt_failed;
} else { } else {
if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) if (v4l2object->ioctl (fd, VIDIOC_S_FMT, &format) < 0)
goto set_fmt_failed; goto set_fmt_failed;
} }
...@@ -3454,7 +3479,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, ...@@ -3454,7 +3479,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
ctl.id = V4L2_CID_ALPHA_COMPONENT; ctl.id = V4L2_CID_ALPHA_COMPONENT;
ctl.value = 0xff; ctl.value = 0xff;
if (v4l2_ioctl (fd, VIDIOC_S_CTRL, &ctl) < 0) if (v4l2object->ioctl (fd, VIDIOC_S_CTRL, &ctl) < 0)
GST_WARNING_OBJECT (v4l2object->element, GST_WARNING_OBJECT (v4l2object->element,
"Failed to set alpha component value"); "Failed to set alpha component value");
} }
...@@ -3466,7 +3491,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, ...@@ -3466,7 +3491,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm)); memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm));
streamparm.type = v4l2object->type; streamparm.type = v4l2object->type;
if (v4l2_ioctl (fd, VIDIOC_G_PARM, &streamparm) < 0) if (v4l2object->ioctl (fd, VIDIOC_G_PARM, &streamparm) < 0)
goto get_parm_failed; goto get_parm_failed;
if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
...@@ -3500,7 +3525,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, ...@@ -3500,7 +3525,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
streamparm.parm.capture.timeperframe.denominator = fps_n; streamparm.parm.capture.timeperframe.denominator = fps_n;
/* some cheap USB cam's won't accept any change */ /* some cheap USB cam's won't accept any change */
if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0) if (v4l2object->ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
goto set_parm_failed; goto set_parm_failed;
if (streamparm.parm.capture.timeperframe.numerator > 0 && if (streamparm.parm.capture.timeperframe.numerator > 0 &&
...@@ -3542,7 +3567,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, ...@@ -3542,7 +3567,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
streamparm.parm.output.timeperframe.numerator = fps_d; streamparm.parm.output.timeperframe.numerator = fps_d;
streamparm.parm.output.timeperframe.denominator = fps_n; streamparm.parm.output.timeperframe.denominator = fps_n;
if (v4l2_ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0) if (v4l2object->ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0)
goto set_parm_failed; goto set_parm_failed;
if (streamparm.parm.output.timeperframe.numerator > 0 && if (streamparm.parm.output.timeperframe.numerator > 0 &&
...@@ -3750,7 +3775,7 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info) ...@@ -3750,7 +3775,7 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
memset (&fmt, 0x00, sizeof (struct v4l2_format)); memset (&fmt, 0x00, sizeof (struct v4l2_format));
fmt.type = v4l2object->type; fmt.type = v4l2object->type;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FMT, &fmt) < 0) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_FMT, &fmt) < 0)
goto get_fmt_failed; goto get_fmt_failed;
fmtdesc = gst_v4l2_object_get_format_from_fourcc (v4l2object, fmtdesc = gst_v4l2_object_get_format_from_fourcc (v4l2object,
...@@ -3775,13 +3800,13 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info) ...@@ -3775,13 +3800,13 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
memset (&sel, 0, sizeof (struct v4l2_selection)); memset (&sel, 0, sizeof (struct v4l2_selection));
sel.type = v4l2object->type; sel.type = v4l2object->type;
sel.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; sel.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_SELECTION, &sel) >= 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_SELECTION, &sel) >= 0) {
r = &sel.r; r = &sel.r;
} else { } else {
/* For ancient kernels, fall back to G_CROP */ /* For ancient kernels, fall back to G_CROP */
memset (&crop, 0, sizeof (struct v4l2_crop)); memset (&crop, 0, sizeof (struct v4l2_crop));
crop.type = v4l2object->type; crop.type = v4l2object->type;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CROP, &crop) >= 0) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CROP, &crop) >= 0)
r = &crop.c; r = &crop.c;
} }
if (r) { if (r) {
...@@ -3869,12 +3894,12 @@ gst_v4l2_object_set_crop (GstV4l2Object * obj) ...@@ -3869,12 +3894,12 @@ gst_v4l2_object_set_crop (GstV4l2Object * obj)
"Desired cropping left %u, top %u, size %ux%u", crop.c.left, crop.c.top, "Desired cropping left %u, top %u, size %ux%u", crop.c.left, crop.c.top,
crop.c.width, crop.c.height); crop.c.width, crop.c.height);
if (v4l2_ioctl (obj->video_fd, VIDIOC_S_CROP, &crop) < 0) { if (obj->ioctl (obj->video_fd, VIDIOC_S_CROP, &crop) < 0) {
GST_WARNING_OBJECT (obj->element, "VIDIOC_S_CROP failed"); GST_WARNING_OBJECT (obj->element, "VIDIOC_S_CROP failed");
return FALSE; return FALSE;
} }
if (v4l2_ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) { if (obj->ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) {
GST_WARNING_OBJECT (obj->element, "VIDIOC_G_CROP failed"); GST_WARNING_OBJECT (obj->element, "VIDIOC_G_CROP failed");
return FALSE; return FALSE;
} }
...@@ -3972,7 +3997,7 @@ gst_v4l2_object_probe_caps (GstV4l2Object * v4l2object, GstCaps * filter) ...@@ -3972,7 +3997,7 @@ gst_v4l2_object_probe_caps (GstV4l2Object * v4l2object, GstCaps * filter)
memset (&cropcap, 0, sizeof (cropcap)); memset (&cropcap, 0, sizeof (cropcap));
cropcap.type = v4l2object->type; cropcap.type = v4l2object->type;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0) {
if (errno != ENOTTY) if (errno != ENOTTY)
GST_WARNING_OBJECT (v4l2object->element, GST_WARNING_OBJECT (v4l2object->element,
"Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s", "Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s",
......
...@@ -24,23 +24,11 @@ ...@@ -24,23 +24,11 @@
#ifndef __GST_V4L2_OBJECT_H__ #ifndef __GST_V4L2_OBJECT_H__
#define __GST_V4L2_OBJECT_H__ #define __GST_V4L2_OBJECT_H__
#include "ext/videodev2.h"
#ifdef HAVE_LIBV4L2 #ifdef HAVE_LIBV4L2
# include <libv4l2.h> # include <libv4l2.h>
#else
# include "ext/videodev2.h"
# include <sys/ioctl.h>
# include <sys/mman.h>
# include <unistd.h>
# define v4l2_fd_open(fd, flags) (fd)
# 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 #endif
#include "ext/videodev2.h"
#include "v4l2-utils.h" #include "v4l2-utils.h"
#include <gst/gst.h> #include <gst/gst.h>
...@@ -212,6 +200,16 @@ struct _GstV4l2Object { ...@@ -212,6 +200,16 @@ struct _GstV4l2Object {
GstV4l2SetInOutFunction set_in_out_func; GstV4l2SetInOutFunction set_in_out_func;
GstV4l2UpdateFpsFunction update_fps_func; GstV4l2UpdateFpsFunction update_fps_func;
/* syscalls */
int (*fd_open) (int fd, int v4l2_flags);
int (*close) (int fd);
int (*dup) (int fd);
int (*ioctl) (int fd, unsigned long int request, ...);
ssize_t (*read) (int fd, void *buffer, size_t n);
void * (*mmap) (void *start, size_t length, int prot, int flags,
int fd, int64_t offset);
int (*munmap) (void *_start, size_t length);
/* Quirks */ /* Quirks */
/* Skips interlacing probes */ /* Skips interlacing probes */
gboolean never_interlaced; gboolean never_interlaced;
......
...@@ -86,7 +86,7 @@ gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio) ...@@ -86,7 +86,7 @@ gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio)
memset (&vc, 0, sizeof (vc)); memset (&vc, 0, sizeof (vc));
res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &vc); res = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &vc);
if (res < 0) if (res < 0)
goto caps_failed; goto caps_failed;
...@@ -102,7 +102,7 @@ gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio) ...@@ -102,7 +102,7 @@ gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio)
memset (&vtun, 0, sizeof (vtun)); memset (&vtun, 0, sizeof (vtun));
vtun.index = 0; vtun.index = 0;
res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun); res = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun);
if (res < 0) if (res < 0)
goto tuner_failed; goto tuner_failed;
......
...@@ -246,16 +246,16 @@ gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink) ...@@ -246,16 +246,16 @@ gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink)
if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
gint fd = v4l2sink->v4l2object->video_fd; GstV4l2Object *obj = v4l2sink->v4l2object;
struct v4l2_format format; struct v4l2_format format;
memset (&format, 0x00, sizeof (struct v4l2_format)); memset (&format, 0x00, sizeof (struct v4l2_format));
if (v4l2sink->v4l2object->device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) if (obj->device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY; format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
else else
format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0) { if (obj->ioctl (obj->video_fd, VIDIOC_G_FMT, &format) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_FMT failed"); GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_FMT failed");
return; return;
} }
...@@ -275,7 +275,7 @@ gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink) ...@@ -275,7 +275,7 @@ gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink)
if (v4l2sink->overlay_fields_set & RECT_HEIGHT_SET) if (v4l2sink->overlay_fields_set & RECT_HEIGHT_SET)
format.fmt.win.w.height = v4l2sink->overlay.height; format.fmt.win.w.height = v4l2sink->overlay.height;
if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) { if (obj->ioctl (obj->video_fd, VIDIOC_S_FMT, &format) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_FMT failed"); GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_FMT failed");
return; return;
} }
...@@ -293,13 +293,13 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink) ...@@ -293,13 +293,13 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink)
if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) {
gint fd = v4l2sink->v4l2object->video_fd; GstV4l2Object *obj = v4l2sink->v4l2object;
struct v4l2_crop crop; struct v4l2_crop crop;
memset (&crop, 0x00, sizeof (struct v4l2_crop)); memset (&crop, 0x00, sizeof (struct v4l2_crop));
crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
if (v4l2_ioctl (fd, VIDIOC_G_CROP, &crop) < 0) { if (obj->ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed"); GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed");
return; return;
} }
...@@ -319,12 +319,12 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink) ...@@ -319,12 +319,12 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink)
if (v4l2sink->crop_fields_set & RECT_HEIGHT_SET) if (v4l2sink->crop_fields_set & RECT_HEIGHT_SET)
crop.c.height = v4l2sink->crop.height; crop.c.height = v4l2sink->crop.height;
if (v4l2_ioctl (fd, VIDIOC_S_CROP, &crop) < 0) { if (obj->ioctl (obj->video_fd, VIDIOC_S_CROP, &crop) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_CROP failed"); GST_WARNING_OBJECT (v4l2sink, "VIDIOC_S_CROP failed");
return; return;
} }
if (v4l2_ioctl (fd, VIDIOC_G_CROP, &crop) < 0) { if (obj->ioctl (obj->video_fd, VIDIOC_G_CROP, &crop) < 0) {
GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed"); GST_WARNING_OBJECT (v4l2sink, "VIDIOC_G_CROP failed");
return; return;
} }
......
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
* ]| This pipeline shows the video captured from a webcam that delivers jpeg * ]| This pipeline shows the video captured from a webcam that delivers jpeg
* images. * images.
* </refsect2> * </refsect2>
*
* Since 1.14, the use of libv4l2 has been disabled due to major bugs in the
* emulation layer. To enable usage of this library, set the environment
* variable GST_V4L2_USE_LIBV4L2=1.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
......
...@@ -311,7 +311,7 @@ gst_v4l2_decoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags) ...@@ -311,7 +311,7 @@ gst_v4l2_decoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags)
dcmd.cmd = cmd; dcmd.cmd = cmd;
dcmd.flags = flags; dcmd.flags = flags;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_DECODER_CMD, &dcmd) < 0) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_DECODER_CMD, &dcmd) < 0)
goto dcmd_failed; goto dcmd_failed;
return TRUE; return TRUE;
......
...@@ -241,7 +241,7 @@ gst_v4l2_encoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags) ...@@ -241,7 +241,7 @@ gst_v4l2_encoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags)
ecmd.cmd = cmd; ecmd.cmd = cmd;
ecmd.flags = flags; ecmd.flags = flags;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENCODER_CMD, &ecmd) < 0) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENCODER_CMD, &ecmd) < 0)
goto ecmd_failed; goto ecmd_failed;
return TRUE; return TRUE;
......
...@@ -68,7 +68,8 @@ gst_v4l2_get_capabilities (GstV4l2Object * v4l2object) ...@@ -68,7 +68,8 @@ gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
if (!GST_V4L2_IS_OPEN (v4l2object)) if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE; return FALSE;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0) if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP,
&v4l2object->vcap) < 0)
goto cap_failed; goto cap_failed;
if (v4l2object->vcap.capabilities & V4L2_CAP_DEVICE_CAPS) if (v4l2object->vcap.capabilities & V4L2_CAP_DEVICE_CAPS)
...@@ -147,7 +148,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object) ...@@ -147,7 +148,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
memset (&input, 0, sizeof (input)); memset (&input, 0, sizeof (input));
input.index = n; input.index = n;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUMINPUT, &input) < 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
if (errno == EINVAL || errno == ENOTTY) if (errno == EINVAL || errno == ENOTTY)
break; /* end of enumeration */ break; /* end of enumeration */
else { else {
...@@ -181,7 +182,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object) ...@@ -181,7 +182,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
channel->flags |= GST_TUNER_CHANNEL_FREQUENCY; channel->flags |= GST_TUNER_CHANNEL_FREQUENCY;
vtun.index = input.tuner; vtun.index = input.tuner;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun) < 0) { if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS, GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed to get setting of tuner %d on device '%s'."), (_("Failed to get setting of tuner %d on device '%s'."),
input.tuner, v4l2object