mssdemux: add manifest parsing
authorThiago Santos <thiago.sousa.santos@collabora.com>
Fri, 9 Nov 2012 19:47:54 +0000 (16:47 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 8 May 2013 00:05:10 +0000 (21:05 -0300)
Continued implementing:
1) parse the manifest with libxml2
2) detect stream types

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

index 5f19316..9fb1daf 100644 (file)
@@ -211,11 +211,51 @@ gst_mss_demux_event (GstPad * pad, GstEvent * event)
 }
 
 static void
+gst_mss_demux_create_streams (GstMssDemux * mssdemux)
+{
+  GSList *streams = gst_mss_manifest_get_streams (mssdemux->manifest);
+  GSList *iter;
+
+  if (streams == NULL) {
+    GST_INFO_OBJECT (mssdemux, "No streams found in the manifest");
+    /* TODO  post eos? */
+  }
+
+  for (iter = streams; iter; iter = g_slist_next (iter)) {
+    GstMssManifestStream *manifeststream = iter->data;
+    GstMssManifestStreamType streamtype;
+
+    streamtype = gst_mss_manifest_stream_get_type (manifeststream);
+    GST_DEBUG_OBJECT (mssdemux, "Found stream of type: %s",
+        gst_mss_manifest_stream_type_name (streamtype));
+  }
+}
+
+static void
 gst_mss_demux_process_manifest (GstMssDemux * mssdemux)
 {
+  GstQuery *query;
+  gchar *uri = NULL;
+  gboolean ret;
+
   g_return_if_fail (mssdemux->manifest_buffer != NULL);
   g_return_if_fail (mssdemux->manifest == NULL);
 
+  query = gst_query_new_uri ();
+  ret = gst_pad_peer_query (mssdemux->sinkpad, query);
+  if (ret) {
+    gst_query_parse_uri (query, &uri);
+    /* TODO use this to get the base url for the fragments */
+    g_free (uri);
+  }
+  gst_query_unref (query);
+
   mssdemux->manifest = gst_mss_manifest_new (mssdemux->manifest_buffer);
-  /* TODO */
+  if (!mssdemux->manifest) {
+    GST_ELEMENT_ERROR (mssdemux, STREAM, FORMAT, ("Bad manifest file"),
+        ("Xml manifest file couldn't be parsed"));
+    return;
+  }
+
+  gst_mss_demux_create_streams (mssdemux);
 }
index f2003ae..3e0096d 100644 (file)
  */
 
 #include <glib.h>
+#include <string.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
 
 #include "gstmssmanifest.h"
 
+struct _GstMssManifestStream
+{
+  xmlNodePtr xmlnode;
+};
+
 struct _GstMssManifest
 {
+  xmlDocPtr xml;
+  xmlNodePtr xmlrootnode;
+
+  GSList *streams;
 };
 
 GstMssManifest *
-gst_mss_manifest_new (GstBuffer * data)
+gst_mss_manifest_new (const GstBuffer * data)
 {
   GstMssManifest *manifest;
+  xmlNodePtr root;
+  xmlNodePtr nodeiter;
 
   manifest = g_malloc0 (sizeof (GstMssManifest));
 
+  manifest->xml = xmlReadMemory ((const gchar *) GST_BUFFER_DATA (data),
+      GST_BUFFER_SIZE (data), "manifest", NULL, 0);
+  root = manifest->xmlrootnode = xmlDocGetRootElement (manifest->xml);
+
+  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);
+
+      manifest->streams = g_slist_append (manifest->streams, stream);
+      stream->xmlnode = nodeiter;
+    }
+  }
+
   return manifest;
 }
 
@@ -42,5 +70,44 @@ void
 gst_mss_manifest_free (GstMssManifest * manifest)
 {
   g_return_if_fail (manifest != NULL);
+
+  g_slist_free_full (manifest->streams, g_free);
+
+  xmlFreeDoc (manifest->xml);
   g_free (manifest);
 }
+
+GSList *
+gst_mss_manifest_get_streams (GstMssManifest * manifest)
+{
+  return manifest->streams;
+}
+
+GstMssManifestStreamType
+gst_mss_manifest_stream_get_type (GstMssManifestStream * stream)
+{
+  gchar *prop = (gchar *) xmlGetProp (stream->xmlnode, (xmlChar *) "Type");
+  GstMssManifestStreamType ret = MSS_STREAM_TYPE_UNKNOWN;
+
+  if (strcmp (prop, "video") == 0) {
+    ret = MSS_STREAM_TYPE_VIDEO;
+  } else if (strcmp (prop, "audio") == 0) {
+    ret = MSS_STREAM_TYPE_AUDIO;
+  }
+  xmlFree (prop);
+  return ret;
+}
+
+const gchar *
+gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype)
+{
+  switch (streamtype) {
+    case MSS_STREAM_TYPE_VIDEO:
+      return "video";
+    case MSS_STREAM_TYPE_AUDIO:
+      return "audio";
+    case MSS_STREAM_TYPE_UNKNOWN:
+    default:
+      return "unknown";
+  }
+}
index ce033e4..21b860a 100644 (file)
 G_BEGIN_DECLS
 
 typedef struct _GstMssManifest GstMssManifest;
+typedef struct _GstMssManifestStream GstMssManifestStream;
 
-GstMssManifest * gst_mss_manifest_new (GstBuffer * data); 
+typedef enum _GstMssManifestStreamType {
+  MSS_STREAM_TYPE_UNKNOWN = 0,
+  MSS_STREAM_TYPE_VIDEO = 1,
+  MSS_STREAM_TYPE_AUDIO = 2
+} GstMssManifestStreamType;
+
+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);
+
+const gchar * gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype);
 
 G_END_DECLS
 #endif /* __GST_MSS_MANIFEST_H__ */