vorbisdec: Always handle in-band header packets once the first non-header packet...
authorSebastian Dröge <sebastian@centricular.com>
Thu, 16 Aug 2018 16:37:33 +0000 (19:37 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 28 Aug 2018 14:47:09 +0000 (17:47 +0300)
And clean up any old pending headers if we receive a new identification
header, or if we receive a new set of headers via caps.

Otherwise it might happen that we receive one or more header but not
all, and then afterwards all headers again, and libvorbis does not like
getting headers passed multiple times and would error out.

It only makes sense to pass the very latest headers to the decoder at
the time we can actually make use of them.

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

ext/vorbis/gstvorbisdec.c

index f4e563c..eaa3848 100644 (file)
@@ -399,6 +399,14 @@ vorbis_dec_handle_header_caps (GstVorbisDec * vd)
     GstBuffer *buf = NULL;
     gint i = 0;
 
+    if (vd->pending_headers) {
+      GST_DEBUG_OBJECT (vd,
+          "got new headers from caps, discarding old pending headers");
+
+      g_list_free_full (vd->pending_headers, (GDestroyNotify) gst_buffer_unref);
+      vd->pending_headers = NULL;
+    }
+
     while (result == GST_FLOW_OK && i < gst_value_array_get_size (array)) {
       value = gst_value_array_get_value (array, i);
       buf = gst_value_get_buffer (value);
@@ -672,20 +680,17 @@ vorbis_dec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
 
   /* switch depending on packet type */
   if ((gst_ogg_packet_data (packet))[0] & 1) {
-    /* If we get a new initialization packet after being initialized,
-     * store it.
-     * When the next non-header buffer comes in, we will check whether
-     * those pending headers are correct and if so reset ourselves */
-    if (vd->initialized) {
-      GST_LOG_OBJECT (vd, "storing header for later analyzis");
-      vd->pending_headers =
-          g_list_append (vd->pending_headers, gst_buffer_ref (buffer));
-      goto done;
+    GST_LOG_OBJECT (vd, "storing header for later analyzis");
+    if (vd->pending_headers && (gst_ogg_packet_data (packet))[0] == 0x01) {
+      GST_DEBUG_OBJECT (vd,
+          "got new identification header packet, discarding old pending headers");
+
+      g_list_free_full (vd->pending_headers, (GDestroyNotify) gst_buffer_unref);
+      vd->pending_headers = NULL;
     }
-    result = vorbis_handle_header_packet (vd, packet);
-    if (result != GST_FLOW_OK)
-      goto done;
-    /* consumer header packet/frame */
+
+    vd->pending_headers =
+        g_list_append (vd->pending_headers, gst_buffer_ref (buffer));
     result = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (vd), NULL, 1);
   } else {
     GstClockTime timestamp, duration;