v4l2allocator: support orphaning

Recent kernels allow REQBUFS(0) on a queue that still has buffers in
use (mmapped or exported via dmabuf), orphaning all buffers on the queue.

Orphaning the allocator causes it to release all buffers with
REQBUFS(0), even if they are still in use. An orphaned allocator can
only be stopped. It can not be restarted or create new buffers.
This commit is contained in:
Philipp Zabel 2019-01-24 16:12:13 +01:00 committed by Nicolas Dufresne
parent 5d904530c1
commit 0948ce0478
2 changed files with 54 additions and 4 deletions

View file

@ -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)
{

View file

@ -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,