mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
v4l2allocator: Guaranty queued state integrety
Because of the buf in videobuf2, dqbuf may leave the DONE flag being, which would implied that the buffer is queued. As this has been broken for 4 years, simply guaranty the state flags integrity when doing qbuf/dqbuf. See https://patchwork.linuxtv.org/patch/23641/
This commit is contained in:
parent
783417ee9f
commit
7b00d7ac46
1 changed files with 42 additions and 4 deletions
|
@ -33,6 +33,14 @@ G_DEFINE_TYPE (GstV4l2Allocator, gst_v4l2_allocator, GST_TYPE_ALLOCATOR);
|
|||
GST_DEBUG_CATEGORY_STATIC (v4l2allocator_debug);
|
||||
#define GST_CAT_DEFAULT v4l2allocator_debug
|
||||
|
||||
#define UNSET_QUEUED(buffer) \
|
||||
((buffer).flags &= ~(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
|
||||
|
||||
#define SET_QUEUED(buffer) ((buffer).flags |= V4L2_BUF_FLAG_QUEUED)
|
||||
|
||||
#define IS_QUEUED(buffer) \
|
||||
((buffer).flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
|
||||
|
||||
enum
|
||||
{
|
||||
GROUP_RELEASED,
|
||||
|
@ -787,11 +795,10 @@ gst_v4l2_allocator_flush (GstV4l2Allocator * allocator)
|
|||
|
||||
for (i = 0; i < allocator->count; i++) {
|
||||
GstV4l2MemoryGroup *group = allocator->groups[i];
|
||||
guint32 queued = (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE);
|
||||
gint n;
|
||||
|
||||
if (group->buffer.flags & queued) {
|
||||
group->buffer.flags &= ~queued;
|
||||
if (IS_QUEUED (group->buffer)) {
|
||||
UNSET_QUEUED (group->buffer);
|
||||
|
||||
for (n = 0; n < group->n_mem; n++)
|
||||
gst_memory_unref (group->mem[n]);
|
||||
|
@ -822,12 +829,28 @@ gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator,
|
|||
GST_ERROR_OBJECT (allocator, "failed queing buffer %i: %s",
|
||||
group->buffer.index, g_strerror (errno));
|
||||
ret = FALSE;
|
||||
if (IS_QUEUED (group->buffer)) {
|
||||
GST_DEBUG_OBJECT (allocator,
|
||||
"driver pretends buffer is queued even if queue failed");
|
||||
UNSET_QUEUED (group->buffer);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (allocator, "queued buffer %i (flags 0x%X)",
|
||||
group->buffer.index, group->buffer.flags);
|
||||
|
||||
if (!IS_QUEUED (group->buffer)) {
|
||||
GST_DEBUG_OBJECT (allocator,
|
||||
"driver pretends buffer is not queued even if queue succeeded");
|
||||
SET_QUEUED (group->buffer);
|
||||
}
|
||||
|
||||
/* Ensure the memory will stay around and is RO */
|
||||
for (i = 0; i < group->n_mem; i++)
|
||||
gst_memory_ref (group->mem[i]);
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -854,6 +877,15 @@ gst_v4l2_allocator_dqbuf (GstV4l2Allocator * allocator)
|
|||
group = allocator->groups[buffer.index];
|
||||
group->buffer = buffer;
|
||||
|
||||
GST_LOG_OBJECT (allocator, "dequeued buffer %i (flags 0x%X)", buffer.index,
|
||||
buffer.flags);
|
||||
|
||||
if (IS_QUEUED (group->buffer)) {
|
||||
GST_DEBUG_OBJECT (allocator,
|
||||
"driver pretends buffer is queued even if dequeue succeeded");
|
||||
UNSET_QUEUED (group->buffer);
|
||||
}
|
||||
|
||||
if (V4L2_TYPE_IS_MULTIPLANAR (allocator->type)) {
|
||||
group->buffer.m.planes = group->planes;
|
||||
memcpy (group->planes, buffer.m.planes, sizeof (planes));
|
||||
|
@ -907,7 +939,7 @@ error:
|
|||
" Note the driver might dequeue an (empty) buffer despite"
|
||||
" returning an error, or even stop capturing.");
|
||||
/* have we de-queued a buffer ? */
|
||||
if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
|
||||
if (!IS_QUEUED (buffer)) {
|
||||
GST_DEBUG_OBJECT (allocator, "reenqueing buffer");
|
||||
/* FIXME ... should we do something here? */
|
||||
}
|
||||
|
@ -921,6 +953,12 @@ error:
|
|||
g_strerror (errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!IS_QUEUED (group->buffer)) {
|
||||
GST_DEBUG_OBJECT (allocator,
|
||||
"driver pretends buffer is dequeued even if dequeue failed");
|
||||
SET_QUEUED (group->buffer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue