diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c index 8d4afaa0b1..5e301a6c4f 100644 --- a/ext/smoothstreaming/gstmssdemux.c +++ b/ext/smoothstreaming/gstmssdemux.c @@ -123,7 +123,7 @@ gst_mss_demux_init (GstMssDemux * mssdemux, GstMssDemuxClass * klass) static GstMssDemuxStream * gst_mss_demux_stream_new (GstMssDemux * mssdemux, - GstMssManifestStream * manifeststream, GstPad * srcpad) + GstMssStream * manifeststream, GstPad * srcpad) { GstMssDemuxStream *stream; @@ -190,6 +190,8 @@ gst_mss_demux_reset (GstMssDemux * mssdemux) } mssdemux->n_videos = mssdemux->n_audios = 0; + g_free (mssdemux->base_url); + mssdemux->base_url = NULL; } static void @@ -242,6 +244,18 @@ gst_mss_demux_chain (GstPad * pad, GstBuffer * buffer) return GST_FLOW_OK; } +static void +gst_mss_demux_start (GstMssDemux * mssdemux) +{ + GSList *iter; + + GST_INFO_OBJECT (mssdemux, "Starting streams' tasks"); + for (iter = mssdemux->streams; iter; iter = g_slist_next (iter)) { + GstMssDemuxStream *stream = iter->data; + gst_task_start (stream->stream_task); + } +} + static gboolean gst_mss_demux_event (GstPad * pad, GstEvent * event) { @@ -257,6 +271,7 @@ gst_mss_demux_event (GstPad * pad, GstEvent * event) } gst_mss_demux_process_manifest (mssdemux); + gst_mss_demux_start (mssdemux); forward = FALSE; break; default: @@ -287,12 +302,12 @@ gst_mss_demux_create_streams (GstMssDemux * mssdemux) gchar *name; GstPad *srcpad = NULL; GstMssDemuxStream *stream = NULL; - GstMssManifestStream *manifeststream = iter->data; - GstMssManifestStreamType streamtype; + GstMssStream *manifeststream = iter->data; + GstMssStreamType streamtype; - streamtype = gst_mss_manifest_stream_get_type (manifeststream); + streamtype = gst_mss_stream_get_type (manifeststream); GST_DEBUG_OBJECT (mssdemux, "Found stream of type: %s", - gst_mss_manifest_stream_type_name (streamtype)); + gst_mss_stream_type_name (streamtype)); /* TODO use stream's name as the pad name? */ if (streamtype == MSS_STREAM_TYPE_VIDEO) { @@ -325,7 +340,7 @@ gst_mss_demux_expose_stream (GstMssDemux * mssdemux, GstMssDemuxStream * stream) GstCaps *caps; GstPad *pad = stream->pad; - caps = gst_mss_manifest_stream_get_caps (stream->manifest_stream); + caps = gst_mss_stream_get_caps (stream->manifest_stream); if (caps) { gst_pad_set_caps (pad, caps); @@ -354,9 +369,19 @@ gst_mss_demux_process_manifest (GstMssDemux * mssdemux) query = gst_query_new_uri (); ret = gst_pad_peer_query (mssdemux->sinkpad, query); if (ret) { + gchar *baseurl_end; gst_query_parse_uri (query, &uri); - /* TODO use this to get the base url for the fragments */ - g_free (uri); + GST_INFO_OBJECT (mssdemux, "Upstream is using URI: %s", uri); + + baseurl_end = g_strrstr (uri, "/Manifest"); + if (baseurl_end) { + /* set the new end of the string */ + baseurl_end[0] = '\0'; + } else { + GST_WARNING_OBJECT (mssdemux, "Stream's URI didn't end with /manifest"); + } + + mssdemux->base_url = uri; } gst_query_unref (query); @@ -376,27 +401,33 @@ gst_mss_demux_process_manifest (GstMssDemux * mssdemux) static void gst_mss_demux_stream_loop (GstMssDemuxStream * stream) { + GstMssDemux *mssdemux = stream->parent; + gchar *path; gchar *url; GstFragment *fragment; GstBufferList *buflist; GstFlowReturn ret; - ret = gst_mss_manifest_stream_get_fragment_url (stream->manifest_stream, - &url); + GST_DEBUG_OBJECT (mssdemux, "Getting url for stream %p", stream); + ret = gst_mss_stream_get_fragment_url (stream->manifest_stream, &path); switch (ret) { default: break; } - if (!url) { + if (!path) { /* TODO */ } + GST_DEBUG_OBJECT (mssdemux, "Got url path '%s' for stream %p", path, stream); + + url = g_strdup_printf ("%s/%s", mssdemux->base_url, path); fragment = gst_uri_downloader_fetch_uri (stream->downloader, url); + g_free (path); g_free (url); buflist = gst_fragment_get_buffer_list (fragment); ret = gst_pad_push_list (stream->pad, buflist); /* TODO check return */ - ret = gst_mss_manifest_stream_advance_fragment (stream->manifest_stream); + ret = gst_mss_stream_advance_fragment (stream->manifest_stream); } diff --git a/ext/smoothstreaming/gstmssdemux.h b/ext/smoothstreaming/gstmssdemux.h index 9fb0ecd77b..52c2377e00 100644 --- a/ext/smoothstreaming/gstmssdemux.h +++ b/ext/smoothstreaming/gstmssdemux.h @@ -55,7 +55,7 @@ struct _GstMssDemuxStream { GstMssDemux *parent; - GstMssManifestStream *manifest_stream; + GstMssStream *manifest_stream; GstUriDownloader *downloader; @@ -73,6 +73,7 @@ struct _GstMssDemux { GstBuffer *manifest_buffer; GstMssManifest *manifest; + gchar *base_url; GSList *streams; guint n_videos; diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c index 1bfbe64270..8d92a0ddac 100644 --- a/ext/smoothstreaming/gstmssmanifest.c +++ b/ext/smoothstreaming/gstmssmanifest.c @@ -38,14 +38,14 @@ /* TODO check if atoi is successful? */ -typedef struct _GstMssManifestStreamFragment +typedef struct _GstMssStreamFragment { guint number; guint64 time; guint64 duration; -} GstMssManifestStreamFragment; +} GstMssStreamFragment; -struct _GstMssManifestStream +struct _GstMssStream { xmlNodePtr xmlnode; @@ -79,10 +79,10 @@ node_has_type (xmlNodePtr node, const gchar * name) } static void -_gst_mss_manifest_stream_init (GstMssManifestStream * stream, xmlNodePtr node) +_gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node) { xmlNodePtr iter; - GstMssManifestStreamFragment *previous_fragment = NULL; + GstMssStreamFragment *previous_fragment = NULL; guint fragment_number = 0; guint fragment_time_accum = 0; GError *gerror = NULL; @@ -97,8 +97,7 @@ _gst_mss_manifest_stream_init (GstMssManifestStream * stream, xmlNodePtr node) gchar *duration_str; gchar *time_str; gchar *seqnum_str; - GstMssManifestStreamFragment *fragment = - g_new (GstMssManifestStreamFragment, 1); + GstMssStreamFragment *fragment = g_new (GstMssStreamFragment, 1); duration_str = (gchar *) xmlGetProp (iter, (xmlChar *) MSS_PROP_DURATION); time_str = (gchar *) xmlGetProp (iter, (xmlChar *) MSS_PROP_TIME); @@ -171,10 +170,10 @@ gst_mss_manifest_new (const GstBuffer * data) for (nodeiter = root->children; nodeiter; nodeiter = nodeiter->next) { if (nodeiter->type == XML_ELEMENT_NODE && (strcmp ((const char *) nodeiter->name, "StreamIndex") == 0)) { - GstMssManifestStream *stream = g_new0 (GstMssManifestStream, 1); + GstMssStream *stream = g_new0 (GstMssStream, 1); manifest->streams = g_slist_append (manifest->streams, stream); - _gst_mss_manifest_stream_init (stream, nodeiter); + _gst_mss_stream_init (stream, nodeiter); } } @@ -182,7 +181,7 @@ gst_mss_manifest_new (const GstBuffer * data) } static void -gst_mss_manifest_stream_free (GstMssManifestStream * stream) +gst_mss_stream_free (GstMssStream * stream) { g_list_free_full (stream->fragments, g_free); g_list_free (stream->qualities); @@ -197,8 +196,7 @@ gst_mss_manifest_free (GstMssManifest * manifest) { g_return_if_fail (manifest != NULL); - g_slist_free_full (manifest->streams, - (GDestroyNotify) gst_mss_manifest_stream_free); + g_slist_free_full (manifest->streams, (GDestroyNotify) gst_mss_stream_free); xmlFreeDoc (manifest->xml); g_free (manifest); @@ -210,11 +208,11 @@ gst_mss_manifest_get_streams (GstMssManifest * manifest) return manifest->streams; } -GstMssManifestStreamType -gst_mss_manifest_stream_get_type (GstMssManifestStream * stream) +GstMssStreamType +gst_mss_stream_get_type (GstMssStream * stream) { gchar *prop = (gchar *) xmlGetProp (stream->xmlnode, (xmlChar *) "Type"); - GstMssManifestStreamType ret = MSS_STREAM_TYPE_UNKNOWN; + GstMssStreamType ret = MSS_STREAM_TYPE_UNKNOWN; if (strcmp (prop, "video") == 0) { ret = MSS_STREAM_TYPE_VIDEO; @@ -226,7 +224,7 @@ gst_mss_manifest_stream_get_type (GstMssManifestStream * stream) } static GstCaps * -_gst_mss_manifest_stream_video_caps_from_fourcc (gchar * fourcc) +_gst_mss_stream_video_caps_from_fourcc (gchar * fourcc) { if (!fourcc) return NULL; @@ -238,7 +236,7 @@ _gst_mss_manifest_stream_video_caps_from_fourcc (gchar * fourcc) } static GstCaps * -_gst_mss_manifest_stream_audio_caps_from_fourcc (gchar * fourcc) +_gst_mss_stream_audio_caps_from_fourcc (gchar * fourcc) { if (!fourcc) return NULL; @@ -251,7 +249,7 @@ _gst_mss_manifest_stream_audio_caps_from_fourcc (gchar * fourcc) } static GstCaps * -_gst_mss_manifest_stream_video_caps_from_qualitylevel_xml (xmlNodePtr node) +_gst_mss_stream_video_caps_from_qualitylevel_xml (xmlNodePtr node) { GstCaps *caps; GstStructure *structure; @@ -261,7 +259,7 @@ _gst_mss_manifest_stream_video_caps_from_qualitylevel_xml (xmlNodePtr node) gchar *codec_data = (gchar *) xmlGetProp (node, (xmlChar *) "CodecPrivateData"); - caps = _gst_mss_manifest_stream_video_caps_from_fourcc (fourcc); + caps = _gst_mss_stream_video_caps_from_fourcc (fourcc); if (!caps) goto end; @@ -290,7 +288,7 @@ end: } static GstCaps * -_gst_mss_manifest_stream_audio_caps_from_qualitylevel_xml (xmlNodePtr node) +_gst_mss_stream_audio_caps_from_qualitylevel_xml (xmlNodePtr node) { GstCaps *caps; GstStructure *structure; @@ -300,7 +298,7 @@ _gst_mss_manifest_stream_audio_caps_from_qualitylevel_xml (xmlNodePtr node) gchar *codec_data = (gchar *) xmlGetProp (node, (xmlChar *) "CodecPrivateData"); - caps = _gst_mss_manifest_stream_audio_caps_from_fourcc (fourcc); + caps = _gst_mss_stream_audio_caps_from_fourcc (fourcc); if (!caps) goto end; @@ -329,32 +327,26 @@ end: } GstCaps * -gst_mss_manifest_stream_get_caps (GstMssManifestStream * stream) +gst_mss_stream_get_caps (GstMssStream * stream) { - GstMssManifestStreamType streamtype = - gst_mss_manifest_stream_get_type (stream); + GstMssStreamType streamtype = gst_mss_stream_get_type (stream); xmlNodePtr qualitylevel = stream->current_quality->data; if (streamtype == MSS_STREAM_TYPE_VIDEO) - return - _gst_mss_manifest_stream_video_caps_from_qualitylevel_xml - (qualitylevel); + return _gst_mss_stream_video_caps_from_qualitylevel_xml (qualitylevel); else if (streamtype == MSS_STREAM_TYPE_AUDIO) - return - _gst_mss_manifest_stream_audio_caps_from_qualitylevel_xml - (qualitylevel); + return _gst_mss_stream_audio_caps_from_qualitylevel_xml (qualitylevel); return NULL; } GstFlowReturn -gst_mss_manifest_stream_get_fragment_url (GstMssManifestStream * stream, - gchar ** url) +gst_mss_stream_get_fragment_url (GstMssStream * stream, gchar ** url) { gchar *tmp; gchar *bitrate_str; gchar *start_time_str; - GstMssManifestStreamFragment *fragment = stream->current_fragment->data; + GstMssStreamFragment *fragment = stream->current_fragment->data; if (stream->current_fragment == NULL) /* stream is over */ return GST_FLOW_UNEXPECTED; @@ -376,7 +368,7 @@ gst_mss_manifest_stream_get_fragment_url (GstMssManifestStream * stream, } GstFlowReturn -gst_mss_manifest_stream_advance_fragment (GstMssManifestStream * stream) +gst_mss_stream_advance_fragment (GstMssStream * stream) { if (stream->current_fragment == NULL) return GST_FLOW_UNEXPECTED; @@ -388,7 +380,7 @@ gst_mss_manifest_stream_advance_fragment (GstMssManifestStream * stream) } const gchar * -gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype) +gst_mss_stream_type_name (GstMssStreamType streamtype) { switch (streamtype) { case MSS_STREAM_TYPE_VIDEO: diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h index e3e727ff77..c2bf37ecd3 100644 --- a/ext/smoothstreaming/gstmssmanifest.h +++ b/ext/smoothstreaming/gstmssmanifest.h @@ -30,24 +30,24 @@ G_BEGIN_DECLS typedef struct _GstMssManifest GstMssManifest; -typedef struct _GstMssManifestStream GstMssManifestStream; +typedef struct _GstMssStream GstMssStream; -typedef enum _GstMssManifestStreamType { +typedef enum _GstMssStreamType { MSS_STREAM_TYPE_UNKNOWN = 0, MSS_STREAM_TYPE_VIDEO = 1, MSS_STREAM_TYPE_AUDIO = 2 -} GstMssManifestStreamType; +} GstMssStreamType; GstMssManifest * gst_mss_manifest_new (const GstBuffer * data); void gst_mss_manifest_free (GstMssManifest * manifest); GSList * gst_mss_manifest_get_streams (GstMssManifest * manifest); -GstMssManifestStreamType gst_mss_manifest_stream_get_type (GstMssManifestStream *stream); -GstCaps * gst_mss_manifest_stream_get_caps (GstMssManifestStream * stream); -GstFlowReturn gst_mss_manifest_stream_get_fragment_url (GstMssManifestStream * stream, gchar ** url); -GstFlowReturn gst_mss_manifest_stream_advance_fragment (GstMssManifestStream * stream); +GstMssStreamType gst_mss_stream_get_type (GstMssStream *stream); +GstCaps * gst_mss_stream_get_caps (GstMssStream * stream); +GstFlowReturn gst_mss_stream_get_fragment_url (GstMssStream * stream, gchar ** url); +GstFlowReturn gst_mss_stream_advance_fragment (GstMssStream * stream); -const gchar * gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype); +const gchar * gst_mss_stream_type_name (GstMssStreamType streamtype); G_END_DECLS #endif /* __GST_MSS_MANIFEST_H__ */