diff options
Diffstat (limited to 'ext/smoothstreaming')
-rw-r--r-- | ext/smoothstreaming/gstmssdemux.c | 76 | ||||
-rw-r--r-- | ext/smoothstreaming/gstmssdemux.h | 1 | ||||
-rw-r--r-- | ext/smoothstreaming/gstmssmanifest.c | 61 | ||||
-rw-r--r-- | ext/smoothstreaming/gstmssmanifest.h | 2 |
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); |