diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c index 0281fc560f..05bde3d2a5 100644 --- a/sys/v4l2/gstv4l2allocator.c +++ b/sys/v4l2/gstv4l2allocator.c @@ -503,6 +503,9 @@ gst_v4l2_allocator_probe (GstV4l2Allocator * allocator, guint32 memory, flags |= bcreate_flag; } + if (breq.capabilities & V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS) + flags |= GST_V4L2_ALLOCATOR_FLAG_SUPPORTS_ORPHANED_BUFS; + return flags; } @@ -518,6 +521,9 @@ gst_v4l2_allocator_create_buf (GstV4l2Allocator * allocator) if (!g_atomic_int_get (&allocator->active)) goto done; + if (GST_V4L2_ALLOCATOR_IS_ORPHANED (allocator)) + goto orphaned_bug; + bcreate.memory = allocator->memory; bcreate.format = obj->format; bcreate.count = 1; @@ -542,6 +548,12 @@ done: GST_OBJECT_UNLOCK (allocator); return group; +orphaned_bug: + { + GST_ERROR_OBJECT (allocator, "allocator was orphaned, " + "not creating new buffers"); + goto done; + } create_bufs_failed: { GST_WARNING_OBJECT (allocator, "error creating a new buffer: %s", @@ -667,6 +679,9 @@ gst_v4l2_allocator_start (GstV4l2Allocator * allocator, guint32 count, if (g_atomic_int_get (&allocator->active)) goto already_active; + if (GST_V4L2_ALLOCATOR_IS_ORPHANED (allocator)) + goto orphaned; + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) goto reqbufs_failed; @@ -715,6 +730,11 @@ already_active: GST_ERROR_OBJECT (allocator, "allocator already active"); goto error; } +orphaned: + { + GST_ERROR_OBJECT (allocator, "allocator was orphaned"); + goto error; + } reqbufs_failed: { GST_ERROR_OBJECT (allocator, @@ -765,10 +785,12 @@ gst_v4l2_allocator_stop (GstV4l2Allocator * allocator) gst_v4l2_memory_group_free (group); } - /* Not all drivers support rebufs(0), so warn only */ - if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) - GST_WARNING_OBJECT (allocator, - "error releasing buffers buffers: %s", g_strerror (errno)); + if (!GST_V4L2_ALLOCATOR_IS_ORPHANED (allocator)) { + /* Not all drivers support rebufs(0), so warn only */ + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) + GST_WARNING_OBJECT (allocator, + "error releasing buffers buffers: %s", g_strerror (errno)); + } allocator->count = 0; @@ -779,6 +801,26 @@ done: return ret; } +gboolean +gst_v4l2_allocator_orphan (GstV4l2Allocator * allocator) +{ + GstV4l2Object *obj = allocator->obj; + struct v4l2_requestbuffers breq = { 0, obj->type, allocator->memory }; + + if (!GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS (allocator)) + return FALSE; + + GST_OBJECT_FLAG_SET (allocator, GST_V4L2_ALLOCATOR_FLAG_ORPHANED); + + if (obj->ioctl (obj->video_fd, VIDIOC_REQBUFS, &breq) < 0) { + GST_ERROR_OBJECT (allocator, + "error orphaning buffers buffers: %s", g_strerror (errno)); + return FALSE; + } + + return TRUE; +} + GstV4l2MemoryGroup * gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator) { diff --git a/sys/v4l2/gstv4l2allocator.h b/sys/v4l2/gstv4l2allocator.h index 25337138e0..eb515245a1 100644 --- a/sys/v4l2/gstv4l2allocator.h +++ b/sys/v4l2/gstv4l2allocator.h @@ -41,6 +41,10 @@ G_BEGIN_DECLS (GST_OBJECT_FLAG_IS_SET (obj, GST_V4L2_ALLOCATOR_FLAG_ ## type ## _REQBUFS)) #define GST_V4L2_ALLOCATOR_CAN_ALLOCATE(obj,type) \ (GST_OBJECT_FLAG_IS_SET (obj, GST_V4L2_ALLOCATOR_FLAG_ ## type ## _CREATE_BUFS)) +#define GST_V4L2_ALLOCATOR_CAN_ORPHAN_BUFS(obj) \ + (GST_OBJECT_FLAG_IS_SET (obj, GST_V4L2_ALLOCATOR_FLAG_SUPPORTS_ORPHANED_BUFS)) +#define GST_V4L2_ALLOCATOR_IS_ORPHANED(obj) \ + (GST_OBJECT_FLAG_IS_SET (obj, GST_V4L2_ALLOCATOR_FLAG_ORPHANED)) #define GST_V4L2_MEMORY_QUARK gst_v4l2_memory_quark () @@ -59,6 +63,8 @@ enum _GstV4l2AllocatorFlags GST_V4L2_ALLOCATOR_FLAG_USERPTR_CREATE_BUFS = (GST_ALLOCATOR_FLAG_LAST << 3), GST_V4L2_ALLOCATOR_FLAG_DMABUF_REQBUFS = (GST_ALLOCATOR_FLAG_LAST << 4), GST_V4L2_ALLOCATOR_FLAG_DMABUF_CREATE_BUFS = (GST_ALLOCATOR_FLAG_LAST << 5), + GST_V4L2_ALLOCATOR_FLAG_SUPPORTS_ORPHANED_BUFS = (GST_ALLOCATOR_FLAG_LAST << 6), + GST_V4L2_ALLOCATOR_FLAG_ORPHANED = (GST_ALLOCATOR_FLAG_LAST << 7), }; enum _GstV4l2Return @@ -122,6 +128,8 @@ guint gst_v4l2_allocator_start (GstV4l2Allocator * alloc GstV4l2Return gst_v4l2_allocator_stop (GstV4l2Allocator * allocator); +gboolean gst_v4l2_allocator_orphan (GstV4l2Allocator * allocator); + GstV4l2MemoryGroup* gst_v4l2_allocator_alloc_mmap (GstV4l2Allocator * allocator); GstV4l2MemoryGroup* gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,