smoothstreaming: refactor structure names and implement url fetching
authorThiago Santos <thiago.sousa.santos@collabora.com>
Mon, 19 Nov 2012 20:53:16 +0000 (17:53 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 8 May 2013 00:05:10 +0000 (21:05 -0300)
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

ext/smoothstreaming/gstmssdemux.c
ext/smoothstreaming/gstmssdemux.h
ext/smoothstreaming/gstmssmanifest.c
ext/smoothstreaming/gstmssmanifest.h

index 8d4afaa0b189a5c25c0bf3ee01a05a071ac6e3e0..5e301a6c4fa9f5acbc544ac9c8bf4fb33ce666a6 100644 (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);
 }
index 9fb0ecd77b4cf1115e582ac3664a33d5c33c5772..52c2377e002c8014fe0aae8f69403637012c06db 100644 (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;
index 1bfbe642702213d9058fcea0fe46c46a31688da8..8d92a0ddace0a9bdf115f94b57de9af4c9b357b9 100644 (file)
 
 /* 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:
index e3e727ff77865827f423b84f6345d9a9bf48f312..c2bf37ecd319a805e6a53034f9fe06038717b415 100644 (file)
 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__ */