From 33d872916b9e0297d16c67cb90bdbe4f41e08fdc Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 26 Dec 2012 16:19:14 -0300 Subject: [PATCH] mssdemux: handle src pad queries fir duration and latency 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 | 61 ++++++++++++++++++++++++++++ ext/smoothstreaming/gstmssmanifest.c | 33 +++++++++++++++ ext/smoothstreaming/gstmssmanifest.h | 2 + 3 files changed, 96 insertions(+) diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c index a12e2ddc31..d2a68f7068 100644 --- a/ext/smoothstreaming/gstmssdemux.c +++ b/ext/smoothstreaming/gstmssdemux.c @@ -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); } diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c index 8f20ab8025..34c36f69e9 100644 --- a/ext/smoothstreaming/gstmssmanifest.c +++ b/ext/smoothstreaming/gstmssmanifest.c @@ -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) { diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h index 7b5f1f7af0..280bdaeebf 100644 --- a/ext/smoothstreaming/gstmssmanifest.h +++ b/ext/smoothstreaming/gstmssmanifest.h @@ -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); -- 2.34.1