mssdemux: handle src pad queries fir duration and latency
authorThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 26 Dec 2012 19:19:14 +0000 (16:19 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 8 May 2013 00:05:11 +0000 (21:05 -0300)
Add a src pad query handler to get the duration from the manifest
and report it upstream.

Also adds a simple handler for latency queries

ext/smoothstreaming/gstmssdemux.c
ext/smoothstreaming/gstmssmanifest.c
ext/smoothstreaming/gstmssmanifest.h

index a12e2dd..d2a68f7 100644 (file)
@@ -69,6 +69,8 @@ gst_mss_demux_change_state (GstElement * element, GstStateChange transition);
 static GstFlowReturn gst_mss_demux_chain (GstPad * pad, GstBuffer * buffer);
 static GstFlowReturn gst_mss_demux_event (GstPad * pad, GstEvent * event);
 
+static gboolean gst_mss_demux_src_query (GstPad * pad, GstQuery * query);
+
 static void gst_mss_demux_stream_loop (GstMssDemuxStream * stream);
 
 static void gst_mss_demux_process_manifest (GstMssDemux * mssdemux);
@@ -293,6 +295,63 @@ gst_mss_demux_event (GstPad * pad, GstEvent * event)
   return ret;
 }
 
+static gboolean
+gst_mss_demux_src_query (GstPad * pad, GstQuery * query)
+{
+  GstMssDemux *mssdemux;
+  gboolean ret = FALSE;
+
+  if (query == NULL)
+    return FALSE;
+
+  mssdemux = GST_MSS_DEMUX (GST_PAD_PARENT (pad));
+
+  switch (query->type) {
+    case GST_QUERY_DURATION:{
+      GstClockTime duration = -1;
+      GstFormat fmt;
+
+      gst_query_parse_duration (query, &fmt, NULL);
+      if (fmt == GST_FORMAT_TIME && mssdemux->manifest) {
+        /* TODO should we use the streams accumulated duration? */
+        guint64 dur = gst_mss_manifest_get_duration (mssdemux->manifest);
+        guint64 timescale = gst_mss_manifest_get_timescale (mssdemux->manifest);
+
+        if (dur != -1 && timescale != -1)
+          duration =
+              (GstClockTime) gst_util_uint64_scale_round (dur, GST_SECOND,
+              timescale);
+
+        if (GST_CLOCK_TIME_IS_VALID (duration) && duration > 0) {
+          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
+          ret = TRUE;
+        }
+      }
+      GST_INFO_OBJECT (mssdemux, "GST_QUERY_DURATION returns %s with duration %"
+          GST_TIME_FORMAT, ret ? "TRUE" : "FALSE", GST_TIME_ARGS (duration));
+      break;
+    }
+    case GST_QUERY_LATENCY:
+      gst_query_set_latency (query, FALSE, 0, -1);
+      ret = TRUE;
+      break;
+    default:
+      /* Don't fordward queries upstream because of the special nature of this
+       *  "demuxer", which relies on the upstream element only to be fed
+       *  the Manifest
+       */
+      break;
+  }
+
+  return ret;
+}
+
+static void
+_set_src_pad_functions (GstPad * pad)
+{
+  gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_mss_demux_src_query));
+}
+
 static void
 gst_mss_demux_create_streams (GstMssDemux * mssdemux)
 {
@@ -338,6 +397,8 @@ gst_mss_demux_create_streams (GstMssDemux * mssdemux)
       continue;
     }
 
+    _set_src_pad_functions (srcpad);
+
     stream = gst_mss_demux_stream_new (mssdemux, manifeststream, srcpad);
     mssdemux->streams = g_slist_append (mssdemux->streams, stream);
   }
index 8f20ab8..34c36f6 100644 (file)
@@ -38,6 +38,7 @@
 #define MSS_PROP_BITRATE              "Bitrate"
 #define MSS_PROP_DURATION             "d"
 #define MSS_PROP_NUMBER               "n"
+#define MSS_PROP_STREAM_DURATION      "Duration"
 #define MSS_PROP_TIME                 "t"
 #define MSS_PROP_TIMESCALE            "TimeScale"
 #define MSS_PROP_URL                  "Url"
@@ -463,6 +464,38 @@ gst_mss_stream_get_timescale (GstMssStream * stream)
   return ts;
 }
 
+guint64
+gst_mss_manifest_get_timescale (GstMssManifest * manifest)
+{
+  gchar *timescale;
+  guint64 ts = DEFAULT_TIMESCALE;
+
+  timescale =
+      (gchar *) xmlGetProp (manifest->xmlrootnode,
+      (xmlChar *) MSS_PROP_TIMESCALE);
+  if (timescale) {
+    ts = strtoull (timescale, NULL, 10);
+    g_free (timescale);
+  }
+  return ts;
+}
+
+guint64
+gst_mss_manifest_get_duration (GstMssManifest * manifest)
+{
+  gchar *duration;
+  guint64 dur = -1;
+
+  duration =
+      (gchar *) xmlGetProp (manifest->xmlrootnode,
+      (xmlChar *) MSS_PROP_STREAM_DURATION);
+  if (duration) {
+    dur = strtoull (duration, NULL, 10);
+    g_free (duration);
+  }
+  return dur;
+}
+
 GstCaps *
 gst_mss_stream_get_caps (GstMssStream * stream)
 {
index 7b5f1f7..280bdae 100644 (file)
@@ -41,6 +41,8 @@ typedef enum _GstMssStreamType {
 GstMssManifest * gst_mss_manifest_new (const GstBuffer * data);
 void gst_mss_manifest_free (GstMssManifest * manifest);
 GSList * gst_mss_manifest_get_streams (GstMssManifest * manifest);
+guint64 gst_mss_manifest_get_timescale (GstMssManifest * manifest);
+guint64 gst_mss_manifest_get_duration (GstMssManifest * manifest);
 
 GstMssStreamType gst_mss_stream_get_type (GstMssStream *stream);
 GstCaps * gst_mss_stream_get_caps (GstMssStream * stream);