vaapidecode: fix surface timeout error
authorZhong Cong <congx.zhong@intel.com>
Tue, 9 Apr 2013 08:33:03 +0000 (16:33 +0800)
committerZhong Cong <congx.zhong@intel.com>
Tue, 9 Apr 2013 08:33:03 +0000 (16:33 +0800)
gst-libs/gst/vaapi/gstvaapidecoder.c
gst-libs/gst/vaapi/gstvaapidecoder.h
gst/vaapi/gstvaapidecode.c
gst/vaapi/gstvaapidecode.h
tests/test-decode.c
tests/test-subpicture.c

index 0df566d..dad1e4b 100644 (file)
@@ -90,7 +90,7 @@ pop_buffer(GstVaapiDecoder *decoder)
 }
 
 static GstVaapiDecoderStatus
-decode_step(GstVaapiDecoder *decoder)
+decode_step(GstVaapiDecoder *decoder, gboolean *try_again)
 {
     GstVaapiDecoderStatus status;
     GstBuffer *buffer;
@@ -101,12 +101,23 @@ decode_step(GstVaapiDecoder *decoder)
         return status;
 
     do {
-        buffer = pop_buffer(decoder);
+        if (*try_again){
+            buffer = gst_buffer_new();
+            if (buffer){
+                gst_buffer_set_data(buffer, NULL, 0);
+            }
+            *try_again = FALSE;
+        }else{
+            buffer = pop_buffer(decoder);
+        }
         if (!buffer)
             return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
 
         status = GST_VAAPI_DECODER_GET_CLASS(decoder)->decode(decoder, buffer);
         GST_DEBUG("decode frame (status = %d)", status);
+        if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
+            *try_again = TRUE;
+        }
         if (status != GST_VAAPI_DECODER_STATUS_SUCCESS && GST_BUFFER_IS_EOS(buffer))
             status = GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
         gst_buffer_unref(buffer);
@@ -413,6 +424,7 @@ gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf)
  * gst_vaapi_decoder_get_surface:
  * @decoder: a #GstVaapiDecoder
  * @pstatus: return location for the decoder status, or %NULL
+ * @try_again: a #gboolean
  *
  * Flushes encoded buffers to the decoder and returns a decoded
  * surface, if any.
