decoder: optimize and clean decode_step() up.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Fri, 18 Jan 2013 15:56:15 +0000 (16:56 +0100)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Fri, 18 Jan 2013 15:56:15 +0000 (16:56 +0100)
Avoid usage of goto. Simplify decode_step() process to first accumulate all
pending buffers into the GstAdapter, and then parse and decode units from
that input adapter. Stop the process once a frame is fully decoded or an
error occurred.

gst-libs/gst/vaapi/gstvaapidecoder.c

index 74375826314c47866b88722a598690c46a5c6a1e..6209c405841a1c6e19f454960dfbb36325b3982d 100644 (file)
@@ -275,67 +275,72 @@ decode_step(GstVaapiDecoder *decoder)
     GstVaapiDecoderStatus status;
     GstBuffer *buffer;
     gboolean got_frame;
-    guint got_unit_size;
-
-    if (G_UNLIKELY(ps->at_eos))
-        return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+    guint got_unit_size, input_size;
 
     status = gst_vaapi_decoder_check_status(decoder);
     if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
         return status;
 
-    if (ps->current_frame)
-        goto parse;
-
-    do {
+    /* Fill adapter with all buffers we have in the queue */
+    for (;;) {
         buffer = pop_buffer(decoder);
         if (!buffer)
-            return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+            break;
 
         ps->at_eos = GST_BUFFER_IS_EOS(buffer);
         if (!ps->at_eos)
             gst_adapter_push(ps->input_adapter, buffer);
+    }
 
-        do {
-            if (!ps->current_frame) {
-                ps->current_frame = g_slice_new0(GstVideoCodecFrame);
-                if (!ps->current_frame)
-                    return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
-                ps->current_frame->ref_count = 1;
-            }
+    /* Parse and decode all decode units */
+    input_size = gst_adapter_available(ps->input_adapter);
+    if (input_size == 0) {
+        if (ps->at_eos)
+            return GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+        return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
+    }
 
-        parse:
-            status = do_parse(decoder, ps->current_frame,
-                ps->input_adapter, ps->at_eos, &got_unit_size, &got_frame);
-            GST_DEBUG("parse frame (status = %d)", status);
-            if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
-                break;
-
-            if (got_unit_size > 0) {
-                buffer = gst_adapter_take_buffer(ps->input_adapter,
-                    got_unit_size);
-                if (gst_adapter_available(ps->output_adapter) == 0) {
-                    ps->current_frame->pts =
-                        gst_adapter_prev_timestamp(ps->input_adapter, NULL);
-                }
-                gst_adapter_push(ps->output_adapter, buffer);
-            }
+    do {
+        if (!ps->current_frame) {
+            ps->current_frame = g_slice_new0(GstVideoCodecFrame);
+            if (!ps->current_frame)
+                return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED;
+            ps->current_frame->ref_count = 1;
+        }
 
-            if (got_frame) {
-                ps->current_frame->input_buffer = gst_adapter_take_buffer(
-                    ps->output_adapter,
-                    gst_adapter_available(ps->output_adapter));
+        status = do_parse(decoder, ps->current_frame, ps->input_adapter,
+            ps->at_eos, &got_unit_size, &got_frame);
+        GST_DEBUG("parse frame (status = %d)", status);
+        if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) {
+            if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA && ps->at_eos)
+                status = GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
+            break;
+        }
 
-                status = do_decode(decoder, ps->current_frame);
-                GST_DEBUG("decode frame (status = %d)", status);
+        if (got_unit_size > 0) {
+            buffer = gst_adapter_take_buffer(ps->input_adapter, got_unit_size);
+            input_size -= got_unit_size;
 
-                gst_video_codec_frame_unref(ps->current_frame);
-                ps->current_frame = NULL;
-                break;
+            if (gst_adapter_available(ps->output_adapter) == 0) {
+                ps->current_frame->pts =
+                    gst_adapter_prev_timestamp(ps->input_adapter, NULL);
             }
-        } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS &&
-                 gst_adapter_available(ps->input_adapter) > 0);
-    } while (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA);
+            gst_adapter_push(ps->output_adapter, buffer);
+        }
+
+        if (got_frame) {
+            ps->current_frame->input_buffer = gst_adapter_take_buffer(
+                ps->output_adapter,
+                gst_adapter_available(ps->output_adapter));
+
+            status = do_decode(decoder, ps->current_frame);
+            GST_DEBUG("decode frame (status = %d)", status);
+
+            gst_video_codec_frame_unref(ps->current_frame);
+            ps->current_frame = NULL;
+            break;
+        }
+    } while (input_size > 0);
     return status;
 }