From 72b05c0051114f6626e3e1c7a208d6faefe63219 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 9 Nov 2012 16:47:54 -0300 Subject: [PATCH] mssdemux: add manifest parsing Continued implementing: 1) parse the manifest with libxml2 2) detect stream types --- ext/smoothstreaming/gstmssdemux.c | 42 ++++++++++++++++- ext/smoothstreaming/gstmssmanifest.c | 69 +++++++++++++++++++++++++++- ext/smoothstreaming/gstmssmanifest.h | 14 +++++- 3 files changed, 122 insertions(+), 3 deletions(-) diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c index 5f1931688f..9fb1daf5ec 100644 --- a/ext/smoothstreaming/gstmssdemux.c +++ b/ext/smoothstreaming/gstmssdemux.c @@ -210,12 +210,52 @@ gst_mss_demux_event (GstPad * pad, GstEvent * event) return ret; } +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); } diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c index f2003ae3f8..3e0096d5bd 100644 --- a/ext/smoothstreaming/gstmssmanifest.c +++ b/ext/smoothstreaming/gstmssmanifest.c @@ -21,20 +21,48 @@ */ #include +#include +#include +#include #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"; + } +} diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h index ce033e4aba..21b860a2d4 100644 --- a/ext/smoothstreaming/gstmssmanifest.h +++ b/ext/smoothstreaming/gstmssmanifest.h @@ -30,9 +30,21 @@ 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__ */ -- 2.34.1