From 31d8a1d929fecd7ceaa7575be5921f9148ed8afb Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 24 Jul 2017 14:19:02 -0400 Subject: [PATCH] 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. --- sys/v4l2/gstv4l2allocator.c | 102 ++++++++++++++++++++++++------------------- sys/v4l2/gstv4l2allocator.h | 8 ++-- sys/v4l2/gstv4l2bufferpool.c | 11 +++-- sys/v4l2/gstv4l2h264enc.c | 8 ++-- sys/v4l2/gstv4l2object.c | 65 ++++++++++++++++++--------- sys/v4l2/gstv4l2object.h | 24 +++++----- sys/v4l2/gstv4l2radio.c | 4 +- sys/v4l2/gstv4l2sink.c | 16 +++---- sys/v4l2/gstv4l2src.c | 4 ++ sys/v4l2/gstv4l2videodec.c | 2 +- sys/v4l2/gstv4l2videoenc.c | 2 +- sys/v4l2/v4l2_calls.c | 55 +++++++++++++---------- 12 files changed, 171 insertions(+), 130 deletions(-) diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c index 122a8b5..c47b8c5 100644 --- a/sys/v4l2/gstv4l2allocator.c +++ b/sys/v4l2/gstv4l2allocator.c @@ -241,9 +241,9 @@ gst_v4l2_memory_group_free (GstV4l2MemoryGroup * group) static GstV4l2MemoryGroup * gst_v4l2_memory_group_new (GstV4l2Allocator * allocator, guint32 index) { - gint video_fd = allocator->video_fd; + GstV4l2Object *obj = allocator->obj; guint32 memory = allocator->memory; - struct v4l2_format *format = &allocator->format; + struct v4l2_format *format = &obj->format; GstV4l2MemoryGroup *group; gsize img_size, buf_size; @@ -260,7 +260,7 @@ gst_v4l2_memory_group_new (GstV4l2Allocator * allocator, guint32 index) group->n_mem = 1; } - if (v4l2_ioctl (video_fd, VIDIOC_QUERYBUF, &group->buffer) < 0) + if (obj->ioctl (obj->video_fd, VIDIOC_QUERYBUF, &group->buffer) < 0) goto querybuf_failed; if (group->buffer.index != index) { @@ -273,17 +273,17 @@ gst_v4l2_memory_group_new (GstV4l2Allocator * allocator, guint32 index) /* Check that provided size matches the format we have negotiation. Failing * there usually means a driver of libv4l bug. */ - if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { gint i; for (i = 0; i < group->n_mem; i++) { - img_size = allocator->format.fmt.pix_mp.plane_fmt[i].sizeimage; + img_size = obj->format.fmt.pix_mp.plane_fmt[i].sizeimage; buf_size = group->planes[i].length; if (buf_size < img_size) goto buffer_too_short; } } else { - img_size = allocator->format.fmt.pix.sizeimage; + img_size = obj->format.fmt.pix.sizeimage; buf_size = group->buffer.length; if (buf_size < img_size) goto buffer_too_short; @@ -378,6 +378,7 @@ static void gst_v4l2_allocator_free (GstAllocator * gallocator, GstMemory * gmem) { GstV4l2Allocator *allocator = (GstV4l2Allocator *) gallocator; + GstV4l2Object *obj = allocator->obj; GstV4l2Memory *mem = (GstV4l2Memory *) gmem; GstV4l2MemoryGroup *group = mem->group; @@ -388,7 +389,7 @@ gst_v4l2_allocator_free (GstAllocator * gallocator, GstMemory * gmem) if (allocator->memory == V4L2_MEMORY_MMAP) { if (mem->data) - v4l2_munmap (mem->data, group->planes[mem->plane].length); + obj->munmap (mem->data, group->planes[mem->plane].length); } /* This apply for both mmap with expbuf, and dmabuf imported memory */ @@ -424,7 +425,6 @@ gst_v4l2_allocator_finalize (GObject * obj) GST_LOG_OBJECT (obj, "called"); - v4l2_close (allocator->video_fd); gst_atomic_queue_unref (allocator->free_queue); G_OBJECT_CLASS (parent_class)->finalize (obj); @@ -478,22 +478,23 @@ static guint32 gst_v4l2_allocator_probe (GstV4l2Allocator * allocator, guint32 memory, guint32 breq_flag, guint32 bcreate_flag) { + GstV4l2Object *obj = allocator->obj; struct v4l2_requestbuffers breq = { 0 }; guint32 flags = 0; - breq.type = allocator->type; + breq.type = obj->type; breq.count = 0; breq.memory = memory; - if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) == 0) { + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) == 0) { struct v4l2_create_buffers bcreate = { 0 }; flags |= breq_flag; bcreate.memory = memory; - bcreate.format = allocator->format; + bcreate.format = obj->format; - if ((v4l2_ioctl (allocator->video_fd, VIDIOC_CREATE_BUFS, &bcreate) == 0)) + if ((obj->ioctl (obj->video_fd, VIDIOC_CREATE_BUFS, &bcreate) == 0)) flags |= bcreate_flag; } @@ -503,6 +504,7 @@ gst_v4l2_allocator_probe (GstV4l2Allocator * allocator, guint32 memory, static GstV4l2MemoryGroup * gst_v4l2_allocator_create_buf (GstV4l2Allocator * allocator) { + GstV4l2Object *obj = allocator->obj; struct v4l2_create_buffers bcreate = { 0 }; GstV4l2MemoryGroup *group = NULL; @@ -512,13 +514,13 @@ gst_v4l2_allocator_create_buf (GstV4l2Allocator * allocator) goto done; bcreate.memory = allocator->memory; - bcreate.format = allocator->format; + bcreate.format = obj->format; bcreate.count = 1; if (!allocator->can_allocate) goto done; - if (v4l2_ioctl (allocator->video_fd, VIDIOC_CREATE_BUFS, &bcreate) < 0) + if (obj->ioctl (obj->video_fd, VIDIOC_CREATE_BUFS, &bcreate) < 0) goto create_bufs_failed; if (allocator->groups[bcreate.index] != NULL) @@ -577,6 +579,7 @@ static void gst_v4l2_allocator_reset_size (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) { + GstV4l2Object *obj = allocator->obj; gsize size; gboolean imported = FALSE; @@ -587,11 +590,11 @@ gst_v4l2_allocator_reset_size (GstV4l2Allocator * allocator, break; } - if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { gint i; for (i = 0; i < group->n_mem; i++) { - size = allocator->format.fmt.pix_mp.plane_fmt[i].sizeimage; + size = obj->format.fmt.pix_mp.plane_fmt[i].sizeimage; if (imported) group->mem[i]->maxsize = size; @@ -600,7 +603,7 @@ gst_v4l2_allocator_reset_size (GstV4l2Allocator * allocator, } } else { - size = allocator->format.fmt.pix.sizeimage; + size = obj->format.fmt.pix.sizeimage; if (imported) group->mem[0]->maxsize = size; @@ -628,8 +631,7 @@ _cleanup_failed_alloc (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) GstV4l2Allocator * -gst_v4l2_allocator_new (GstObject * parent, gint video_fd, - struct v4l2_format *format) +gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object) { GstV4l2Allocator *allocator; guint32 flags = 0; @@ -644,9 +646,7 @@ gst_v4l2_allocator_new (GstObject * parent, gint video_fd, g_free (name); /* Save everything */ - allocator->video_fd = v4l2_dup (video_fd); - allocator->type = format->type; - allocator->format = *format; + allocator->obj = v4l2object; flags |= GST_V4L2_ALLOCATOR_PROBE (allocator, MMAP); flags |= GST_V4L2_ALLOCATOR_PROBE (allocator, USERPTR); @@ -672,7 +672,8 @@ guint gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint32 count, guint32 memory) { - struct v4l2_requestbuffers breq = { count, allocator->type, memory }; + GstV4l2Object *obj = allocator->obj; + struct v4l2_requestbuffers breq = { count, obj->type, memory }; gboolean can_allocate; gint i; @@ -683,7 +684,7 @@ gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint32 count, if (g_atomic_int_get (&allocator->active)) goto already_active; - if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) < 0) + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) goto reqbufs_failed; if (breq.count < 1) @@ -752,7 +753,8 @@ error: GstV4l2Return gst_v4l2_allocator_stop (GstV4l2Allocator * allocator) { - struct v4l2_requestbuffers breq = { 0, allocator->type, allocator->memory }; + GstV4l2Object *obj = allocator->obj; + struct v4l2_requestbuffers breq = { 0, obj->type, allocator->memory }; gint i = 0; GstV4l2Return ret = GST_V4L2_OK; @@ -781,7 +783,7 @@ gst_v4l2_allocator_stop (GstV4l2Allocator * allocator) } /* Not all drivers support rebufs(0), so warn only */ - if (v4l2_ioctl (allocator->video_fd, VIDIOC_REQBUFS, &breq) < 0) + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) GST_WARNING_OBJECT (allocator, "error releasing buffers buffers: %s", g_strerror (errno)); @@ -797,6 +799,7 @@ done: GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator) { + GstV4l2Object *obj = allocator->obj; GstV4l2MemoryGroup *group; gint i; @@ -810,8 +813,8 @@ gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator) for (i = 0; i < group->n_mem; i++) { if (group->mem[i] == NULL) { gpointer data; - data = v4l2_mmap (NULL, group->planes[i].length, PROT_READ | PROT_WRITE, - MAP_SHARED, allocator->video_fd, group->planes[i].m.mem_offset); + data = obj->mmap (NULL, group->planes[i].length, PROT_READ | PROT_WRITE, + MAP_SHARED, obj->video_fd, group->planes[i].m.mem_offset); if (data == MAP_FAILED) goto mmap_failed; @@ -852,6 +855,7 @@ GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, GstAllocator * dmabuf_allocator) { + GstV4l2Object *obj = allocator->obj; GstV4l2MemoryGroup *group; gint i; @@ -870,12 +874,12 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator, if (group->mem[i] == NULL) { struct v4l2_exportbuffer expbuf = { 0 }; - expbuf.type = allocator->type; + expbuf.type = obj->type; expbuf.index = group->buffer.index; expbuf.plane = i; expbuf.flags = O_CLOEXEC | O_RDWR; - if (v4l2_ioctl (allocator->video_fd, VIDIOC_EXPBUF, &expbuf) < 0) + if (obj->ioctl (obj->video_fd, VIDIOC_EXPBUF, &expbuf) < 0) goto expbuf_failed; GST_LOG_OBJECT (allocator, "exported DMABUF as fd %i plane %d", @@ -933,6 +937,7 @@ static void gst_v4l2_allocator_clear_dmabufin (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) { + GstV4l2Object *obj = allocator->obj; GstV4l2Memory *mem; gint i; @@ -961,7 +966,7 @@ gst_v4l2_allocator_clear_dmabufin (GstV4l2Allocator * allocator, group->planes[i].data_offset = 0; } - if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { group->buffer.bytesused = 0; group->buffer.length = 0; group->buffer.m.fd = -1; @@ -1004,6 +1009,7 @@ static void gst_v4l2_allocator_clear_userptr (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) { + GstV4l2Object *obj = allocator->obj; GstV4l2Memory *mem; gint i; @@ -1024,7 +1030,7 @@ gst_v4l2_allocator_clear_userptr (GstV4l2Allocator * allocator, group->planes[i].m.userptr = 0; } - if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { group->buffer.bytesused = 0; group->buffer.length = 0; group->buffer.m.userptr = 0; @@ -1068,6 +1074,7 @@ gboolean gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group, gint n_mem, GstMemory ** dma_mem) { + GstV4l2Object *obj = allocator->obj; GstV4l2Memory *mem; gint i; @@ -1106,7 +1113,7 @@ gst_v4l2_allocator_import_dmabuf (GstV4l2Allocator * allocator, } /* Copy into buffer structure if not using planes */ - if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { group->buffer.bytesused = group->planes[0].bytesused; group->buffer.length = group->planes[0].length; group->buffer.m.fd = group->planes[0].m.userptr; @@ -1140,24 +1147,25 @@ gst_v4l2_allocator_import_userptr (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group, gsize img_size, int n_planes, gpointer * data, gsize * size) { + GstV4l2Object *obj = allocator->obj; GstV4l2Memory *mem; gint i; g_return_val_if_fail (allocator->memory == V4L2_MEMORY_USERPTR, FALSE); /* TODO Support passing N plane from 1 memory to MPLANE v4l2 format */ - if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type) && n_planes != group->n_mem) + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type) && n_planes != group->n_mem) goto n_mem_missmatch; for (i = 0; i < group->n_mem; i++) { gsize maxsize, psize; - if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { - struct v4l2_pix_format_mplane *pix = &allocator->format.fmt.pix_mp; + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { + struct v4l2_pix_format_mplane *pix = &obj->format.fmt.pix_mp; maxsize = pix->plane_fmt[i].sizeimage; psize = size[i]; } else { - maxsize = allocator->format.fmt.pix.sizeimage; + maxsize = obj->format.fmt.pix.sizeimage; psize = img_size; } @@ -1179,7 +1187,7 @@ gst_v4l2_allocator_import_userptr (GstV4l2Allocator * allocator, } /* Copy into buffer structure if not using planes */ - if (!V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (!V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { group->buffer.bytesused = group->planes[0].bytesused; group->buffer.length = group->planes[0].length; group->buffer.m.userptr = group->planes[0].m.userptr; @@ -1229,13 +1237,14 @@ gboolean gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group) { + GstV4l2Object *obj = allocator->obj; gboolean ret = TRUE; gint i; g_return_val_if_fail (g_atomic_int_get (&allocator->active), FALSE); /* update sizes */ - if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { for (i = 0; i < group->n_mem; i++) group->planes[i].bytesused = gst_memory_get_sizes (group->mem[i], NULL, NULL); @@ -1247,7 +1256,7 @@ gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator, for (i = 0; i < group->n_mem; i++) gst_memory_ref (group->mem[i]); - if (v4l2_ioctl (allocator->video_fd, VIDIOC_QBUF, &group->buffer) < 0) { + if (obj->ioctl (obj->video_fd, VIDIOC_QBUF, &group->buffer) < 0) { GST_ERROR_OBJECT (allocator, "failed queueing buffer %i: %s", group->buffer.index, g_strerror (errno)); @@ -1281,6 +1290,7 @@ GstFlowReturn gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator, GstV4l2MemoryGroup ** group_out) { + GstV4l2Object *obj = allocator->obj; struct v4l2_buffer buffer = { 0 }; struct v4l2_plane planes[VIDEO_MAX_PLANES] = { {0} }; gint i; @@ -1289,15 +1299,15 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator, g_return_val_if_fail (g_atomic_int_get (&allocator->active), GST_FLOW_ERROR); - buffer.type = allocator->type; + buffer.type = obj->type; buffer.memory = allocator->memory; - if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { - buffer.length = allocator->format.fmt.pix_mp.num_planes; + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { + buffer.length = obj->format.fmt.pix_mp.num_planes; buffer.m.planes = planes; } - if (v4l2_ioctl (allocator->video_fd, VIDIOC_DQBUF, &buffer) < 0) + if (obj->ioctl (obj->video_fd, VIDIOC_DQBUF, &buffer) < 0) goto error; group = allocator->groups[buffer.index]; @@ -1319,7 +1329,7 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator, UNSET_QUEUED (group->buffer); } - if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) { + if (V4L2_TYPE_IS_MULTIPLANAR (obj->type)) { group->buffer.m.planes = group->planes; memcpy (group->planes, buffer.m.planes, sizeof (planes)); } else { @@ -1330,7 +1340,7 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator, } /* And update memory size */ - if (V4L2_TYPE_IS_OUTPUT (allocator->type)) { + if (V4L2_TYPE_IS_OUTPUT (obj->type)) { gst_v4l2_allocator_reset_size (allocator, group); } else { /* for capture, simply read the size */ diff --git a/sys/v4l2/gstv4l2allocator.h b/sys/v4l2/gstv4l2allocator.h index a260389..9826815 100644 --- a/sys/v4l2/gstv4l2allocator.h +++ b/sys/v4l2/gstv4l2allocator.h @@ -50,6 +50,7 @@ typedef struct _GstV4l2MemoryGroup GstV4l2MemoryGroup; typedef struct _GstV4l2Memory GstV4l2Memory; typedef enum _GstV4l2Capabilities GstV4l2Capabilities; typedef enum _GstV4l2Return GstV4l2Return; +typedef struct _GstV4l2Object GstV4l2Object; enum _GstV4l2AllocatorFlags { @@ -89,11 +90,9 @@ struct _GstV4l2MemoryGroup struct _GstV4l2Allocator { GstAllocator parent; - gint video_fd; + GstV4l2Object *obj; guint32 count; - guint32 type; guint32 memory; - struct v4l2_format format; gboolean can_allocate; gboolean active; @@ -117,8 +116,7 @@ gboolean gst_v4l2_allocator_is_active (GstV4l2Allocator * alloc guint gst_v4l2_allocator_get_size (GstV4l2Allocator * allocator); -GstV4l2Allocator* gst_v4l2_allocator_new (GstObject *parent, gint video_fd, - struct v4l2_format * format); +GstV4l2Allocator* gst_v4l2_allocator_new (GstObject *parent, GstV4l2Object * obj); guint gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint32 count, guint32 memory); diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index edfba00..46c6691 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -621,7 +621,7 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool) case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_DMABUF_IMPORT: 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; pool->streaming = TRUE; @@ -654,7 +654,7 @@ gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool) case GST_V4L2_IO_DMABUF: case GST_V4L2_IO_DMABUF_IMPORT: 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)", errno, g_strerror (errno)); @@ -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 * driver. */ if (obj->device_caps & V4L2_CAP_STREAMING) - v4l2_read (obj->video_fd, NULL, 0); + obj->read (obj->video_fd, NULL, 0); #endif break; case GST_V4L2_IO_DMABUF: @@ -1609,8 +1609,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps) pool->obj = obj; pool->can_poll_device = TRUE; - pool->vallocator = - gst_v4l2_allocator_new (GST_OBJECT (pool), obj->video_fd, &obj->format); + pool->vallocator = gst_v4l2_allocator_new (GST_OBJECT (pool), obj); if (pool->vallocator == NULL) goto allocator_failed; @@ -1657,7 +1656,7 @@ gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf) if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK) goto poll_error; - amount = v4l2_read (obj->video_fd, map.data, toread); + amount = obj->read (obj->video_fd, map.data, toread); if (amount == toread) { break; diff --git a/sys/v4l2/gstv4l2h264enc.c b/sys/v4l2/gstv4l2h264enc.c index 0a1faec..3d5b16b 100644 --- a/sys/v4l2/gstv4l2h264enc.c +++ b/sys/v4l2/gstv4l2h264enc.c @@ -329,7 +329,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s, if (control.value < 0) 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'", g_strerror (errno)); break; @@ -371,7 +371,7 @@ negotiate_profile_and_level (GstCapsFeatures * features, GstStructure * s, if (control.value < 0) 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'", g_strerror (errno)); break; @@ -436,7 +436,7 @@ gst_v4l2_h264_enc_negotiate (GstVideoEncoder * encoder) 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; ctx.profile = v4l2_profile_to_string (control.value); @@ -447,7 +447,7 @@ gst_v4l2_h264_enc_negotiate (GstVideoEncoder * encoder) 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; ctx.level = v4l2_level_to_string (control.value); diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index 859925e..adf2fa3 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include + #ifdef HAVE_GUDEV #include @@ -490,6 +493,28 @@ gst_v4l2_object_new (GstElement * element, 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; } @@ -775,7 +800,7 @@ gst_v4l2_get_driver_min_buffers (GstV4l2Object * v4l2object) else 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, "driver requires a minimum of %d buffers", control.value); v4l2object->min_buffers = control.value; @@ -1113,7 +1138,7 @@ gst_v4l2_object_fill_format_list (GstV4l2Object * v4l2object, format->index = n; 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) { g_free (format); break; /* end of enumeration */ @@ -2065,7 +2090,7 @@ gst_v4l2_object_try_fmt (GstV4l2Object * v4l2object, int r; 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) { /* The driver might not implement TRY_FMT, in which case we will try @@ -2074,7 +2099,7 @@ gst_v4l2_object_try_fmt (GstV4l2Object * v4l2object, goto error; 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)); @@ -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 * 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; if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { @@ -2296,7 +2321,7 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object, gst_value_list_append_value (&rates, &rate); 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) { GValue min = { 0, }; GValue step = { 0, }; @@ -2535,7 +2560,7 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object, "Enumerating frame sizes for %" GST_FOURCC_FORMAT, 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; if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { @@ -2556,7 +2581,7 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object, } 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, "done iterating discrete frame sizes"); } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { @@ -3369,10 +3394,10 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, } 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; } else { - if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) + if (v4l2object->ioctl (fd, VIDIOC_S_FMT, &format) < 0) goto set_fmt_failed; } @@ -3454,7 +3479,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, ctl.id = V4L2_CID_ALPHA_COMPONENT; 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, "Failed to set alpha component value"); } @@ -3466,7 +3491,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, memset (&streamparm, 0x00, sizeof (struct v4l2_streamparm)); 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; if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE @@ -3500,7 +3525,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, streamparm.parm.capture.timeperframe.denominator = fps_n; /* 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; if (streamparm.parm.capture.timeperframe.numerator > 0 && @@ -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.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; if (streamparm.parm.output.timeperframe.numerator > 0 && @@ -3750,7 +3775,7 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info) memset (&fmt, 0x00, sizeof (struct v4l2_format)); 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; fmtdesc = gst_v4l2_object_get_format_from_fourcc (v4l2object, @@ -3775,13 +3800,13 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info) memset (&sel, 0, sizeof (struct v4l2_selection)); sel.type = v4l2object->type; 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; } else { /* For ancient kernels, fall back to G_CROP */ memset (&crop, 0, sizeof (struct v4l2_crop)); 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; } if (r) { @@ -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, 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"); 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"); return FALSE; } @@ -3972,7 +3997,7 @@ gst_v4l2_object_probe_caps (GstV4l2Object * v4l2object, GstCaps * filter) memset (&cropcap, 0, sizeof (cropcap)); 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) GST_WARNING_OBJECT (v4l2object->element, "Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: %s", diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index 0df840e..b39687d 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -24,23 +24,11 @@ #ifndef __GST_V4L2_OBJECT_H__ #define __GST_V4L2_OBJECT_H__ +#include "ext/videodev2.h" #ifdef HAVE_LIBV4L2 # include -#else -# include "ext/videodev2.h" -# include -# include -# include -# 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 -#include "ext/videodev2.h" #include "v4l2-utils.h" #include @@ -212,6 +200,16 @@ struct _GstV4l2Object { GstV4l2SetInOutFunction set_in_out_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 */ /* Skips interlacing probes */ gboolean never_interlaced; diff --git a/sys/v4l2/gstv4l2radio.c b/sys/v4l2/gstv4l2radio.c index 77e4715..4e1aec3 100644 --- a/sys/v4l2/gstv4l2radio.c +++ b/sys/v4l2/gstv4l2radio.c @@ -86,7 +86,7 @@ gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio) 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) goto caps_failed; @@ -102,7 +102,7 @@ gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio) memset (&vtun, 0, sizeof (vtun)); 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) goto tuner_failed; diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c index 3295947..c77227c 100644 --- a/sys/v4l2/gstv4l2sink.c +++ b/sys/v4l2/gstv4l2sink.c @@ -246,16 +246,16 @@ gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink) if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { - gint fd = v4l2sink->v4l2object->video_fd; + GstV4l2Object *obj = v4l2sink->v4l2object; struct v4l2_format 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; else 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"); return; } @@ -275,7 +275,7 @@ gst_v4l2sink_sync_overlay_fields (GstV4l2Sink * v4l2sink) if (v4l2sink->overlay_fields_set & RECT_HEIGHT_SET) 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"); return; } @@ -293,13 +293,13 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink) if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { - gint fd = v4l2sink->v4l2object->video_fd; + GstV4l2Object *obj = v4l2sink->v4l2object; struct v4l2_crop crop; memset (&crop, 0x00, sizeof (struct v4l2_crop)); 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"); return; } @@ -319,12 +319,12 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink) if (v4l2sink->crop_fields_set & RECT_HEIGHT_SET) 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"); 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"); return; } diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 807a3a7..b445e5c 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -38,6 +38,10 @@ * ]| This pipeline shows the video captured from a webcam that delivers jpeg * images. * + * + * 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 diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c index 1550c46..4a65002 100644 --- a/sys/v4l2/gstv4l2videodec.c +++ b/sys/v4l2/gstv4l2videodec.c @@ -311,7 +311,7 @@ gst_v4l2_decoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags) dcmd.cmd = cmd; 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; return TRUE; diff --git a/sys/v4l2/gstv4l2videoenc.c b/sys/v4l2/gstv4l2videoenc.c index 644141f..79949ba 100644 --- a/sys/v4l2/gstv4l2videoenc.c +++ b/sys/v4l2/gstv4l2videoenc.c @@ -241,7 +241,7 @@ gst_v4l2_encoder_cmd (GstV4l2Object * v4l2object, guint cmd, guint flags) ecmd.cmd = cmd; 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; return TRUE; diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c index b12efe0..f52bd99 100644 --- a/sys/v4l2/v4l2_calls.c +++ b/sys/v4l2/v4l2_calls.c @@ -68,7 +68,8 @@ gst_v4l2_get_capabilities (GstV4l2Object * v4l2object) if (!GST_V4L2_IS_OPEN (v4l2object)) 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; if (v4l2object->vcap.capabilities & V4L2_CAP_DEVICE_CAPS) @@ -147,7 +148,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object) memset (&input, 0, sizeof (input)); 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) break; /* end of enumeration */ else { @@ -181,7 +182,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object) channel->flags |= GST_TUNER_CHANNEL_FREQUENCY; 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, (_("Failed to get setting of tuner %d on device '%s'."), input.tuner, v4l2object->videodev), GST_ERROR_SYSTEM); @@ -222,7 +223,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object) standard.frameperiod.denominator = 0; standard.index = n; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) { + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) { if (errno == EINVAL || errno == ENOTTY) break; /* end of enumeration */ #ifdef ENODATA @@ -280,7 +281,8 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object) GST_DEBUG_OBJECT (e, "checking control %08x", n); control.id = n | next; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL, &control) < 0) { + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL, + &control) < 0) { if (next) { if (n > 0) { GST_DEBUG_OBJECT (e, "controls finished"); @@ -405,7 +407,8 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object) menu.id = n; for (i = 0;; i++) { menu.index = i; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYMENU, &menu) < 0) { + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYMENU, + &menu) < 0) { if (errno == EINVAL) break; /* end of enumeration */ else { @@ -515,7 +518,7 @@ gboolean gst_v4l2_open (GstV4l2Object * v4l2object) { struct stat st; - int libv4l2_fd; + int libv4l2_fd = -1; GST_DEBUG_OBJECT (v4l2object->element, "Trying to open device %s", v4l2object->videodev); @@ -541,8 +544,12 @@ gst_v4l2_open (GstV4l2Object * v4l2object) if (!GST_V4L2_IS_OPEN (v4l2object)) goto not_open; - libv4l2_fd = v4l2_fd_open (v4l2object->video_fd, - V4L2_ENABLE_ENUM_FMT_EMULATION); +#ifdef HAVE_LIBV4L2 + if (v4l2object->fd_open) + libv4l2_fd = v4l2object->fd_open (v4l2object->video_fd, + V4L2_ENABLE_ENUM_FMT_EMULATION); +#endif + /* Note the v4l2_xxx functions are designed so that if they get passed an unknown fd, the will behave exactly as their regular xxx counterparts, so if v4l2_fd_open fails, we continue as normal (missing the libv4l2 custom @@ -651,7 +658,7 @@ error: { if (GST_V4L2_IS_OPEN (v4l2object)) { /* close device */ - v4l2_close (v4l2object->video_fd); + v4l2object->close (v4l2object->video_fd); v4l2object->video_fd = -1; } /* empty lists */ @@ -676,7 +683,7 @@ gst_v4l2_dup (GstV4l2Object * v4l2object, GstV4l2Object * other) v4l2object->device_caps = other->device_caps; gst_v4l2_adjust_buf_type (v4l2object); - v4l2object->video_fd = v4l2_dup (other->video_fd); + v4l2object->video_fd = v4l2object->dup (other->video_fd); if (!GST_V4L2_IS_OPEN (v4l2object)) goto not_open; @@ -717,7 +724,7 @@ gst_v4l2_close (GstV4l2Object * v4l2object) GST_V4L2_CHECK_NOT_ACTIVE (v4l2object); /* close device */ - v4l2_close (v4l2object->video_fd); + v4l2object->close (v4l2object->video_fd); v4l2object->video_fd = -1; /* empty lists */ @@ -740,7 +747,7 @@ gst_v4l2_get_norm (GstV4l2Object * v4l2object, v4l2_std_id * norm) if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_STD, norm) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_STD, norm) < 0) goto std_failed; return TRUE; @@ -769,7 +776,7 @@ gst_v4l2_set_norm (GstV4l2Object * v4l2object, v4l2_std_id norm) if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_STD, &norm) < 0) goto std_failed; return TRUE; @@ -805,7 +812,7 @@ gst_v4l2_get_frequency (GstV4l2Object * v4l2object, channel = gst_tuner_get_channel (GST_TUNER (v4l2object->element)); freq.tuner = tunernum; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) goto freq_failed; *frequency = freq.frequency * channel->freq_multiplicator; @@ -846,10 +853,10 @@ gst_v4l2_set_frequency (GstV4l2Object * v4l2object, freq.tuner = tunernum; /* fill in type - ignore error */ - (void) v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq); + (void) v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_FREQUENCY, &freq); freq.frequency = frequency / channel->freq_multiplicator; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) goto freq_failed; return TRUE; @@ -881,7 +888,7 @@ gst_v4l2_signal_strength (GstV4l2Object * v4l2object, return FALSE; tuner.index = tunernum; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &tuner) < 0) goto tuner_failed; *signal_strength = tuner.signal; @@ -917,7 +924,7 @@ gst_v4l2_get_attribute (GstV4l2Object * v4l2object, control.id = attribute_num; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) goto ctrl_failed; *value = control.value; @@ -954,7 +961,7 @@ gst_v4l2_set_attribute (GstV4l2Object * v4l2object, control.id = attribute_num; control.value = value; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) goto ctrl_failed; return TRUE; @@ -1027,7 +1034,7 @@ gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input) if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_INPUT, &n) < 0) goto input_failed; *input = n; @@ -1056,7 +1063,7 @@ gst_v4l2_set_input (GstV4l2Object * v4l2object, gint input) if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_INPUT, &input) < 0) goto input_failed; return TRUE; @@ -1084,7 +1091,7 @@ gst_v4l2_get_output (GstV4l2Object * v4l2object, gint * output) if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_OUTPUT, &n) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_OUTPUT, &n) < 0) goto output_failed; *output = n; @@ -1113,7 +1120,7 @@ gst_v4l2_set_output (GstV4l2Object * v4l2object, gint output) if (!GST_V4L2_IS_OPEN (v4l2object)) return FALSE; - if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_OUTPUT, &output) < 0) + if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_OUTPUT, &output) < 0) goto output_failed; return TRUE; -- 2.7.4