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);
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);
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);
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 */
- GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
- ("No more picture buffer available."), (NULL));
+ 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;
}
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)
{
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)
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);
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);
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)) {
- gst_atomic_queue_push (self->queue, buf);
- return GST_FLOW_ERROR;
+ 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 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);