smoothstreaming: refactor structure names and implement url fetching

Use shorter names for the MSS manifest helper structure and functions.

Also continues the implementation of the stream fetching and pushing loop.
Now it uses the base url correctly and already fetches and pushes the fragments
downstream
This commit is contained in:
Thiago Santos 2012-11-19 17:53:16 -03:00
parent 7ceb023682
commit ca4e5c34cb
4 changed files with 80 additions and 56 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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:

View file

@ -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__ */