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);
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)
{
continue;
}
+ _set_src_pad_functions (srcpad);
+
stream = gst_mss_demux_stream_new (mssdemux, manifeststream, srcpad);
mssdemux->streams = g_slist_append (mssdemux->streams, stream);
}
#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"
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)
{
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);