discoverer: try harder to obtain a duration if we don't get one right away
authorTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 14 Feb 2012 19:23:27 +0000 (19:23 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 14 Feb 2012 19:36:43 +0000 (19:36 +0000)
If we don't get a duration right away, set the pipeline to playing
and sleep a bit, then try again. This is ugly, but the least worst
we can do right now. The alternative would be to make parsers etc.
return some bogus duration estimate even after only having pushed
a single frame, for example.

Fixes discoverer showing 0 durations for some mp3 and aac files
(e.g. soweto-adts.aac).

gst-libs/gst/pbutils/gstdiscoverer.c

index 8d2d03b..ba02cdb 100644 (file)
@@ -1026,6 +1026,31 @@ discoverer_collect (GstDiscoverer * dc)
           GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
           dc->priv->current_info->duration = (guint64) dur;
         }
+      } else {
+        GstStateChangeReturn sret;
+
+        /* Some parsers may not even return a rough estimate right away, e.g.
+         * because they've only processed a single frame so far, so if we
+         * didn't get a duration the first time, spin a bit and try again.
+         * Ugly, but still better than making parsers or other elements return
+         * completely bogus values. We need some API extensions to solve this
+         * better. */
+        GST_INFO ("No duration yet, try a bit harder..");
+        sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+        if (sret != GST_STATE_CHANGE_FAILURE) {
+          int i;
+
+          for (i = 0; i < 2; ++i) {
+            g_usleep (G_USEC_PER_SEC / 20);
+            if (gst_element_query_duration (pipeline, &format, &dur) &&
+                format == GST_FORMAT_TIME && dur > 0) {
+              GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
+              dc->priv->current_info->duration = (guint64) dur;
+              break;
+            }
+          }
+          gst_element_set_state (pipeline, GST_STATE_PAUSED);
+        }
       }
 
       if (dc->priv->seeking_query) {