videodecoder: allow parse function to not use all data on adapter

This commit is contained in:
Thijs Vermeir 2013-01-02 12:15:25 +01:00 committed by Sebastian Dröge
parent e7caef6b29
commit d189beda4d

View file

@ -453,6 +453,8 @@ static gboolean gst_video_decoder_decide_allocation_default (GstVideoDecoder *
static gboolean gst_video_decoder_propose_allocation_default (GstVideoDecoder *
decoder, GstQuery * query);
static gboolean gst_video_decoder_negotiate_default (GstVideoDecoder * decoder);
static GstFlowReturn gst_video_decoder_parse_available (GstVideoDecoder * dec,
gboolean at_eos);
/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
* method to get to the padtemplates */
@ -898,6 +900,32 @@ gst_video_decoder_push_event (GstVideoDecoder * decoder, GstEvent * event)
return gst_pad_push_event (decoder->srcpad, event);
}
static GstFlowReturn
gst_video_decoder_parse_available (GstVideoDecoder * dec, gboolean at_eos)
{
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_GET_CLASS (dec);
GstVideoDecoderPrivate *priv = dec->priv;
GstFlowReturn ret = GST_FLOW_OK;
gsize start_size, available;
available = gst_adapter_available (priv->input_adapter);
start_size = 0;
while (ret == GST_FLOW_OK && available && start_size != available) {
/* current frame may have been parsed and handled,
* so we need to set up a new one when asking subclass to parse */
if (priv->current_frame == NULL)
priv->current_frame = gst_video_decoder_new_frame (dec);
start_size = available;
ret = decoder_class->parse (dec, priv->current_frame,
priv->input_adapter, at_eos);
available = gst_adapter_available (priv->input_adapter);
}
return ret;
}
static GstFlowReturn
gst_video_decoder_drain_out (GstVideoDecoder * dec, gboolean at_eos)
{
@ -911,13 +939,7 @@ gst_video_decoder_drain_out (GstVideoDecoder * dec, gboolean at_eos)
/* Forward mode, if unpacketized, give the child class
* a final chance to flush out packets */
if (!priv->packetized) {
while (ret == GST_FLOW_OK && gst_adapter_available (priv->input_adapter)) {
if (priv->current_frame == NULL)
priv->current_frame = gst_video_decoder_new_frame (dec);
ret = decoder_class->parse (dec, priv->current_frame,
priv->input_adapter, TRUE);
}
ret = gst_video_decoder_parse_available (dec, TRUE);
}
} else {
/* Reverse playback mode */
@ -1699,24 +1721,11 @@ gst_video_decoder_chain_forward (GstVideoDecoder * decoder,
}
priv->current_frame = NULL;
} else {
gst_adapter_push (priv->input_adapter, buf);
if (G_UNLIKELY (!gst_adapter_available (priv->input_adapter)))
goto beach;
do {
/* current frame may have been parsed and handled,
* so we need to set up a new one when asking subclass to parse */
if (priv->current_frame == NULL)
priv->current_frame = gst_video_decoder_new_frame (decoder);
ret = klass->parse (decoder, priv->current_frame,
priv->input_adapter, at_eos);
} while (ret == GST_FLOW_OK && gst_adapter_available (priv->input_adapter));
ret = gst_video_decoder_parse_available (decoder, at_eos);
}
beach:
if (ret == GST_VIDEO_DECODER_FLOW_NEED_DATA)
return GST_FLOW_OK;