Update fix for seek
authorZhao Halley <halley.zhao@intel.com>
Sat, 20 Apr 2013 07:35:53 +0000 (15:35 +0800)
committerZhao Halley <halley.zhao@intel.com>
Sat, 20 Apr 2013 07:35:53 +0000 (15:35 +0800)
1. Use GST_EVENT_FLUSH_START to help decoder escape from waiting for
   an availabe surface; correspondingly, GST_EVENT_FLUSH_STOP disables
   such special exception.
2. Remove such escape by GST_STATE_CHANGE_PAUSED_TO_READY
   during seek, the status/event happens as following order:
   GST_STATE_CHANGE_PLAYING_TO_PAUSED -> GST_EVENT_FLUSH_START ->
   GST_EVENT_FLUSH_STOP -> GST_STATE_CHANGE_PAUSED_TO_PLAYING
3. Remove such escape by GST_EVENT_EOS.
   EOS is the symptom caused by no surface available, not the reason.
   I'm afraid the original code will miss some frames if EOS comes
   earlier than decoder finishes decoding the sent data.

gst/vaapi/gstvaapidecode.c [changed mode: 0644->0755]
gst/vaapi/gstvaapidecode.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 21139dc..e07867b
@@ -211,15 +211,15 @@ gst_vaapidecode_step(GstVaapiDecode *decode)
         if (!proxy) {
             if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
                 g_mutex_lock(&decode->decoder_mutex);
-                if (decode->break_flag){
-                    goto handle_break_flag;
+                if (decode->escape_decoding){
+                    goto handle_escape_decoding;
                 }
                 g_cond_wait(
                     &decode->decoder_ready,
                     &decode->decoder_mutex
                 );
-                if (decode->break_flag){
-                    goto handle_break_flag;
+                if (decode->escape_decoding){
+                    goto handle_escape_decoding;
                 }
                 g_mutex_unlock(&decode->decoder_mutex);
                 try_again = TRUE;
@@ -273,13 +273,10 @@ gst_vaapidecode_step(GstVaapiDecode *decode)
     return GST_FLOW_OK;
 
     /* ERRORS */
-handle_break_flag:
+handle_escape_decoding:
     {
         g_mutex_unlock(&decode->decoder_mutex);
-        goto error_receive_event;
-    }
-error_receive_event:
-    {
+        GST_INFO("Escape decoding wait: flush event comes for seek etc.");
         return GST_FLOW_UNEXPECTED;
     }
 error_decode:
@@ -519,12 +516,32 @@ gst_vaapidecode_finalize(GObject *object)
     G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
 }
 
+typedef struct {
+    int trans;
+    char *trans_name;
+} _GstStateChangeMap;
+_GstStateChangeMap gst_state_change_string_map[] = {
+    {GST_STATE_CHANGE_NULL_TO_READY,    "GST_STATE_CHANGE_NULL_TO_READY"}, 
+    {GST_STATE_CHANGE_READY_TO_PAUSED,  "GST_STATE_CHANGE_READY_TO_PAUSED",},
+    {GST_STATE_CHANGE_PAUSED_TO_PLAYING,"GST_STATE_CHANGE_PAUSED_TO_PLAYING"},
+    {GST_STATE_CHANGE_PLAYING_TO_PAUSED,"GST_STATE_CHANGE_PLAYING_TO_PAUSED"},
+    {GST_STATE_CHANGE_PAUSED_TO_READY,  "GST_STATE_CHANGE_PAUSED_TO_READY"},
+    {GST_STATE_CHANGE_READY_TO_NULL,    "GST_STATE_CHANGE_READY_TO_NULL"},
+    {-1,                                "UNDEFINED_STATE_CHANGE"}
+};
+
 static GstStateChangeReturn
 gst_vaapidecode_change_state(GstElement *element, GstStateChange transition)
 {
     GstVaapiDecode * const decode = GST_VAAPIDECODE(element);
     GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+    int i;
 
+    for (i=0; i<sizeof(gst_state_change_string_map)/sizeof(_GstStateChangeMap);i++) {
+        if (gst_state_change_string_map[i].trans == transition)
+            GST_INFO(gst_state_change_string_map[i].trans_name);
+    }
+    
     switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
         decode->is_ready = TRUE;
@@ -545,10 +562,6 @@ 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);
@@ -717,10 +730,20 @@ 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));
+    GST_INFO("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
+
     /* Propagate event downstream */
     switch (GST_EVENT_TYPE(event)) {
+    case GST_EVENT_FLUSH_START:
+        g_mutex_lock(&decode->decoder_mutex);
+        decode->escape_decoding = TRUE;
+        g_cond_signal(&decode->decoder_ready);
+        g_mutex_unlock(&decode->decoder_mutex);
+        break;
     case GST_EVENT_FLUSH_STOP:
+        g_mutex_lock(&decode->decoder_mutex);
+        decode->escape_decoding = FALSE;
+        g_mutex_unlock(&decode->decoder_mutex);
         gst_segment_init(&decode->segment, GST_FORMAT_UNDEFINED);
         if (decode->decoder)
             gst_vaapi_decoder_clear_buffer(decode->decoder);
@@ -737,10 +760,6 @@ 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");
         }
@@ -792,7 +811,7 @@ gst_vaapidecode_init(GstVaapiDecode *decode)
     decode->render_time_base    = 0;
     decode->last_buffer_time    = 0;
     decode->is_ready            = FALSE;
-    decode->break_flag          = FALSE;
+    decode->escape_decoding          = FALSE;
 
     g_mutex_init(&decode->decoder_mutex);
     g_cond_init(&decode->decoder_ready);
old mode 100644 (file)
new mode 100755 (executable)
index a15aeb3..ff27780
@@ -76,7 +76,8 @@ struct _GstVaapiDecode {
     gint64              render_time_base;
     GstClockTime        last_buffer_time;
     unsigned int        is_ready        : 1;
-    gboolean            break_flag;
+    // escape decoding (blocked by hw resource) when there is _flush event, usually happens during seek.
+    unsigned int        escape_decoding : 1;
 };
 
 struct _GstVaapiDecodeClass {