summaryrefslogtreecommitdiff
path: root/ext/smoothstreaming
diff options
context:
space:
mode:
authorThiago Santos <thiago.sousa.santos@collabora.com>2012-11-14 17:19:35 -0300
committerThiago Santos <thiago.sousa.santos@collabora.com>2013-05-07 21:05:10 -0300
commit5291985efeccb3f8e3ffa903c162f8f948b657a1 (patch)
tree4741f965c88f4768205362e4444acb08cc6b5af1 /ext/smoothstreaming
parent72b05c0051114f6626e3e1c7a208d6faefe63219 (diff)
downloadgstreamer-plugins-bad-5291985efeccb3f8e3ffa903c162f8f948b657a1.tar.gz
mssdemux: pad exposing initial implementation
Does some basic parsing of the stream caps and adds a pad for each stream detected in the manifest
Diffstat (limited to 'ext/smoothstreaming')
-rw-r--r--ext/smoothstreaming/gstmssdemux.c68
-rw-r--r--ext/smoothstreaming/gstmssdemux.h11
-rw-r--r--ext/smoothstreaming/gstmssmanifest.c129
-rw-r--r--ext/smoothstreaming/gstmssmanifest.h1
4 files changed, 209 insertions, 0 deletions
diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c
index 9fb1daf5e..eeefe57db 100644
--- a/ext/smoothstreaming/gstmssdemux.c
+++ b/ext/smoothstreaming/gstmssdemux.c
@@ -122,12 +122,26 @@ gst_mss_demux_init (GstMssDemux * mssdemux, GstMssDemuxClass * klass)
static void
gst_mss_demux_reset (GstMssDemux * mssdemux)
{
+ GSList *iter;
if (mssdemux->manifest_buffer) {
gst_buffer_unref (mssdemux->manifest_buffer);
+ mssdemux->manifest_buffer = NULL;
+ }
+
+ for (iter = mssdemux->streams; iter; iter = g_slist_next (iter)) {
+ GstMssDemuxStream *stream = iter->data;
+ gst_element_remove_pad (GST_ELEMENT_CAST (mssdemux), stream->pad);
+ g_free (stream);
}
+ g_slist_free (mssdemux->streams);
+ mssdemux->streams = NULL;
+
if (mssdemux->manifest) {
gst_mss_manifest_free (mssdemux->manifest);
+ mssdemux->manifest = NULL;
}
+
+ mssdemux->n_videos = mssdemux->n_audios = 0;
}
static void
@@ -222,12 +236,62 @@ gst_mss_demux_create_streams (GstMssDemux * mssdemux)
}
for (iter = streams; iter; iter = g_slist_next (iter)) {
+ gchar *name;
+ GstPad *srcpad = NULL;
+ GstMssDemuxStream *stream = NULL;
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));
+
+ /* TODO use stream's name as the pad name? */
+ if (streamtype == MSS_STREAM_TYPE_VIDEO) {
+ name = g_strdup_printf ("video_%02u", mssdemux->n_videos++);
+ srcpad =
+ gst_pad_new_from_static_template (&gst_mss_demux_videosrc_template,
+ name);
+ g_free (name);
+ } else if (streamtype == MSS_STREAM_TYPE_AUDIO) {
+ name = g_strdup_printf ("audio_%02u", mssdemux->n_audios++);
+ srcpad =
+ gst_pad_new_from_static_template (&gst_mss_demux_audiosrc_template,
+ name);
+ g_free (name);
+ }
+
+ if (!srcpad) {
+ GST_WARNING_OBJECT (mssdemux, "Ignoring unknown type stream");
+ continue;
+ }
+
+ stream = g_new (GstMssDemuxStream, 1);
+ stream->pad = srcpad;
+ stream->manifest_stream = manifeststream;
+ mssdemux->streams = g_slist_append (mssdemux->streams, stream);
+
+ }
+}
+
+static void
+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);
+
+ if (caps) {
+ gst_pad_set_caps (pad, caps);
+ gst_caps_unref (caps);
+
+ gst_pad_set_active (pad, TRUE);
+ GST_INFO_OBJECT (mssdemux, "Adding srcpad %s:%s with caps %" GST_PTR_FORMAT,
+ GST_DEBUG_PAD_NAME (pad), caps);
+ gst_element_add_pad (GST_ELEMENT_CAST (mssdemux), pad);
+ } else {
+ GST_WARNING_OBJECT (mssdemux, "Not exposing stream of unrecognized format");
}
}
@@ -237,6 +301,7 @@ gst_mss_demux_process_manifest (GstMssDemux * mssdemux)
GstQuery *query;
gchar *uri = NULL;
gboolean ret;
+ GSList *iter;
g_return_if_fail (mssdemux->manifest_buffer != NULL);
g_return_if_fail (mssdemux->manifest == NULL);
@@ -258,4 +323,7 @@ gst_mss_demux_process_manifest (GstMssDemux * mssdemux)
}
gst_mss_demux_create_streams (mssdemux);
+ for (iter = mssdemux->streams; iter; iter = g_slist_next (iter)) {
+ gst_mss_demux_expose_stream (mssdemux, iter->data);
+ }
}
diff --git a/ext/smoothstreaming/gstmssdemux.h b/ext/smoothstreaming/gstmssdemux.h
index 52f872b0a..2b14134d4 100644
--- a/ext/smoothstreaming/gstmssdemux.h
+++ b/ext/smoothstreaming/gstmssdemux.h
@@ -45,9 +45,16 @@ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
#define GST_MSS_DEMUX_CAST(obj) ((GstMssDemux *)(obj))
+typedef struct _GstMssDemuxStream GstMssDemuxStream;
typedef struct _GstMssDemux GstMssDemux;
typedef struct _GstMssDemuxClass GstMssDemuxClass;
+struct _GstMssDemuxStream {
+ GstPad *pad;
+
+ GstMssManifestStream *manifest_stream;
+};
+
struct _GstMssDemux {
GstElement element;
@@ -57,6 +64,10 @@ struct _GstMssDemux {
GstBuffer *manifest_buffer;
GstMssManifest *manifest;
+
+ GSList *streams;
+ guint n_videos;
+ guint n_audios;
};
struct _GstMssDemuxClass {
diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c
index 3e0096d5b..f71270ffe 100644
--- a/ext/smoothstreaming/gstmssmanifest.c
+++ b/ext/smoothstreaming/gstmssmanifest.c
@@ -30,6 +30,8 @@
struct _GstMssManifestStream
{
xmlNodePtr xmlnode;
+
+ gint selectedQualityIndex;
};
struct _GstMssManifest
@@ -98,6 +100,133 @@ gst_mss_manifest_stream_get_type (GstMssManifestStream * stream)
return ret;
}
+static GstCaps *
+_gst_mss_manifest_stream_video_caps_from_fourcc (gchar * fourcc)
+{
+ if (!fourcc)
+ return NULL;
+
+ if (strcmp (fourcc, "H264") == 0) {
+ return gst_caps_new_simple ("video/x-h264", NULL);
+ }
+ return NULL;
+}
+
+static GstCaps *
+_gst_mss_manifest_stream_audio_caps_from_fourcc (gchar * fourcc)
+{
+ if (!fourcc)
+ return NULL;
+
+ if (strcmp (fourcc, "AACL") == 0) {
+ return gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 4,
+ NULL);
+ }
+ return NULL;
+}
+
+static GstCaps *
+_gst_mss_manifest_stream_video_caps_from_qualitylevel_xml (xmlNodePtr node)
+{
+ GstCaps *caps;
+ GstStructure *structure;
+ gchar *fourcc = (gchar *) xmlGetProp (node, (xmlChar *) "FourCC");
+ gchar *max_width = (gchar *) xmlGetProp (node, (xmlChar *) "MaxWidth");
+ gchar *max_height = (gchar *) xmlGetProp (node, (xmlChar *) "MaxHeight");
+ gchar *codec_data =
+ (gchar *) xmlGetProp (node, (xmlChar *) "CodecPrivateData");
+
+ caps = _gst_mss_manifest_stream_video_caps_from_fourcc (fourcc);
+ if (!caps)
+ goto end;
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ if (max_width)
+ gst_structure_set (structure, "width", G_TYPE_INT, atoi (max_width), NULL);
+ if (max_height)
+ gst_structure_set (structure, "height", G_TYPE_INT, atoi (max_height),
+ NULL);
+
+ if (codec_data) {
+ GValue *value = g_new0 (GValue, 1);
+ g_value_init (value, GST_TYPE_BUFFER);
+ gst_value_deserialize (value, (gchar *) codec_data);
+ gst_structure_take_value (structure, "codec_data", value);
+ }
+
+end:
+ g_free (fourcc);
+ g_free (max_width);
+ g_free (max_height);
+ g_free (codec_data);
+
+ return caps;
+}
+
+static GstCaps *
+_gst_mss_manifest_stream_audio_caps_from_qualitylevel_xml (xmlNodePtr node)
+{
+ GstCaps *caps;
+ GstStructure *structure;
+ gchar *fourcc = (gchar *) xmlGetProp (node, (xmlChar *) "FourCC");
+ gchar *channels = (gchar *) xmlGetProp (node, (xmlChar *) "Channels");
+ gchar *rate = (gchar *) xmlGetProp (node, (xmlChar *) "SamplingRate");
+ gchar *codec_data =
+ (gchar *) xmlGetProp (node, (xmlChar *) "CodecPrivateData");
+
+ caps = _gst_mss_manifest_stream_audio_caps_from_fourcc (fourcc);
+ if (!caps)
+ goto end;
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ if (channels)
+ gst_structure_set (structure, "channels", G_TYPE_INT, atoi (channels),
+ NULL);
+ if (rate)
+ gst_structure_set (structure, "rate", G_TYPE_INT, atoi (rate), NULL);
+
+ if (codec_data) {
+ GValue *value = g_new0 (GValue, 1);
+ g_value_init (value, GST_TYPE_BUFFER);
+ gst_value_deserialize (value, (gchar *) codec_data);
+ gst_structure_take_value (structure, "codec_data", value);
+ }
+
+end:
+ g_free (fourcc);
+ g_free (channels);
+ g_free (rate);
+ g_free (codec_data);
+
+ return caps;
+}
+
+GstCaps *
+gst_mss_manifest_stream_get_caps (GstMssManifestStream * stream)
+{
+ GstMssManifestStreamType streamtype =
+ gst_mss_manifest_stream_get_type (stream);
+
+ /* TODO properly get the stream */
+ xmlNodePtr qualitylevel = stream->xmlnode->children;
+ while (strcmp ((gchar *) qualitylevel->name, "QualityLevel")) {
+ qualitylevel = qualitylevel->next;
+ }
+
+ if (streamtype == MSS_STREAM_TYPE_VIDEO)
+ return
+ _gst_mss_manifest_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 NULL;
+}
+
const gchar *
gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype)
{
diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h
index 21b860a2d..bbe907dab 100644
--- a/ext/smoothstreaming/gstmssmanifest.h
+++ b/ext/smoothstreaming/gstmssmanifest.h
@@ -43,6 +43,7 @@ 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);
const gchar * gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype);