mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
v4l2decoder: Track pending request
With the asynchronous slice decoding, we only queue up to 2 slices per frames. That side effect is that now we are dequeuing bitstream buffers in both decoding and presentation order. This would lead to a bitstream buffer from a previous frame being dequeued instead of the expected last slice buffer and lead to us trying to queue an already queued bitstream buffer. We now fix this by tracking pending requests. As request are executed in decoding order, we marking a request done, we can effectively dequeue bitstream buffer from all previous request, as they have been executed already. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1395>
This commit is contained in:
parent
a88e63dd2f
commit
1bef43f9d4
1 changed files with 38 additions and 3 deletions
|
@ -63,6 +63,7 @@ struct _GstV4l2Decoder
|
|||
gint media_fd;
|
||||
gint video_fd;
|
||||
GstQueueArray *request_pool;
|
||||
GstQueueArray *pending_requests;
|
||||
|
||||
enum v4l2_buf_type src_buf_type;
|
||||
enum v4l2_buf_type sink_buf_type;
|
||||
|
@ -104,6 +105,7 @@ static void
|
|||
gst_v4l2_decoder_init (GstV4l2Decoder * self)
|
||||
{
|
||||
self->request_pool = gst_queue_array_new (16);
|
||||
self->pending_requests = gst_queue_array_new (16);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -223,8 +225,18 @@ gst_v4l2_decoder_streamon (GstV4l2Decoder * self, GstPadDirection direction)
|
|||
gboolean
|
||||
gst_v4l2_decoder_streamoff (GstV4l2Decoder * self, GstPadDirection direction)
|
||||
{
|
||||
gint ret;
|
||||
GstV4l2Request *pending_req;
|
||||
guint32 type = direction_to_buffer_type (self, direction);
|
||||
gint ret;
|
||||
|
||||
if (direction == GST_PAD_SRC) {
|
||||
/* STREAMOFF have the effect of cancelling all requests and unqueuing all
|
||||
* buffers, so clear the pending request list */
|
||||
while ((pending_req = gst_queue_array_pop_head (self->pending_requests))) {
|
||||
g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
|
||||
pending_req->pending = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ioctl (self->video_fd, VIDIOC_STREAMOFF, &type);
|
||||
if (ret < 0) {
|
||||
|
@ -838,7 +850,14 @@ gst_v4l2_request_free (GstV4l2Request * request)
|
|||
request->decoder = NULL;
|
||||
|
||||
if (request->pending) {
|
||||
gint idx;
|
||||
|
||||
GST_DEBUG_OBJECT (decoder, "Freeing pending request %p.", request);
|
||||
|
||||
idx = gst_queue_array_find (decoder->pending_requests, NULL, NULL);
|
||||
if (idx >= 0)
|
||||
gst_queue_array_drop_element (decoder->pending_requests, idx);
|
||||
|
||||
gst_v4l2_request_free (request);
|
||||
g_object_unref (decoder);
|
||||
return;
|
||||
|
@ -874,6 +893,7 @@ gst_v4l2_request_queue (GstV4l2Request * request)
|
|||
}
|
||||
|
||||
request->pending = TRUE;
|
||||
gst_queue_array_push_tail (request->decoder->pending_requests, request);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -888,8 +908,23 @@ void
|
|||
gst_v4l2_request_set_done (GstV4l2Request * request)
|
||||
{
|
||||
if (request->bitstream) {
|
||||
gst_v4l2_decoder_dequeue_sink (request->decoder);
|
||||
g_clear_pointer (&request->bitstream, gst_memory_unref);
|
||||
GstV4l2Decoder *dec = request->decoder;
|
||||
GstV4l2Request *pending_req;
|
||||
|
||||
while ((pending_req = gst_queue_array_pop_head (dec->pending_requests))) {
|
||||
gst_v4l2_decoder_dequeue_sink (request->decoder);
|
||||
g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
|
||||
|
||||
if (pending_req == request)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Pending request should always be found in the fifo */
|
||||
if (pending_req != request) {
|
||||
g_warning ("Pending request not found in the pending list.");
|
||||
gst_v4l2_decoder_dequeue_sink (request->decoder);
|
||||
g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
|
||||
}
|
||||
}
|
||||
|
||||
request->pending = FALSE;
|
||||
|
|
Loading…
Reference in a new issue