From 3db6f45ca902a88ae1a235136accede243a6a6c3 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 14 Dec 2020 17:07:01 -0500 Subject: [PATCH] v4l2codecs: Rework handling of queues and pending requests Starting from this patch, all queue and dequeue operation happening on V4L2 is now abstracted with the request. Buffers are dequeued automatically when pending requests are marked done and only 1 in-flight request is now used. Along with fixing issues with request not being reused with slice decoders, this change reduces the memory footprint by allocating only two bitstream buffers. Part-of: --- sys/v4l2codecs/gstv4l2codech264dec.c | 129 +++++++------------ sys/v4l2codecs/gstv4l2codecvp8dec.c | 64 ++++------ sys/v4l2codecs/gstv4l2decoder.c | 182 ++++++++++++++++++++++----- sys/v4l2codecs/gstv4l2decoder.h | 33 +++-- 4 files changed, 236 insertions(+), 172 deletions(-) diff --git a/sys/v4l2codecs/gstv4l2codech264dec.c b/sys/v4l2codecs/gstv4l2codech264dec.c index a24739ebf5..f554f99277 100644 --- a/sys/v4l2codecs/gstv4l2codech264dec.c +++ b/sys/v4l2codecs/gstv4l2codech264dec.c @@ -337,7 +337,7 @@ gst_v4l2_codec_h264_dec_decide_allocation (GstVideoDecoder * decoder, min = MAX (2, min); self->sink_allocator = gst_v4l2_codec_allocator_new (self->decoder, - GST_PAD_SINK, self->min_pool_size + 2); + GST_PAD_SINK, 2); self->src_allocator = gst_v4l2_codec_allocator_new (self->decoder, GST_PAD_SRC, self->min_pool_size + min + 4); self->src_pool = gst_v4l2_codec_pool_new (self->src_allocator, &self->vinfo); @@ -825,24 +825,6 @@ fail: return FALSE; } -static gboolean -gst_v4l2_codec_h264_dec_wait (GstV4l2CodecH264Dec * self, - GstV4l2Request * request) -{ - gint ret = gst_v4l2_request_poll (request, GST_SECOND); - if (ret == 0) { - GST_ELEMENT_ERROR (self, STREAM, DECODE, - ("Decoding frame took too long"), (NULL)); - return FALSE; - } else if (ret < 0) { - GST_ELEMENT_ERROR (self, STREAM, DECODE, - ("Decoding request failed: %s", g_strerror (errno)), (NULL)); - return FALSE; - } - - return TRUE; -} - static GstFlowReturn gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder, GstVideoCodecFrame * frame, GstH264Picture * picture) @@ -850,41 +832,35 @@ gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder, GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder); GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder); GstV4l2Request *request = gst_h264_picture_get_user_data (picture); + gint ret; GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); if (gst_v4l2_request_is_done (request)) goto finish_frame; - if (!gst_v4l2_codec_h264_dec_wait (self, request)) + ret = gst_v4l2_request_poll (request, GST_SECOND); + if (ret == 0) { + GST_ELEMENT_ERROR (self, STREAM, DECODE, + ("Decoding frame %u took too long", picture->system_frame_number), + (NULL)); + goto error; + } else if (ret < 0) { + GST_ELEMENT_ERROR (self, STREAM, DECODE, + ("Decoding request failed: %s", g_strerror (errno)), (NULL)); goto error; - - while (TRUE) { - guint32 frame_num; - GstH264Picture *other_pic; - GstV4l2Request *other_request; - - if (!gst_v4l2_decoder_dequeue_src (self->decoder, &frame_num)) { - GST_ELEMENT_ERROR (self, STREAM, DECODE, - ("Decoder did not produce a frame"), (NULL)); - goto error; - } - - if (frame_num == picture->system_frame_number) - break; - - other_pic = gst_h264_decoder_get_picture (decoder, frame_num); - if (other_pic) { - other_request = gst_h264_picture_get_user_data (other_pic); - gst_v4l2_request_set_done (other_request); - gst_h264_picture_unref (other_pic); - } } -finish_frame: gst_v4l2_request_set_done (request); g_return_val_if_fail (frame->output_buffer, GST_FLOW_ERROR); +finish_frame: + if (gst_v4l2_request_failed (request)) { + GST_ELEMENT_ERROR (self, STREAM, DECODE, + ("Failed to decode frame %u", picture->system_frame_number), (NULL)); + goto error; + } + /* Hold on reference buffers for the rest of the picture lifetime */ gst_h264_picture_set_user_data (picture, gst_buffer_ref (frame->output_buffer), (GDestroyNotify) gst_buffer_unref); @@ -937,14 +913,6 @@ gst_v4l2_codec_h264_dec_ensure_output_buffer (GstV4l2CodecH264Dec * self, return FALSE; } - if (!gst_v4l2_decoder_queue_src_buffer (self->decoder, buffer, - frame->system_frame_number)) { - GST_ELEMENT_ERROR (self, RESOURCE, WRITE, - ("Driver did not accept the picture buffer."), (NULL)); - gst_buffer_unref (buffer); - return FALSE; - } - frame->output_buffer = buffer; return TRUE; } @@ -953,8 +921,7 @@ static gboolean gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self, GstH264Picture * picture, guint flags) { - GstVideoCodecFrame *frame; - GstV4l2Request *prev_request, *request; + GstV4l2Request *prev_request, *request = NULL; gsize bytesused; gboolean ret = FALSE; @@ -989,23 +956,38 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self, }; /* *INDENT-ON* */ - request = gst_v4l2_decoder_alloc_request (self->decoder); + prev_request = gst_h264_picture_get_user_data (picture); + + bytesused = self->bitstream_map.size; + gst_memory_unmap (self->bitstream, &self->bitstream_map); + self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT; + gst_memory_resize (self->bitstream, 0, bytesused); + + if (prev_request) { + request = gst_v4l2_decoder_alloc_sub_request (self->decoder, prev_request, + self->bitstream); + } else { + GstVideoCodecFrame *frame; + + frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), + picture->system_frame_number); + g_return_val_if_fail (frame, FALSE); + + if (!gst_v4l2_codec_h264_dec_ensure_output_buffer (self, frame)) + goto done; + + request = gst_v4l2_decoder_alloc_request (self->decoder, + picture->system_frame_number, self->bitstream, frame->output_buffer); + + gst_video_codec_frame_unref (frame); + } + if (!request) { GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, ("Failed to allocate a media request object."), (NULL)); goto done; } - - frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), - picture->system_frame_number); - g_return_val_if_fail (frame, FALSE); - - if (!gst_v4l2_codec_h264_dec_ensure_output_buffer (self, frame)) - goto done; - - gst_video_codec_frame_unref (frame); - if (!gst_v4l2_decoder_set_controls (self->decoder, request, control, G_N_ELEMENTS (control))) { GST_ELEMENT_ERROR (self, RESOURCE, WRITE, @@ -1013,30 +995,12 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self, goto done; } - bytesused = self->bitstream_map.size; - gst_memory_unmap (self->bitstream, &self->bitstream_map); - self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT; - - if (!gst_v4l2_decoder_queue_sink_mem (self->decoder, request, self->bitstream, - picture->system_frame_number, bytesused, flags)) { - GST_ELEMENT_ERROR (self, RESOURCE, WRITE, - ("Driver did not accept the bitstream data."), (NULL)); - goto done; - } - - if (!gst_v4l2_request_queue (request)) { + if (!gst_v4l2_request_queue (request, flags)) { GST_ELEMENT_ERROR (self, RESOURCE, WRITE, ("Driver did not accept the decode request."), (NULL)); goto done; } - prev_request = gst_h264_picture_get_user_data (picture); - if (prev_request) { - if (!gst_v4l2_codec_h264_dec_wait (self, prev_request)) - goto done; - gst_v4l2_request_set_done (prev_request); - } - gst_h264_picture_set_user_data (picture, g_steal_pointer (&request), (GDestroyNotify) gst_v4l2_request_free); ret = TRUE; @@ -1044,6 +1008,7 @@ gst_v4l2_codec_h264_dec_submit_bitstream (GstV4l2CodecH264Dec * self, done: if (request) gst_v4l2_request_free (request); + gst_v4l2_codec_h264_dec_reset_picture (self); return ret; diff --git a/sys/v4l2codecs/gstv4l2codecvp8dec.c b/sys/v4l2codecs/gstv4l2codecvp8dec.c index 0e5024c016..ca5267b630 100644 --- a/sys/v4l2codecs/gstv4l2codecvp8dec.c +++ b/sys/v4l2codecs/gstv4l2codecvp8dec.c @@ -246,7 +246,7 @@ gst_v4l2_codec_vp8_dec_decide_allocation (GstVideoDecoder * decoder, min = MAX (2, min); self->sink_allocator = gst_v4l2_codec_allocator_new (self->decoder, - GST_PAD_SINK, self->min_pool_size + 2); + GST_PAD_SINK, 2); self->src_allocator = gst_v4l2_codec_allocator_new (self->decoder, GST_PAD_SRC, self->min_pool_size + min + 4); self->src_pool = gst_v4l2_codec_pool_new (self->src_allocator, &self->vinfo); @@ -539,15 +539,10 @@ gst_v4l2_codec_vp8_dec_end_picture (GstVp8Decoder * decoder, }; /* *INDENT-ON* */ - request = gst_v4l2_decoder_alloc_request (self->decoder); - if (!request) { - GST_ELEMENT_ERROR (decoder, RESOURCE, NO_SPACE_LEFT, - ("Failed to allocate a media request object."), (NULL)); - goto fail; - } - - gst_vp8_picture_set_user_data (picture, request, - (GDestroyNotify) gst_v4l2_request_free); + bytesused = self->bitstream_map.size; + gst_memory_unmap (self->bitstream, &self->bitstream_map); + self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT; + gst_memory_resize (self->bitstream, 0, bytesused); flow_ret = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (self->src_pool), &buffer, NULL); @@ -567,6 +562,17 @@ gst_v4l2_codec_vp8_dec_end_picture (GstVp8Decoder * decoder, frame->output_buffer = buffer; gst_video_codec_frame_unref (frame); + request = gst_v4l2_decoder_alloc_request (self->decoder, + picture->system_frame_number, self->bitstream, buffer); + if (!request) { + GST_ELEMENT_ERROR (decoder, RESOURCE, NO_SPACE_LEFT, + ("Failed to allocate a media request object."), (NULL)); + goto fail; + } + + gst_vp8_picture_set_user_data (picture, request, + (GDestroyNotify) gst_v4l2_request_free); + if (!gst_v4l2_decoder_set_controls (self->decoder, request, control, G_N_ELEMENTS (control))) { GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, @@ -574,26 +580,7 @@ gst_v4l2_codec_vp8_dec_end_picture (GstVp8Decoder * decoder, goto fail; } - bytesused = self->bitstream_map.size; - gst_memory_unmap (self->bitstream, &self->bitstream_map); - self->bitstream_map = (GstMapInfo) GST_MAP_INFO_INIT; - - if (!gst_v4l2_decoder_queue_sink_mem (self->decoder, request, self->bitstream, - picture->system_frame_number, bytesused, 0)) { - GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, - ("Driver did not accept the bitstream data."), (NULL)); - goto fail; - } - - - if (!gst_v4l2_decoder_queue_src_buffer (self->decoder, buffer, - picture->system_frame_number)) { - GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, - ("Driver did not accept the picture buffer."), (NULL)); - goto fail; - } - - if (!gst_v4l2_request_queue (request)) { + if (!gst_v4l2_request_queue (request, 0)) { GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, ("Driver did not accept the decode request."), (NULL)); goto fail; @@ -663,7 +650,6 @@ gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder, GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder); GstV4l2Request *request = gst_vp8_picture_get_user_data (picture); gint ret; - guint32 frame_num; GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); @@ -682,18 +668,16 @@ gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder, goto error; } - do { - if (!gst_v4l2_decoder_dequeue_src (self->decoder, &frame_num)) { - GST_ELEMENT_ERROR (self, STREAM, DECODE, - ("Decoder did not produce a frame"), (NULL)); - goto error; - } - } while (frame_num != picture->system_frame_number); - -finish_frame: gst_v4l2_request_set_done (request); g_return_val_if_fail (frame->output_buffer, GST_FLOW_ERROR); +finish_frame: + if (gst_v4l2_request_failed (request)) { + GST_ELEMENT_ERROR (self, STREAM, DECODE, + ("Failed to decode frame %u", picture->system_frame_number), (NULL)); + goto error; + } + /* Hold on reference buffers for the rest of the picture lifetime */ gst_vp8_picture_set_user_data (picture, gst_buffer_ref (frame->output_buffer), (GDestroyNotify) gst_buffer_unref); diff --git a/sys/v4l2codecs/gstv4l2decoder.c b/sys/v4l2codecs/gstv4l2decoder.c index abe81f94a3..533ce3d443 100644 --- a/sys/v4l2codecs/gstv4l2decoder.c +++ b/sys/v4l2codecs/gstv4l2decoder.c @@ -49,10 +49,17 @@ struct _GstV4l2Request { GstV4l2Decoder *decoder; gint fd; + guint32 frame_num; GstMemory *bitstream; + GstBuffer *pic_buf; GstPoll *poll; GstPollFD pollfd; + + /* request state */ gboolean pending; + gboolean failed; + gboolean hold_pic_buf; + gboolean sub_request; }; struct _GstV4l2Decoder @@ -225,11 +232,12 @@ gst_v4l2_decoder_streamon (GstV4l2Decoder * self, GstPadDirection direction) gboolean gst_v4l2_decoder_streamoff (GstV4l2Decoder * self, GstPadDirection direction) { - GstV4l2Request *pending_req; guint32 type = direction_to_buffer_type (self, direction); gint ret; if (direction == GST_PAD_SRC) { + GstV4l2Request *pending_req; + /* 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))) { @@ -530,12 +538,13 @@ gst_v4l2_decoder_export_buffer (GstV4l2Decoder * self, return TRUE; } -gboolean +static gboolean gst_v4l2_decoder_queue_sink_mem (GstV4l2Decoder * self, GstV4l2Request * request, GstMemory * mem, guint32 frame_num, - gsize bytesused, guint flags) + guint flags) { gint ret; + gsize bytesused = gst_memory_get_sizes (mem, NULL, NULL); struct v4l2_plane plane = { .bytesused = bytesused, }; @@ -563,14 +572,11 @@ gst_v4l2_decoder_queue_sink_mem (GstV4l2Decoder * self, return FALSE; } - request->bitstream = gst_memory_ref (mem); - return TRUE; } -gboolean -gst_v4l2_decoder_queue_src_buffer (GstV4l2Decoder * self, GstBuffer * buffer, - guint32 frame_num) +static gboolean +gst_v4l2_decoder_queue_src_buffer (GstV4l2Decoder * self, GstBuffer * buffer) { gint i, ret; struct v4l2_plane planes[GST_VIDEO_MAX_PLANES]; @@ -606,7 +612,7 @@ gst_v4l2_decoder_queue_src_buffer (GstV4l2Decoder * self, GstBuffer * buffer, return TRUE; } -gboolean +static gboolean gst_v4l2_decoder_dequeue_sink (GstV4l2Decoder * self) { gint ret; @@ -632,7 +638,7 @@ gst_v4l2_decoder_dequeue_sink (GstV4l2Decoder * self) return TRUE; } -gboolean +static gboolean gst_v4l2_decoder_dequeue_src (GstV4l2Decoder * self, guint32 * out_frame_num) { gint ret; @@ -806,8 +812,23 @@ gst_v4l2_decoder_register (GstPlugin * plugin, g_free (type_name); } +/* + * gst_v4l2_decoder_alloc_request: + * @self a #GstV4l2Decoder pointer + * @frame_num: Used as a timestamp to identify references + * @bitstream the #GstMemory that holds the bitstream data + * @pic_buf the #GstBuffer holding the decoded picture + * + * Allocate a Linux media request file descriptor. This request wrapper will + * hold a reference to the requested bitstream memory to decoded and the + * picture buffer this request will decode to. This will be used for + * transparent management of the V4L2 queues. + * + * Returns: a new #GstV4l2Request + */ GstV4l2Request * -gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self) +gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self, guint32 frame_num, + GstMemory * bitstream, GstBuffer * pic_buf) { GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool); gint ret; @@ -830,9 +851,60 @@ gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self) } request->decoder = g_object_ref (self); + request->bitstream = gst_memory_ref (bitstream); + request->pic_buf = gst_buffer_ref (pic_buf); + request->frame_num = frame_num; + return request; } +/* + * gst_v4l2_decoder_alloc_sub_request: + * @self a #GstV4l2Decoder pointer + * @prev_request the #GstV4l2Request this request continue + * @bitstream the #GstMemory that holds the bitstream data + * + * Allocate a Linux media request file descriptor. Similar to + * gst_v4l2_decoder_alloc_request(), but used when a request is the + * continuation of the decoding of the same picture. This is notably the case + * for subsequent slices or for second field of a frame. + * + * Returns: a new #GstV4l2Request + */ +GstV4l2Request * +gst_v4l2_decoder_alloc_sub_request (GstV4l2Decoder * self, + GstV4l2Request * prev_request, GstMemory * bitstream) +{ + GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool); + gint ret; + + if (!request) { + request = g_new0 (GstV4l2Request, 1); + + ret = ioctl (self->media_fd, MEDIA_IOC_REQUEST_ALLOC, &request->fd); + if (ret < 0) { + GST_ERROR_OBJECT (self, "MEDIA_IOC_REQUEST_ALLOC failed: %s", + g_strerror (errno)); + return NULL; + } + + request->poll = gst_poll_new (FALSE); + gst_poll_fd_init (&request->pollfd); + request->pollfd.fd = request->fd; + gst_poll_add_fd (request->poll, &request->pollfd); + gst_poll_fd_ctl_pri (request->poll, &request->pollfd, TRUE); + } + + request->decoder = g_object_ref (self); + request->bitstream = gst_memory_ref (bitstream); + request->pic_buf = gst_buffer_ref (prev_request->pic_buf); + request->frame_num = prev_request->frame_num; + request->sub_request = TRUE; + + return request; +} + + void gst_v4l2_request_free (GstV4l2Request * request) { @@ -847,6 +919,11 @@ gst_v4l2_request_free (GstV4l2Request * request) } g_clear_pointer (&request->bitstream, gst_memory_unref); + g_clear_pointer (&request->pic_buf, gst_buffer_unref); + request->frame_num = G_MAXUINT32; + request->failed = FALSE; + request->hold_pic_buf = FALSE; + request->sub_request = FALSE; request->decoder = NULL; if (request->pending) { @@ -879,21 +956,48 @@ gst_v4l2_request_free (GstV4l2Request * request) } gboolean -gst_v4l2_request_queue (GstV4l2Request * request) +gst_v4l2_request_queue (GstV4l2Request * request, guint flags) { + GstV4l2Decoder *decoder = request->decoder; gint ret; - GST_TRACE_OBJECT (request->decoder, "Queuing request %p.", request); + GST_TRACE_OBJECT (decoder, "Queuing request %p.", request); + + if (!gst_v4l2_decoder_queue_sink_mem (decoder, request, + request->bitstream, request->frame_num, flags)) { + GST_ERROR_OBJECT (decoder, "Driver did not accept the bitstream data."); + return FALSE; + } + + if (!request->sub_request && + !gst_v4l2_decoder_queue_src_buffer (decoder, request->pic_buf)) { + GST_ERROR_OBJECT (decoder, "Driver did not accept the picture buffer."); + return FALSE; + } ret = ioctl (request->fd, MEDIA_REQUEST_IOC_QUEUE, NULL); if (ret < 0) { - GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_QUEUE, failed: %s", + GST_ERROR_OBJECT (decoder, "MEDIA_REQUEST_IOC_QUEUE, failed: %s", g_strerror (errno)); return FALSE; } + if (flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF) + request->hold_pic_buf = TRUE; + request->pending = TRUE; - gst_queue_array_push_tail (request->decoder->pending_requests, request); + gst_queue_array_push_tail (decoder->pending_requests, 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) { + GstV4l2Request *pending_req; + + pending_req = gst_queue_array_peek_head (decoder->pending_requests); + ret = gst_v4l2_request_poll (pending_req, GST_SECOND); + if (ret > 0) + gst_v4l2_request_set_done (pending_req); + } return TRUE; } @@ -907,28 +1011,38 @@ gst_v4l2_request_poll (GstV4l2Request * request, GstClockTime timeout) void gst_v4l2_request_set_done (GstV4l2Request * request) { - if (request->bitstream) { - GstV4l2Decoder *dec = request->decoder; - GstV4l2Request *pending_req; + GstV4l2Decoder *decoder = request->decoder; + GstV4l2Request *pending_req = NULL; - 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); - pending_req->pending = FALSE; + if (!request->pending) + return; - if (pending_req == request) - break; + while ((pending_req = gst_queue_array_pop_head (decoder->pending_requests))) { + gst_v4l2_decoder_dequeue_sink (decoder); + g_clear_pointer (&pending_req->bitstream, gst_memory_unref); + + if (!pending_req->hold_pic_buf) { + guint32 frame_num = G_MAXUINT32; + + if (!gst_v4l2_decoder_dequeue_src (decoder, &frame_num)) { + pending_req->failed = TRUE; + } else if (frame_num != pending_req->frame_num) { + GST_WARNING_OBJECT (decoder, + "Requested frame %u, but driver returned frame %u.", + pending_req->frame_num, frame_num); + pending_req->failed = TRUE; + } } - /* 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); - } + g_clear_pointer (&pending_req->pic_buf, gst_buffer_unref); + pending_req->pending = FALSE; + + if (pending_req == request) + break; } - request->pending = FALSE; + /* Pending request must be in the pending request list */ + g_assert (pending_req == request); } gboolean @@ -936,3 +1050,9 @@ gst_v4l2_request_is_done (GstV4l2Request * request) { return !request->pending; } + +gboolean +gst_v4l2_request_failed (GstV4l2Request * request) +{ + return request->failed; +} diff --git a/sys/v4l2codecs/gstv4l2decoder.h b/sys/v4l2codecs/gstv4l2decoder.h index 0d32e31c5e..e0f9cf8128 100644 --- a/sys/v4l2codecs/gstv4l2decoder.h +++ b/sys/v4l2codecs/gstv4l2decoder.h @@ -72,22 +72,6 @@ gboolean gst_v4l2_decoder_export_buffer (GstV4l2Decoder * self, gsize * offsets, guint *num_fds); -gboolean gst_v4l2_decoder_queue_sink_mem (GstV4l2Decoder * self, - GstV4l2Request * request, - GstMemory * mem, - guint32 frame_num, - gsize bytesused, - guint flags); - -gboolean gst_v4l2_decoder_dequeue_sink (GstV4l2Decoder * self); - -gboolean gst_v4l2_decoder_queue_src_buffer (GstV4l2Decoder * self, - GstBuffer * buffer, - guint32 frame_num); - -gboolean gst_v4l2_decoder_dequeue_src (GstV4l2Decoder * self, - guint32 *out_frame_num); - gboolean gst_v4l2_decoder_set_controls (GstV4l2Decoder * self, GstV4l2Request * request, struct v4l2_ext_control *control, @@ -115,18 +99,29 @@ void gst_v4l2_decoder_register (GstPlugin * plugin, GstV4l2CodecDevice * device, guint rank); -GstV4l2Request *gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self); +GstV4l2Request *gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self, + guint32 frame_num, + GstMemory *bitstream, + GstBuffer * pic_buf); + +GstV4l2Request *gst_v4l2_decoder_alloc_sub_request (GstV4l2Decoder * self, + GstV4l2Request * prev_request, + GstMemory *bitstream); void gst_v4l2_request_free (GstV4l2Request * request); -gboolean gst_v4l2_request_queue (GstV4l2Request * request); +gboolean gst_v4l2_request_queue (GstV4l2Request * request, + guint flags); -gint gst_v4l2_request_poll (GstV4l2Request * request, GstClockTime timeout); +gint gst_v4l2_request_poll (GstV4l2Request * request, + GstClockTime timeout); void gst_v4l2_request_set_done (GstV4l2Request * request); gboolean gst_v4l2_request_is_done (GstV4l2Request * request); +gboolean gst_v4l2_request_failed (GstV4l2Request * request); + G_END_DECLS #endif /* __GST_V4L2_DECODER_H__ */