From 1c2f391b57014d6e610f0a9c2cbf916ca86f150d Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Fri, 18 Dec 2020 16:36:16 -0500 Subject: [PATCH] v4l2codecs: Make request structure ref-counted This adds a non-thread safe refcount to the GstV4l2Request. This will allow holding on more then one request in order to implement render delay. This is made non-thread safe for speed as we know this will all happen on the same streaming thread. Part-of: --- sys/v4l2codecs/gstv4l2codech264dec.c | 4 +-- sys/v4l2codecs/gstv4l2codecvp8dec.c | 2 +- sys/v4l2codecs/gstv4l2decoder.c | 52 +++++++++++++++++++++------- sys/v4l2codecs/gstv4l2decoder.h | 4 ++- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/sys/v4l2codecs/gstv4l2codech264dec.c b/sys/v4l2codecs/gstv4l2codech264dec.c index f554f99277..3af80c1d11 100644 --- a/sys/v4l2codecs/gstv4l2codech264dec.c +++ b/sys/v4l2codecs/gstv4l2codech264dec.c @@ -1002,12 +1002,12 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self, } gst_h264_picture_set_user_data (picture, g_steal_pointer (&request), - (GDestroyNotify) gst_v4l2_request_free); + (GDestroyNotify) gst_v4l2_request_unref); ret = TRUE; done: if (request) - gst_v4l2_request_free (request); + gst_v4l2_request_unref (request); gst_v4l2_codec_h264_dec_reset_picture (self); diff --git a/sys/v4l2codecs/gstv4l2codecvp8dec.c b/sys/v4l2codecs/gstv4l2codecvp8dec.c index ca5267b630..078331341c 100644 --- a/sys/v4l2codecs/gstv4l2codecvp8dec.c +++ b/sys/v4l2codecs/gstv4l2codecvp8dec.c @@ -571,7 +571,7 @@ gst_v4l2_codec_vp8_dec_end_picture (GstVp8Decoder * decoder, } gst_vp8_picture_set_user_data (picture, request, - (GDestroyNotify) gst_v4l2_request_free); + (GDestroyNotify) gst_v4l2_request_unref); if (!gst_v4l2_decoder_set_controls (self->decoder, request, control, G_N_ELEMENTS (control))) { diff --git a/sys/v4l2codecs/gstv4l2decoder.c b/sys/v4l2codecs/gstv4l2decoder.c index 533ce3d443..5a585e3ac8 100644 --- a/sys/v4l2codecs/gstv4l2decoder.c +++ b/sys/v4l2codecs/gstv4l2decoder.c @@ -47,6 +47,9 @@ enum struct _GstV4l2Request { + /* non-thread safe */ + gint ref_count; + GstV4l2Decoder *decoder; gint fd; guint32 frame_num; @@ -85,6 +88,8 @@ G_DEFINE_TYPE_WITH_CODE (GstV4l2Decoder, gst_v4l2_decoder, GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (v4l2_decoder_debug, "v4l2codecs-decoder", 0, "V4L2 stateless decoder helper")); +static void gst_v4l2_request_free (GstV4l2Request * request); + static guint32 direction_to_buffer_type (GstV4l2Decoder * self, GstPadDirection direction) { @@ -199,6 +204,9 @@ gst_v4l2_decoder_close (GstV4l2Decoder * self) { GstV4l2Request *request; + while ((request = gst_queue_array_pop_head (self->pending_requests))) + gst_v4l2_request_unref (request); + while ((request = gst_queue_array_pop_head (self->request_pool))) gst_v4l2_request_free (request); @@ -243,6 +251,7 @@ gst_v4l2_decoder_streamoff (GstV4l2Decoder * self, GstPadDirection direction) while ((pending_req = gst_queue_array_pop_head (self->pending_requests))) { g_clear_pointer (&pending_req->bitstream, gst_memory_unref); pending_req->pending = FALSE; + gst_v4l2_request_unref (pending_req); } } @@ -854,6 +863,7 @@ gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self, guint32 frame_num, request->bitstream = gst_memory_ref (bitstream); request->pic_buf = gst_buffer_ref (pic_buf); request->frame_num = frame_num; + request->ref_count = 1; return request; } @@ -900,23 +910,42 @@ gst_v4l2_decoder_alloc_sub_request (GstV4l2Decoder * self, request->pic_buf = gst_buffer_ref (prev_request->pic_buf); request->frame_num = prev_request->frame_num; request->sub_request = TRUE; + request->ref_count = 1; return request; } +GstV4l2Request * +gst_v4l2_request_ref (GstV4l2Request * request) +{ + request->ref_count++; + return request; +} + +static void +gst_v4l2_request_free (GstV4l2Request * request) +{ + GstV4l2Decoder *decoder = request->decoder; + + request->decoder = NULL; + close (request->fd); + gst_poll_free (request->poll); + g_free (request); + + if (decoder) + g_object_unref (decoder); +} void -gst_v4l2_request_free (GstV4l2Request * request) +gst_v4l2_request_unref (GstV4l2Request * request) { GstV4l2Decoder *decoder = request->decoder; gint ret; - if (!decoder) { - close (request->fd); - gst_poll_free (request->poll); - g_free (request); + g_return_if_fail (request->ref_count > 0); + + if (--request->ref_count > 0) return; - } g_clear_pointer (&request->bitstream, gst_memory_unref); g_clear_pointer (&request->pic_buf, gst_buffer_unref); @@ -924,7 +953,6 @@ gst_v4l2_request_free (GstV4l2Request * request) request->failed = FALSE; request->hold_pic_buf = FALSE; request->sub_request = FALSE; - request->decoder = NULL; if (request->pending) { gint idx; @@ -936,7 +964,6 @@ gst_v4l2_request_free (GstV4l2Request * request) gst_queue_array_drop_element (decoder->pending_requests, idx); gst_v4l2_request_free (request); - g_object_unref (decoder); return; } @@ -947,12 +974,11 @@ gst_v4l2_request_free (GstV4l2Request * request) GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_REINIT failed: %s", g_strerror (errno)); gst_v4l2_request_free (request); - g_object_unref (decoder); return; } gst_queue_array_push_tail (decoder->request_pool, request); - g_object_unref (decoder); + g_clear_object (&request->decoder); } gboolean @@ -986,11 +1012,12 @@ gst_v4l2_request_queue (GstV4l2Request * request, guint flags) request->hold_pic_buf = TRUE; request->pending = TRUE; - gst_queue_array_push_tail (decoder->pending_requests, request); + gst_queue_array_push_tail (decoder->pending_requests, + gst_v4l2_request_ref (request)); /* FIXME to support more then one pending requests, we need the request to * be refcounted */ - if (gst_queue_array_get_length (decoder->pending_requests) > 1) { + if (gst_queue_array_get_length (decoder->pending_requests) > 6) { GstV4l2Request *pending_req; pending_req = gst_queue_array_peek_head (decoder->pending_requests); @@ -1036,6 +1063,7 @@ gst_v4l2_request_set_done (GstV4l2Request * request) g_clear_pointer (&pending_req->pic_buf, gst_buffer_unref); pending_req->pending = FALSE; + gst_v4l2_request_unref (pending_req); if (pending_req == request) break; diff --git a/sys/v4l2codecs/gstv4l2decoder.h b/sys/v4l2codecs/gstv4l2decoder.h index e0f9cf8128..e83ed38793 100644 --- a/sys/v4l2codecs/gstv4l2decoder.h +++ b/sys/v4l2codecs/gstv4l2decoder.h @@ -108,7 +108,9 @@ GstV4l2Request *gst_v4l2_decoder_alloc_sub_request (GstV4l2Decoder * self, GstV4l2Request * prev_request, GstMemory *bitstream); -void gst_v4l2_request_free (GstV4l2Request * request); +GstV4l2Request * gst_v4l2_request_ref (GstV4l2Request * request); + +void gst_v4l2_request_unref (GstV4l2Request * request); gboolean gst_v4l2_request_queue (GstV4l2Request * request, guint flags);