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__ */