summaryrefslogtreecommitdiff
path: root/ext/smoothstreaming
diff options
context:
space:
mode:
Diffstat (limited to 'ext/smoothstreaming')
-rw-r--r--ext/smoothstreaming/gstmssdemux.c76
-rw-r--r--ext/smoothstreaming/gstmssdemux.h1
-rw-r--r--ext/smoothstreaming/gstmssmanifest.c61
-rw-r--r--ext/smoothstreaming/gstmssmanifest.h2
4 files changed, 140 insertions, 0 deletions
diff --git a/ext/smoothstreaming/gstmssdemux.c b/ext/smoothstreaming/gstmssdemux.c
index 8f10d7de0..d57c205bd 100644
--- a/ext/smoothstreaming/gstmssdemux.c
+++ b/ext/smoothstreaming/gstmssdemux.c
@@ -367,12 +367,34 @@ _create_pad (GstMssDemux * mssdemux, GstMssStream * manifeststream)
return srcpad;
}
+static void
+gst_mss_demux_apply_protection_system (GstCaps * caps,
+ const gchar * selected_system)
+{
+ GstStructure *s;
+
+ g_return_if_fail (selected_system);
+ s = gst_caps_get_structure (caps, 0);
+ gst_structure_set (s,
+ "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
+ GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
+ NULL);
+ gst_structure_set_name (s, "application/x-cenc");
+
+}
+
static gboolean
gst_mss_demux_setup_streams (GstAdaptiveDemux * demux)
{
GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (demux);
GSList *streams = gst_mss_manifest_get_streams (mssdemux->manifest);
GSList *iter;
+ const gchar *protection_system_id =
+ gst_mss_manifest_get_protection_system_id (mssdemux->manifest);
+ const gchar *protection_data =
+ gst_mss_manifest_get_protection_data (mssdemux->manifest);
+ gboolean protected = protection_system_id && protection_data;
+ const gchar *selected_system = NULL;
if (streams == NULL) {
GST_INFO_OBJECT (mssdemux, "No streams found in the manifest");
@@ -382,6 +404,17 @@ gst_mss_demux_setup_streams (GstAdaptiveDemux * demux)
return FALSE;
}
+ if (protected) {
+ const gchar *sys_ids[2] = { protection_system_id, NULL };
+
+ selected_system = gst_protection_select_system (sys_ids);
+ if (!selected_system) {
+ GST_ERROR_OBJECT (mssdemux, "stream is protected, but no "
+ "suitable decryptor element has been found");
+ return FALSE;
+ }
+ }
+
GST_INFO_OBJECT (mssdemux, "Changing max bitrate to %u",
demux->connection_speed);
gst_mss_manifest_change_bitrate (mssdemux->manifest, demux->connection_speed);
@@ -404,7 +437,13 @@ gst_mss_demux_setup_streams (GstAdaptiveDemux * demux)
srcpad);
stream->manifest_stream = manifeststream;
gst_mss_stream_set_active (manifeststream, TRUE);
+
caps = gst_mss_stream_get_caps (stream->manifest_stream);
+
+ if (protected) {
+ gst_mss_demux_apply_protection_system (caps, selected_system);
+ }
+
gst_adaptive_demux_stream_set_caps (GST_ADAPTIVE_DEMUX_STREAM_CAST (stream),
create_mss_caps (stream, caps));
gst_caps_unref (caps);
@@ -417,6 +456,22 @@ gst_mss_demux_setup_streams (GstAdaptiveDemux * demux)
gst_adaptive_demux_stream_set_tags (GST_ADAPTIVE_DEMUX_STREAM_CAST
(stream), tags);
}
+
+ if (protected) {
+ gsize protection_data_len;
+ guchar *decoded_data =
+ g_base64_decode (protection_data, &protection_data_len);
+ GstBuffer *protection_buffer =
+ gst_buffer_new_wrapped (decoded_data, protection_data_len);
+ GstEvent *event =
+ gst_event_new_protection (protection_system_id, protection_buffer,
+ "smooth-streaming");
+
+ GST_LOG_OBJECT (stream, "Queuing Protection event on source pad");
+ gst_adaptive_demux_stream_queue_event ((GstAdaptiveDemuxStream *) stream,
+ event);
+ gst_buffer_unref (protection_buffer);
+ }
}
return TRUE;
@@ -476,10 +531,31 @@ gst_mss_demux_stream_select_bitrate (GstAdaptiveDemuxStream * stream,
if (gst_mss_stream_select_bitrate (mssstream->manifest_stream, bitrate)) {
GstCaps *caps;
GstCaps *msscaps;
+ GstMssDemux *mssdemux = GST_MSS_DEMUX_CAST (stream->demux);
+ const gchar *protection_system_id =
+ gst_mss_manifest_get_protection_system_id (mssdemux->manifest);
+ const gchar *protection_data =
+ gst_mss_manifest_get_protection_data (mssdemux->manifest);
+ gboolean protected = protection_system_id && protection_data;
+
caps = gst_mss_stream_get_caps (mssstream->manifest_stream);
GST_DEBUG_OBJECT (stream->pad,
"Starting streams reconfiguration due to bitrate changes");
+
+ if (protected) {
+ const gchar *sys_ids[2] = { protection_system_id, NULL };
+ const gchar *selected_system = gst_protection_select_system (sys_ids);
+
+ if (!selected_system) {
+ GST_ERROR_OBJECT (mssdemux, "stream is protected, but no "
+ "suitable decryptor element has been found");
+ return FALSE;
+ }
+
+ gst_mss_demux_apply_protection_system (caps, selected_system);
+ }
+
msscaps = create_mss_caps (mssstream, caps);
GST_DEBUG_OBJECT (stream->pad,
diff --git a/ext/smoothstreaming/gstmssdemux.h b/ext/smoothstreaming/gstmssdemux.h
index cc5ff7f57..5c56e23fb 100644
--- a/ext/smoothstreaming/gstmssdemux.h
+++ b/ext/smoothstreaming/gstmssdemux.h
@@ -27,6 +27,7 @@
#include <gst/adaptivedemux/gstadaptivedemux.h>
#include <gst/base/gstadapter.h>
#include <gst/base/gstdataqueue.h>
+#include <gst/gstprotection.h>
#include "gstmssmanifest.h"
#include <gst/uridownloader/gsturidownloader.h>
diff --git a/ext/smoothstreaming/gstmssmanifest.c b/ext/smoothstreaming/gstmssmanifest.c
index 6559c2ec7..33dc76f0f 100644
--- a/ext/smoothstreaming/gstmssmanifest.c
+++ b/ext/smoothstreaming/gstmssmanifest.c
@@ -95,6 +95,9 @@ struct _GstMssManifest
gboolean is_live;
+ GString *protection_system_id;
+ gchar *protection_data;
+
GSList *streams;
};
@@ -267,6 +270,41 @@ _gst_mss_stream_init (GstMssStream * stream, xmlNodePtr node)
stream->regex_position = g_regex_new ("\\{start[ _]time\\}", 0, 0, NULL);
}
+
+static void
+_gst_mss_parse_protection (GstMssManifest * manifest,
+ xmlNodePtr protection_node)
+{
+ xmlNodePtr nodeiter;
+
+ for (nodeiter = protection_node->children; nodeiter;
+ nodeiter = nodeiter->next) {
+ if (nodeiter->type == XML_ELEMENT_NODE
+ && (strcmp ((const char *) nodeiter->name, "ProtectionHeader") == 0)) {
+ xmlChar *system_id_attribute =
+ xmlGetProp (nodeiter, (xmlChar *) "SystemID");
+ gchar *value = (gchar *) system_id_attribute;
+ int id_len = strlen (value);
+ GString *system_id;
+
+ if (value[0] == '{') {
+ value++;
+ id_len--;
+ }
+
+ system_id = g_string_new (value);
+ system_id = g_string_ascii_down (system_id);
+ if (value[id_len - 1] == '}')
+ system_id = g_string_truncate (system_id, id_len - 1);
+
+ manifest->protection_system_id = system_id;
+ manifest->protection_data = (gchar *) xmlNodeGetContent (nodeiter);
+ xmlFree (system_id_attribute);
+ break;
+ }
+ }
+}
+
GstMssManifest *
gst_mss_manifest_new (GstBuffer * data)
{
@@ -300,6 +338,11 @@ gst_mss_manifest_new (GstBuffer * data)
manifest->streams = g_slist_append (manifest->streams, stream);
_gst_mss_stream_init (stream, nodeiter);
}
+
+ if (nodeiter->type == XML_ELEMENT_NODE
+ && (strcmp ((const char *) nodeiter->name, "Protection") == 0)) {
+ _gst_mss_parse_protection (manifest, nodeiter);
+ }
}
gst_buffer_unmap (data, &mapinfo);
@@ -327,10 +370,28 @@ gst_mss_manifest_free (GstMssManifest * manifest)
g_slist_free_full (manifest->streams, (GDestroyNotify) gst_mss_stream_free);
+ if (manifest->protection_system_id != NULL)
+ g_string_free (manifest->protection_system_id, TRUE);
+ xmlFree (manifest->protection_data);
+
xmlFreeDoc (manifest->xml);
g_free (manifest);
}
+const gchar *
+gst_mss_manifest_get_protection_system_id (GstMssManifest * manifest)
+{
+ if (manifest->protection_system_id != NULL)
+ return manifest->protection_system_id->str;
+ return NULL;
+}
+
+const gchar *
+gst_mss_manifest_get_protection_data (GstMssManifest * manifest)
+{
+ return manifest->protection_data;
+}
+
GSList *
gst_mss_manifest_get_streams (GstMssManifest * manifest)
{
diff --git a/ext/smoothstreaming/gstmssmanifest.h b/ext/smoothstreaming/gstmssmanifest.h
index 364f6d12a..65330b40d 100644
--- a/ext/smoothstreaming/gstmssmanifest.h
+++ b/ext/smoothstreaming/gstmssmanifest.h
@@ -52,6 +52,8 @@ gint64 gst_mss_manifest_get_dvr_window_length (GstMssManifest * manifest);
gint gst_mss_manifest_get_look_ahead_fragments_count (GstMssManifest * manifest);
void gst_mss_manifest_reload_fragments (GstMssManifest * manifest, GstBuffer * data);
GstClockTime gst_mss_manifest_get_min_fragment_duration (GstMssManifest * manifest);
+const gchar * gst_mss_manifest_get_protection_system_id (GstMssManifest * manifest);
+const gchar * gst_mss_manifest_get_protection_data (GstMssManifest * manifest);
GstMssStreamType gst_mss_stream_get_type (GstMssStream *stream);
GstCaps * gst_mss_stream_get_caps (GstMssStream * stream);