mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
v4l2codecs: Wait for buffers to come back
This code add required mechanism to try and allocate (not implemented yet) otherwise wait for more buffers. This also comes with mechanism to terminate the wait on flush or PAUSED_TO_READY transitions.
This commit is contained in:
parent
09a9ffcda6
commit
e70993bf43
3 changed files with 89 additions and 17 deletions
|
@ -107,14 +107,9 @@ gst_v4l2_codec_h264_dec_close (GstVideoDecoder * decoder)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_codec_h264_dec_stop (GstVideoDecoder * decoder)
|
||||
static void
|
||||
gst_v4l2_codec_h264_dec_reset_allocation (GstV4l2CodecH264Dec * self)
|
||||
{
|
||||
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||
|
||||
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK);
|
||||
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC);
|
||||
|
||||
if (self->sink_allocator) {
|
||||
gst_v4l2_codec_allocator_detach (self->sink_allocator);
|
||||
g_clear_object (&self->sink_allocator);
|
||||
|
@ -125,6 +120,17 @@ gst_v4l2_codec_h264_dec_stop (GstVideoDecoder * decoder)
|
|||
g_clear_object (&self->src_allocator);
|
||||
g_clear_object (&self->src_pool);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_codec_h264_dec_stop (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||
|
||||
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK);
|
||||
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC);
|
||||
|
||||
gst_v4l2_codec_h264_dec_reset_allocation (self);
|
||||
|
||||
if (self->output_state)
|
||||
gst_video_codec_state_unref (self->output_state);
|
||||
|
@ -156,11 +162,7 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder)
|
|||
|
||||
GST_DEBUG_OBJECT (self, "Negotiate");
|
||||
|
||||
if (self->sink_allocator)
|
||||
gst_v4l2_codec_allocator_detach (self->sink_allocator);
|
||||
|
||||
if (self->src_allocator)
|
||||
gst_v4l2_codec_allocator_detach (self->src_allocator);
|
||||
gst_v4l2_codec_h264_dec_reset_allocation (self);
|
||||
|
||||
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK);
|
||||
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC);
|
||||
|
@ -729,7 +731,9 @@ gst_v4l2_codec_h264_dec_end_picture (GstH264Decoder * decoder,
|
|||
flow_ret = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (self->src_pool),
|
||||
&buffer, NULL);
|
||||
if (flow_ret != GST_FLOW_OK) {
|
||||
/* FIXME our pool does not wait */
|
||||
if (flow_ret == GST_FLOW_FLUSHING)
|
||||
GST_DEBUG_OBJECT (self, "Frame decoding aborted, we are flushing.");
|
||||
else
|
||||
GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
|
||||
("No more picture buffer available."), (NULL));
|
||||
goto fail;
|
||||
|
@ -808,6 +812,16 @@ gst_v4l2_codec_h264_dec_decode_slice (GstH264Decoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_v4l2_codec_h264_dec_set_flushing (GstV4l2CodecH264Dec * self,
|
||||
gboolean flushing)
|
||||
{
|
||||
if (self->sink_allocator)
|
||||
gst_v4l2_codec_allocator_set_flushing (self->sink_allocator, flushing);
|
||||
if (self->src_allocator)
|
||||
gst_v4l2_codec_allocator_set_flushing (self->src_allocator, flushing);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_codec_h264_dec_flush (GstVideoDecoder * decoder)
|
||||
{
|
||||
|
@ -816,10 +830,40 @@ gst_v4l2_codec_h264_dec_flush (GstVideoDecoder * decoder)
|
|||
GST_DEBUG_OBJECT (self, "Flushing decoder state.");
|
||||
|
||||
gst_v4l2_decoder_flush (self->decoder);
|
||||
gst_v4l2_codec_h264_dec_set_flushing (self, FALSE);
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->flush (decoder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_codec_h264_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
|
||||
{
|
||||
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH_START:
|
||||
GST_DEBUG_OBJECT (self, "flush start");
|
||||
gst_v4l2_codec_h264_dec_set_flushing (self, TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_v4l2_codec_h264_dec_change_state (GstElement * element,
|
||||
GstStateChange transition)
|
||||
{
|
||||
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (element);
|
||||
|
||||
if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
|
||||
gst_v4l2_codec_h264_dec_set_flushing (self, TRUE);
|
||||
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_v4l2_codec_h264_dec_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
|
@ -900,6 +944,8 @@ gst_v4l2_codec_h264_dec_subclass_init (GstV4l2CodecH264DecClass * klass,
|
|||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_change_state);
|
||||
|
||||
decoder_class->open = GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_open);
|
||||
decoder_class->close = GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_close);
|
||||
|
@ -909,6 +955,8 @@ gst_v4l2_codec_h264_dec_subclass_init (GstV4l2CodecH264DecClass * klass,
|
|||
decoder_class->decide_allocation =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_decide_allocation);
|
||||
decoder_class->flush = GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_flush);
|
||||
decoder_class->sink_event =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_sink_event);
|
||||
|
||||
h264decoder_class->new_sequence =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_new_sequence);
|
||||
|
|
|
@ -60,9 +60,28 @@ gst_v4l2_codec_pool_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
|
|||
if (!buf)
|
||||
buf = gst_v4l2_codec_pool_create_empty_buffer ();
|
||||
|
||||
/* First, just try and obtain a buffer. */
|
||||
if (!gst_v4l2_codec_allocator_prepare_buffer (self->allocator, buf)) {
|
||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||
|
||||
/* If none were available, try and allocate one. */
|
||||
if (!gst_v4l2_codec_allocator_create_buffer (self->allocator)) {
|
||||
/* Otherwise, wait if this is allowed. */
|
||||
if (params && params->flags & GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT) {
|
||||
flow_ret = GST_FLOW_EOS;
|
||||
} else {
|
||||
if (!gst_v4l2_codec_allocator_wait_for_buffer (self->allocator))
|
||||
flow_ret = GST_FLOW_FLUSHING;
|
||||
}
|
||||
}
|
||||
|
||||
if (flow_ret != GST_FLOW_OK) {
|
||||
gst_atomic_queue_push (self->queue, buf);
|
||||
return GST_FLOW_ERROR;
|
||||
return flow_ret;
|
||||
}
|
||||
|
||||
/* Finally, pop the buffer we created or waited for. */
|
||||
gst_v4l2_codec_allocator_prepare_buffer (self->allocator, buf);
|
||||
}
|
||||
|
||||
vmeta = gst_buffer_get_video_meta (buf);
|
||||
|
|
|
@ -688,11 +688,14 @@ gst_v4l2_request_free (GstV4l2Request * request)
|
|||
request->decoder = NULL;
|
||||
|
||||
if (request->pending) {
|
||||
GST_DEBUG_OBJECT (decoder, "Freeing pending request %p.", request);
|
||||
gst_v4l2_request_free (request);
|
||||
g_object_unref (decoder);
|
||||
return;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (decoder, "Recycling request %p.", request);
|
||||
|
||||
ret = ioctl (request->fd, MEDIA_REQUEST_IOC_REINIT, NULL);
|
||||
if (ret < 0) {
|
||||
GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_REINIT failed: %s",
|
||||
|
@ -711,6 +714,8 @@ gst_v4l2_request_queue (GstV4l2Request * request)
|
|||
{
|
||||
gint ret;
|
||||
|
||||
GST_DEBUG_OBJECT (request->decoder, "Queuing request %p.", request);
|
||||
|
||||
ret = ioctl (request->fd, MEDIA_REQUEST_IOC_QUEUE, NULL);
|
||||
if (ret < 0) {
|
||||
GST_ERROR_OBJECT (request->decoder, "MEDIA_REQUEST_IOC_QUEUE, failed: %s",
|
||||
|
|
Loading…
Reference in a new issue