tiger: fallback on headers in caps to initialize if headers are absent
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Thu, 23 Dec 2010 18:18:50 +0000 (18:18 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Sun, 26 Dec 2010 21:47:53 +0000 (21:47 +0000)
When Totem switches streams, tiger will be reset, and start receiving
buffers from the middle of the stream, without being sent headers.
If this happens, try to get headers from the caps.

https://bugzilla.gnome.org/show_bug.cgi?id=638004

ext/kate/gstkatetiger.c
ext/kate/gstkatetiger.h

index d5a2faf3a03a4b96aafa528796f9e657a98b05ae..67d046aaa8288907f0ce1ee70021f4b90b4e3283 100644 (file)
@@ -355,6 +355,8 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass)
 
   tiger->video_width = 0;
   tiger->video_height = 0;
+
+  tiger->seen_header = FALSE;
 }
 
 static void
@@ -565,6 +567,50 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf)
   GST_LOG_OBJECT (tiger, "Got kate buffer, caps %s",
       gst_caps_to_string (GST_BUFFER_CAPS (buf)));
 
+  /* Unfortunately, it can happen that the start of the stream is not sent,
+     for instance if there's a stream selector upstream, which is switched
+     from another Kate stream. If this happens, then we can fallback on the
+     headers stored in the caps (if any). */
+  if (!tiger->seen_header) {
+    if (GST_BUFFER_SIZE (buf) == 0 || (GST_BUFFER_DATA (buf)[0] & 0x80) == 0) {
+      /* Not a header, try to fall back on caps */
+      GstStructure *s;
+      const GValue *streamheader;
+
+      GST_INFO_OBJECT (tiger, "Headers not seen, start of stream is cut off");
+      s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0);
+      streamheader = gst_structure_get_value (s, "streamheader");
+      if (streamheader && G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY) {
+        GstPad *tagpad = gst_pad_get_peer (pad);
+        GArray *array;
+        gint i;
+
+        GST_INFO_OBJECT (tiger, "Falling back on caps to initialize decoder");
+        array = g_value_peek_pointer (streamheader);
+        for (i = 0; i < array->len; i++) {
+          GValue *value = &g_array_index (array, GValue, i);
+          if (G_VALUE_TYPE (value) == GST_TYPE_BUFFER) {
+            GstBuffer *hbuf = g_value_peek_pointer (value);
+            gst_buffer_ref (hbuf);
+            rflow =
+                gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder,
+                GST_ELEMENT_CAST (tiger), pad, hbuf, tiger->srcpad, tagpad,
+                NULL, NULL);
+          } else {
+            GST_WARNING_OBJECT (tiger,
+                "Streamheader index %d does not hold a buffer", i);
+          }
+        }
+        gst_object_unref (tagpad);
+        tiger->seen_header = TRUE;
+      } else {
+        GST_WARNING_OBJECT (tiger, "No headers seen, and no headers on caps");
+      }
+    } else {
+      tiger->seen_header = TRUE;
+    }
+  }
+
   if (gst_kate_util_decoder_base_update_segment (&tiger->decoder,
           GST_ELEMENT_CAST (tiger), buf)) {
     GstPad *tagpad = gst_pad_get_peer (pad);
@@ -750,6 +796,7 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition)
       }
       gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
       tiger->video_flushing = FALSE;
+      tiger->seen_header = FALSE;
       GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
       break;
     default:
index 353f9f79ec33a2a0b62a4db1b5d8ce2d64b530e4..48884b1c22baf0cf9f9e267e59f0233aa5698ca5 100644 (file)
@@ -97,6 +97,7 @@ struct _GstKateTiger
 
   GstSegment video_segment;
   gboolean video_flushing;
+  gboolean seen_header;
 };
 
 struct _GstKateTigerClass