videodecoder: allow parse function to not use all data on adapter
authorThijs Vermeir <thijsvermeir@gmail.com>
Wed, 2 Jan 2013 11:15:25 +0000 (12:15 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 12 Feb 2013 09:17:46 +0000 (10:17 +0100)
gst-libs/gst/video/gstvideodecoder.c

index 0383682..a9be47e 100644 (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 */
@@ -899,6 +901,32 @@ gst_video_decoder_push_event (GstVideoDecoder * decoder, GstEvent * 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)
 {
   GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_GET_CLASS (dec);
@@ -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;