@@ -424,7 +436,8 @@ gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf)
 GstVaapiSurfaceProxy *
 gst_vaapi_decoder_get_surface(
     GstVaapiDecoder       *decoder,
-    GstVaapiDecoderStatus *pstatus
+    GstVaapiDecoderStatus *pstatus,
+    gboolean              *try_again
 )
 {
     GstVaapiSurfaceProxy *proxy;
@@ -438,7 +451,7 @@ gst_vaapi_decoder_get_surface(
     proxy = pop_surface(decoder);
     if (!proxy) {
         do {
-            status = decode_step(decoder);
+            status = decode_step(decoder, try_again);
         } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
         proxy = pop_surface(decoder);
     }
index ebcead9..d935b1d 100644 (file)
@@ -129,7 +129,8 @@ gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf);
 GstVaapiSurfaceProxy *
 gst_vaapi_decoder_get_surface(
     GstVaapiDecoder       *decoder,
-    GstVaapiDecoderStatus *pstatus
+    GstVaapiDecoderStatus *pstatus,
+    gboolean              *try_again
 );
 
 void
index 5e2c8ef..33587e7 100644 (file)
@@ -199,29 +199,27 @@ gst_vaapidecode_step(GstVaapiDecode *decode)
     GstBuffer *buffer;
     GstFlowReturn ret;
     GstClockTime timestamp;
-    gint64 end_time;
+    gboolean try_again = FALSE;
 
     for (;;) {
-        end_time = decode->render_time_base;
-        if (!end_time)
-            end_time = g_get_monotonic_time();
-        end_time += GST_TIME_AS_USECONDS(decode->last_buffer_time);
-        end_time += G_TIME_SPAN_SECOND;
-
-        proxy = gst_vaapi_decoder_get_surface(decode->decoder, &status);
+        proxy = gst_vaapi_decoder_get_surface(decode->decoder, &status, &try_again);
+        try_again = FALSE;
         if (!proxy) {
             if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
-                gboolean was_signalled;
                 g_mutex_lock(&decode->decoder_mutex);
-                was_signalled = g_cond_wait_until(
+                if (decode->break_flag){
+                    goto handle_break_flag;
+                }
+                g_cond_wait(
                     &decode->decoder_ready,
-                    &decode->decoder_mutex,
-                    end_time
+                    &decode->decoder_mutex
                 );
+                if (decode->break_flag){
+                    goto handle_break_flag;
+                }
                 g_mutex_unlock(&decode->decoder_mutex);
-                if (was_signalled)
-                    continue;
-                goto error_decode_timeout;
+                try_again = TRUE;
+                continue;
             }
             if (status != GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA)
                 goto error_decode;
@@ -271,10 +269,13 @@ gst_vaapidecode_step(GstVaapiDecode *decode)
     return GST_FLOW_OK;
 
     /* ERRORS */
-error_decode_timeout:
+handle_break_flag:
+    {
+        g_mutex_unlock(&decode->decoder_mutex);
+        goto error_receive_event;
+    }
+error_receive_event:
     {
-        GST_DEBUG("decode timeout. Decoder required a VA surface but none "
-                  "got available within one second");
         return GST_FLOW_UNEXPECTED;
     }
 error_decode:
@@ -538,6 +539,10 @@ gst_vaapidecode_change_state(GstElement *element, GstStateChange transition)
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
         break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+        g_mutex_lock(&decode->decoder_mutex);
+        decode->break_flag = TRUE;
+        g_cond_signal(&decode->decoder_ready);
+        g_mutex_unlock(&decode->decoder_mutex);
         break;
     case GST_STATE_CHANGE_READY_TO_NULL:
         gst_vaapidecode_destroy(decode);
@@ -707,7 +712,6 @@ gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event)
     GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
 
     GST_DEBUG("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
-
     /* Propagate event downstream */
     switch (GST_EVENT_TYPE(event)) {
     case GST_EVENT_FLUSH_STOP:
@@ -727,6 +731,10 @@ gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event)
         gst_vaapidecode_configure_segment(decode, event);
         break;
     case GST_EVENT_EOS:
+        g_mutex_lock(&decode->decoder_mutex);
+        decode->break_flag = TRUE;
+        g_cond_signal(&decode->decoder_ready);
+        g_mutex_unlock(&decode->decoder_mutex);
         if (!gst_vaapidecode_flush(decode)) {
             GST_WARNING("failed to flush buffers");
         }
@@ -778,6 +786,7 @@ gst_vaapidecode_init(GstVaapiDecode *decode)
     decode->render_time_base    = 0;
     decode->last_buffer_time    = 0;
     decode->is_ready            = FALSE;
+    decode->break_flag          = FALSE;
 
     g_mutex_init(&decode->decoder_mutex);
     g_cond_init(&decode->decoder_ready);
index c8b2583..a15aeb3 100644 (file)
@@ -76,6 +76,7 @@ struct _GstVaapiDecode {
     gint64              render_time_base;
     GstClockTime        last_buffer_time;
     unsigned int        is_ready        : 1;
+    gboolean            break_flag;
 };
 
 struct _GstVaapiDecodeClass {
index 458416e..81eb7ff 100644 (file)
@@ -179,7 +179,8 @@ main(int argc, char *argv[])
     if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
         g_error("could not send EOS to the decoder");
 
-    proxy = gst_vaapi_decoder_get_surface(decoder, &status);
+    gboolean try_again = FALSE;
+    proxy = gst_vaapi_decoder_get_surface(decoder, &status, &try_again);
     if (!proxy)
         g_error("could not get decoded surface (decoder status %d)", status);
 
index 7a65fe3..89643d7 100644 (file)
@@ -157,7 +157,8 @@ main(int argc, char *argv[])
     if (!gst_vaapi_decoder_put_buffer(decoder, NULL))
         g_error("could not send EOS to the decoder");
 
-    proxy = gst_vaapi_decoder_get_surface(decoder, &status);
+    gboolean try_again = FALSE;
+    proxy = gst_vaapi_decoder_get_surface(decoder, &status, &try_again);
     if (!proxy)
         g_error("could not get decoded surface (decoder status %d)", status);