static GstMssDemuxStream *
gst_mss_demux_stream_new (GstMssDemux * mssdemux,
- GstMssManifestStream * manifeststream, GstPad * srcpad)
+ GstMssStream * manifeststream, GstPad * srcpad)
{
GstMssDemuxStream *stream;
}
mssdemux->n_videos = mssdemux->n_audios = 0;
+ g_free (mssdemux->base_url);
+ mssdemux->base_url = NULL;
}
static void
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)
{
}
gst_mss_demux_process_manifest (mssdemux);
+ gst_mss_demux_start (mssdemux);
forward = FALSE;
break;
default:
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) {
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);
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);
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);
}
/* 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;
}
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;
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);
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);
}
}
}
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);
{
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);
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;
}
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;
}
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;
}
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;
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;
}
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;
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;
}
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;
}
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;
}
const gchar *
-gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype)
+gst_mss_stream_type_name (GstMssStreamType streamtype)
{
switch (streamtype) {
case MSS_STREAM_TYPE_VIDEO:
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__ */