[DASH] Include <mspr:pro> alongside to <cenc:pssh> for PlayReady (#749)
Configurable under flag --include_mspr_pro_for_playready. True by default. Closes #743.
This commit is contained in:
parent
069dbc82f7
commit
8e113af215
1
AUTHORS
1
AUTHORS
|
@ -17,6 +17,7 @@ Anders Hasselqvist <anders.hasselqvist@gmail.com>
|
||||||
Chun-da Chen <capitalm.c@gmail.com>
|
Chun-da Chen <capitalm.c@gmail.com>
|
||||||
Daniel Cantarín <canta@canta.com.ar>
|
Daniel Cantarín <canta@canta.com.ar>
|
||||||
Google Inc. <*@google.com>
|
Google Inc. <*@google.com>
|
||||||
|
Ivi.ru LLC <*@ivi.ru>
|
||||||
Leandro Moreira <leandro.ribeiro.moreira@gmail.com>
|
Leandro Moreira <leandro.ribeiro.moreira@gmail.com>
|
||||||
Leo Law <leoltlaw.gh@gmail.com>
|
Leo Law <leoltlaw.gh@gmail.com>
|
||||||
More Screens Ltd. <*@morescreens.net>
|
More Screens Ltd. <*@morescreens.net>
|
||||||
|
|
|
@ -40,3 +40,4 @@ Rintaro Kuroiwa <rkuroiwa@google.com>
|
||||||
Sanil Raut <sr1990003@gmail.com>
|
Sanil Raut <sr1990003@gmail.com>
|
||||||
Sergio Ammirata <sergio@ammirata.net>
|
Sergio Ammirata <sergio@ammirata.net>
|
||||||
Thomas Inskip <tinskip@google.com>
|
Thomas Inskip <tinskip@google.com>
|
||||||
|
Tim Lansen <tim.lansen@gmail.com>
|
||||||
|
|
|
@ -64,3 +64,8 @@ DEFINE_bool(allow_codec_switching,
|
||||||
"If enabled, allow adaptive switching between different codecs, "
|
"If enabled, allow adaptive switching between different codecs, "
|
||||||
"if they have the same language, media type (audio, video etc) and "
|
"if they have the same language, media type (audio, video etc) and "
|
||||||
"container type.");
|
"container type.");
|
||||||
|
DEFINE_bool(include_mspr_pro_for_playready,
|
||||||
|
true,
|
||||||
|
"If enabled, PlayReady Object <mspr:pro> will be inserted into "
|
||||||
|
"<ContentProtection ...> element alongside with <cenc:pssh> "
|
||||||
|
"when using PlayReady protection system.");
|
||||||
|
|
|
@ -22,5 +22,6 @@ DECLARE_string(utc_timings);
|
||||||
DECLARE_bool(generate_dash_if_iop_compliant_mpd);
|
DECLARE_bool(generate_dash_if_iop_compliant_mpd);
|
||||||
DECLARE_bool(allow_approximate_segment_timeline);
|
DECLARE_bool(allow_approximate_segment_timeline);
|
||||||
DECLARE_bool(allow_codec_switching);
|
DECLARE_bool(allow_codec_switching);
|
||||||
|
DECLARE_bool(include_mspr_pro_for_playready);
|
||||||
|
|
||||||
#endif // APP_MPD_FLAGS_H_
|
#endif // APP_MPD_FLAGS_H_
|
||||||
|
|
|
@ -461,6 +461,7 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
||||||
mpd_params.allow_approximate_segment_timeline =
|
mpd_params.allow_approximate_segment_timeline =
|
||||||
FLAGS_allow_approximate_segment_timeline;
|
FLAGS_allow_approximate_segment_timeline;
|
||||||
mpd_params.allow_codec_switching = FLAGS_allow_codec_switching;
|
mpd_params.allow_codec_switching = FLAGS_allow_codec_switching;
|
||||||
|
mpd_params.include_mspr_pro = FLAGS_include_mspr_pro_for_playready;
|
||||||
|
|
||||||
HlsParams& hls_params = packaging_params.hls_params;
|
HlsParams& hls_params = packaging_params.hls_params;
|
||||||
if (!GetHlsPlaylistType(FLAGS_hls_playlist_type, &hls_params.playlist_type)) {
|
if (!GetHlsPlaylistType(FLAGS_hls_playlist_type, &hls_params.playlist_type)) {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
||||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" xmlns:mas="urn:marlin:mas:1-0:services:schemas:mpd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.7360665798187256S">
|
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" xmlns:mas="urn:marlin:mas:1-0:services:schemas:mpd" xmlns:mspr="urn:microsoft:playready" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.7360665798187256S">
|
||||||
<Period id="0">
|
<Period id="0">
|
||||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||||
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
|
<ContentProtection value="MSPR 2.0" schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
|
||||||
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBOAEQATQB5AE0AVABZADEATwBEAGMANQBNAEQARQB5AE0AegBRADEATgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AGwANQBMAG8AVQBnAEsAOQBLAEMAZwA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
|
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBOAEQATQB5AE0AVABZADEATwBEAGMANQBNAEQARQB5AE0AegBRADEATgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AGwANQBMAG8AVQBnAEsAOQBLAEMAZwA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
|
||||||
|
<mspr:pro>BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATgBEAE0AeQBNAFQAWQAxAE8ARABjADUATQBEAEUAeQBNAHoAUQAxAE4AZwA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBsADUATABvAFUAZwBLADkASwBDAGcAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</mspr:pro>
|
||||||
</ContentProtection>
|
</ContentProtection>
|
||||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||||
<cenc:pssh>AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY=</cenc:pssh>
|
<cenc:pssh>AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY=</cenc:pssh>
|
||||||
|
@ -24,8 +25,9 @@
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
|
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
|
||||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||||
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
|
<ContentProtection value="MSPR 2.0" schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95">
|
||||||
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBOAEQATQB5AE0AVABZADEATwBEAGMANQBNAEQARQB5AE0AegBRADEATgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AGwANQBMAG8AVQBnAEsAOQBLAEMAZwA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
|
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBOAEQATQB5AE0AVABZADEATwBEAGMANQBNAEQARQB5AE0AegBRADEATgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AGwANQBMAG8AVQBnAEsAOQBLAEMAZwA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
|
||||||
|
<mspr:pro>BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATgBEAE0AeQBNAFQAWQAxAE8ARABjADUATQBEAEUAeQBNAHoAUQAxAE4AZwA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBsADUATABvAFUAZwBLADkASwBDAGcAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</mspr:pro>
|
||||||
</ContentProtection>
|
</ContentProtection>
|
||||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||||
<cenc:pssh>AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY=</cenc:pssh>
|
<cenc:pssh>AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY=</cenc:pssh>
|
||||||
|
|
|
@ -79,6 +79,7 @@ void MpdNotifyMuxerListener::OnMediaStart(
|
||||||
if (is_encrypted_) {
|
if (is_encrypted_) {
|
||||||
internal::SetContentProtectionFields(protection_scheme_, default_key_id_,
|
internal::SetContentProtectionFields(protection_scheme_, default_key_id_,
|
||||||
key_system_info_, media_info.get());
|
key_system_info_, media_info.get());
|
||||||
|
media_info->mutable_protected_content()->set_include_mspr_pro(mpd_notifier_->include_mspr_pro());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The content may be splitted into multiple files, but their MediaInfo
|
// The content may be splitted into multiple files, but their MediaInfo
|
||||||
|
|
|
@ -168,6 +168,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodEncryptedContent) {
|
||||||
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
|
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" default_key_id: 'defaultkeyid'\n"
|
" default_key_id: 'defaultkeyid'\n"
|
||||||
|
" include_mspr_pro: 1\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
EXPECT_CALL(*notifier_, NotifyNewContainer(_, _)).Times(0);
|
EXPECT_CALL(*notifier_, NotifyNewContainer(_, _)).Times(0);
|
||||||
|
@ -371,6 +372,7 @@ TEST_P(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
|
||||||
" pssh: \"" + std::string(kExpectedDefaultPsshBox) + "\"\n"
|
" pssh: \"" + std::string(kExpectedDefaultPsshBox) + "\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" protection_scheme: 'cbcs'\n"
|
" protection_scheme: 'cbcs'\n"
|
||||||
|
" include_mspr_pro: 1\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
const uint64_t kStartTime1 = 0u;
|
const uint64_t kStartTime1 = 0u;
|
||||||
|
@ -443,6 +445,7 @@ TEST_P(MpdNotifyMuxerListenerTest, LiveWithKeyRotation) {
|
||||||
"protected_content {\n"
|
"protected_content {\n"
|
||||||
" default_key_id: \"defaultkeyid\"\n"
|
" default_key_id: \"defaultkeyid\"\n"
|
||||||
" protection_scheme: 'cbc1'\n"
|
" protection_scheme: 'cbc1'\n"
|
||||||
|
" include_mspr_pro: 1\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
const uint64_t kStartTime1 = 0u;
|
const uint64_t kStartTime1 = 0u;
|
||||||
|
|
|
@ -95,6 +95,7 @@ message MediaInfo {
|
||||||
// Specifies the protection scheme: 'cenc', 'cens', 'cbc1', 'cbcs'.
|
// Specifies the protection scheme: 'cenc', 'cens', 'cbc1', 'cbcs'.
|
||||||
// "cbca" is also valid which is a place holder for SAMPLE-AES encryption.
|
// "cbca" is also valid which is a place holder for SAMPLE-AES encryption.
|
||||||
optional string protection_scheme = 3 [default = 'cenc'];
|
optional string protection_scheme = 3 [default = 'cenc'];
|
||||||
|
optional bool include_mspr_pro = 4 [default = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rkuroiwa): Remove this. <ContentProtection> element that must be added
|
// TODO(rkuroiwa): Remove this. <ContentProtection> element that must be added
|
||||||
|
|
|
@ -49,11 +49,13 @@ void AddMpdNameSpaceInfo(XmlNode* mpd) {
|
||||||
static const char kMarlinNamespace[] =
|
static const char kMarlinNamespace[] =
|
||||||
"urn:marlin:mas:1-0:services:schemas:mpd";
|
"urn:marlin:mas:1-0:services:schemas:mpd";
|
||||||
static const char kXmlNamespaceXlink[] = "http://www.w3.org/1999/xlink";
|
static const char kXmlNamespaceXlink[] = "http://www.w3.org/1999/xlink";
|
||||||
|
static const char kMsprNamespace[] = "urn:microsoft:playready";
|
||||||
|
|
||||||
const std::map<std::string, std::string> uris = {
|
const std::map<std::string, std::string> uris = {
|
||||||
{"cenc", kCencNamespace},
|
{"cenc", kCencNamespace},
|
||||||
{"mas", kMarlinNamespace},
|
{"mas", kMarlinNamespace},
|
||||||
{"xlink", kXmlNamespaceXlink},
|
{"xlink", kXmlNamespaceXlink},
|
||||||
|
{"mspr", kMsprNamespace},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const std::string& namespace_name : namespaces) {
|
for (const std::string& namespace_name : namespaces) {
|
||||||
|
|
|
@ -104,6 +104,9 @@ class MpdNotifier {
|
||||||
/// forces a flush.
|
/// forces a flush.
|
||||||
virtual bool Flush() = 0;
|
virtual bool Flush() = 0;
|
||||||
|
|
||||||
|
/// @return include_mspr_pro option flag
|
||||||
|
bool include_mspr_pro() const { return mpd_options_.mpd_params.include_mspr_pro; }
|
||||||
|
|
||||||
/// @return The dash profile for this object.
|
/// @return The dash profile for this object.
|
||||||
DashProfile dash_profile() const { return mpd_options_.dash_profile; }
|
DashProfile dash_profile() const { return mpd_options_.dash_profile; }
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "packager/base/strings/string_util.h"
|
#include "packager/base/strings/string_util.h"
|
||||||
#include "packager/media/base/language_utils.h"
|
#include "packager/media/base/language_utils.h"
|
||||||
|
#include "packager/media/base/protection_system_specific_info.h"
|
||||||
#include "packager/mpd/base/adaptation_set.h"
|
#include "packager/mpd/base/adaptation_set.h"
|
||||||
#include "packager/mpd/base/content_protection_element.h"
|
#include "packager/mpd/base/content_protection_element.h"
|
||||||
#include "packager/mpd/base/representation.h"
|
#include "packager/mpd/base/representation.h"
|
||||||
|
@ -324,6 +325,11 @@ const char kMarlinUUID[] = "5e629af5-38da-4063-8977-97ffbd9902d4";
|
||||||
// Unofficial FairPlay system id extracted from
|
// Unofficial FairPlay system id extracted from
|
||||||
// https://forums.developer.apple.com/thread/6185.
|
// https://forums.developer.apple.com/thread/6185.
|
||||||
const char kFairPlayUUID[] = "29701fe4-3cc7-4a34-8c5b-ae90c7439a47";
|
const char kFairPlayUUID[] = "29701fe4-3cc7-4a34-8c5b-ae90c7439a47";
|
||||||
|
// String representation of media::kPlayReadySystemId.
|
||||||
|
const char kPlayReadyUUID[] = "9a04f079-9840-4286-ab92-e65be0885f95";
|
||||||
|
// It is RECOMMENDED to include the @value attribute with name and version "MSPR 2.0".
|
||||||
|
// See https://docs.microsoft.com/en-us/playready/specifications/mpeg-dash-playready#221-general.
|
||||||
|
const char kContentProtectionValueMSPR20[] = "MSPR 2.0";
|
||||||
|
|
||||||
Element GenerateMarlinContentIds(const std::string& key_id) {
|
Element GenerateMarlinContentIds(const std::string& key_id) {
|
||||||
// See https://github.com/google/shaka-packager/issues/381 for details.
|
// See https://github.com/google/shaka-packager/issues/381 for details.
|
||||||
|
@ -354,6 +360,29 @@ Element GenerateCencPsshElement(const std::string& pssh) {
|
||||||
return cenc_pssh;
|
return cenc_pssh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract MS PlayReady Object from given PSSH
|
||||||
|
// and encode it in base64.
|
||||||
|
Element GenerateMsprProElement(const std::string& pssh) {
|
||||||
|
std::unique_ptr<media::PsshBoxBuilder> b =
|
||||||
|
media::PsshBoxBuilder::ParseFromBox(
|
||||||
|
reinterpret_cast<const uint8_t*>(pssh.data()),
|
||||||
|
pssh.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
const std::vector<uint8_t> *p_pssh = &b->pssh_data();
|
||||||
|
std::string base64_encoded_mspr;
|
||||||
|
base::Base64Encode(
|
||||||
|
base::StringPiece(
|
||||||
|
reinterpret_cast<const char*>(p_pssh->data()),
|
||||||
|
p_pssh->size()),
|
||||||
|
&base64_encoded_mspr
|
||||||
|
);
|
||||||
|
Element mspr_pro;
|
||||||
|
mspr_pro.name = kMsproElementName;
|
||||||
|
mspr_pro.content = base64_encoded_mspr;
|
||||||
|
return mspr_pro;
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function. This works because Representation and AdaptationSet both
|
// Helper function. This works because Representation and AdaptationSet both
|
||||||
// have AddContentProtectionElement().
|
// have AddContentProtectionElement().
|
||||||
template <typename ContentProtectionParent>
|
template <typename ContentProtectionParent>
|
||||||
|
@ -419,6 +448,11 @@ void AddContentProtectionElementsHelperTemplated(
|
||||||
if (!entry.pssh().empty()) {
|
if (!entry.pssh().empty()) {
|
||||||
drm_content_protection.subelements.push_back(
|
drm_content_protection.subelements.push_back(
|
||||||
GenerateCencPsshElement(entry.pssh()));
|
GenerateCencPsshElement(entry.pssh()));
|
||||||
|
if(entry.uuid() == kPlayReadyUUID && protected_content.include_mspr_pro()) {
|
||||||
|
drm_content_protection.subelements.push_back(
|
||||||
|
GenerateMsprProElement(entry.pssh()));
|
||||||
|
drm_content_protection.value = kContentProtectionValueMSPR20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ struct SegmentInfo;
|
||||||
|
|
||||||
const char kEncryptedMp4Scheme[] = "urn:mpeg:dash:mp4protection:2011";
|
const char kEncryptedMp4Scheme[] = "urn:mpeg:dash:mp4protection:2011";
|
||||||
const char kPsshElementName[] = "cenc:pssh";
|
const char kPsshElementName[] = "cenc:pssh";
|
||||||
|
const char kMsproElementName[] = "mspr:pro";
|
||||||
|
|
||||||
bool HasVODOnlyFields(const MediaInfo& media_info);
|
bool HasVODOnlyFields(const MediaInfo& media_info);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "packager/mpd/base/adaptation_set.h"
|
#include "packager/mpd/base/adaptation_set.h"
|
||||||
#include "packager/mpd/base/mpd_options.h"
|
#include "packager/mpd/base/mpd_options.h"
|
||||||
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
||||||
|
@ -116,4 +117,113 @@ TEST_F(MpdUtilsTest, ContentProtectionMarlin) {
|
||||||
EXPECT_THAT(adaptation_set_.GetXml().get(), XmlNodeEqual(kExpectedOutput));
|
EXPECT_THAT(adaptation_set_.GetXml().get(), XmlNodeEqual(kExpectedOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MpdUtilsTest, ContentProtectionPlayReadyCencMspr) {
|
||||||
|
const std::string pssh_str("0000003870737368010000009A04F079"
|
||||||
|
"98404286AB92E65BE0885F9500000001"
|
||||||
|
"11223344556677889900AABBCCDDEEFF"
|
||||||
|
"0000000430313233");
|
||||||
|
std::vector<uint8_t> pssh;
|
||||||
|
base::HexStringToBytes(pssh_str, &pssh);
|
||||||
|
|
||||||
|
const char kMediaInfoWithContentProtection[] =
|
||||||
|
"video_info {"
|
||||||
|
" codec: 'avc1'"
|
||||||
|
" width: 1920"
|
||||||
|
" height: 1080"
|
||||||
|
" time_scale: 3000"
|
||||||
|
" frame_duration: 100"
|
||||||
|
"}"
|
||||||
|
"protected_content {"
|
||||||
|
" protection_scheme: 'cenc'"
|
||||||
|
" default_key_id: '0123456789\x3A\x3B\x3C\x3D\x3E\x3F'"
|
||||||
|
" include_mspr_pro: 1"
|
||||||
|
"}"
|
||||||
|
"container_type: 1";
|
||||||
|
|
||||||
|
MediaInfo media_info =
|
||||||
|
ConvertToMediaInfo(kMediaInfoWithContentProtection);
|
||||||
|
|
||||||
|
MediaInfo::ProtectedContent * protected_content =
|
||||||
|
media_info.mutable_protected_content();
|
||||||
|
MediaInfo::ProtectedContent::ContentProtectionEntry* entry =
|
||||||
|
protected_content->add_content_protection_entry();
|
||||||
|
entry->set_uuid("9a04f079-9840-4286-ab92-e65be0885f95");
|
||||||
|
entry->set_pssh(pssh.data(), pssh.size());
|
||||||
|
|
||||||
|
AddContentProtectionElements(media_info, &adaptation_set_);
|
||||||
|
ASSERT_TRUE(adaptation_set_.AddRepresentation(media_info));
|
||||||
|
|
||||||
|
const char kExpectedOutput[] =
|
||||||
|
"<AdaptationSet contentType='video' width='1920'"
|
||||||
|
" height='1080' frameRate='3000/100'>"
|
||||||
|
" <ContentProtection value='cenc'"
|
||||||
|
" schemeIdUri='urn:mpeg:dash:mp4protection:2011'"
|
||||||
|
" cenc:default_KID='30313233-3435-3637-3839-3a3b3c3d3e3f'/>"
|
||||||
|
" <ContentProtection value='MSPR 2.0'"
|
||||||
|
" schemeIdUri='urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95'>"
|
||||||
|
" <cenc:pssh>"
|
||||||
|
"AAAAOHBzc2gBAAAAmgTweZhAQoarkuZb4IhflQAAAAERIjNEVWZ3iJkAqrvM3e7/AAAABDAxMjM="
|
||||||
|
" </cenc:pssh>"
|
||||||
|
" <mspr:pro>MDEyMw==</mspr:pro>"
|
||||||
|
" </ContentProtection>"
|
||||||
|
" <Representation id='0' bandwidth='0' codecs='avc1' mimeType='video/mp4'/>"
|
||||||
|
"</AdaptationSet>";
|
||||||
|
|
||||||
|
EXPECT_THAT(adaptation_set_.GetXml().get(), XmlNodeEqual(kExpectedOutput));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MpdUtilsTest, ContentProtectionPlayReadyCenc) {
|
||||||
|
const std::string pssh_str("0000003870737368010000009A04F079"
|
||||||
|
"98404286AB92E65BE0885F9500000001"
|
||||||
|
"11223344556677889900AABBCCDDEEFF"
|
||||||
|
"0000000430313233");
|
||||||
|
std::vector<uint8_t> pssh;
|
||||||
|
base::HexStringToBytes(pssh_str, &pssh);
|
||||||
|
|
||||||
|
const char kMediaInfoWithContentProtection[] =
|
||||||
|
"video_info {"
|
||||||
|
" codec: 'avc1'"
|
||||||
|
" width: 1920"
|
||||||
|
" height: 1080"
|
||||||
|
" time_scale: 3000"
|
||||||
|
" frame_duration: 100"
|
||||||
|
"}"
|
||||||
|
"protected_content {"
|
||||||
|
" protection_scheme: 'cenc'"
|
||||||
|
" default_key_id: '0123456789\x3A\x3B\x3C\x3D\x3E\x3F'"
|
||||||
|
" include_mspr_pro: 0"
|
||||||
|
"}"
|
||||||
|
"container_type: 1";
|
||||||
|
|
||||||
|
MediaInfo media_info =
|
||||||
|
ConvertToMediaInfo(kMediaInfoWithContentProtection);
|
||||||
|
|
||||||
|
MediaInfo::ProtectedContent * protected_content =
|
||||||
|
media_info.mutable_protected_content();
|
||||||
|
MediaInfo::ProtectedContent::ContentProtectionEntry* entry =
|
||||||
|
protected_content->add_content_protection_entry();
|
||||||
|
entry->set_uuid("9a04f079-9840-4286-ab92-e65be0885f95");
|
||||||
|
entry->set_pssh(pssh.data(), pssh.size());
|
||||||
|
|
||||||
|
AddContentProtectionElements(media_info, &adaptation_set_);
|
||||||
|
ASSERT_TRUE(adaptation_set_.AddRepresentation(media_info));
|
||||||
|
|
||||||
|
const char kExpectedOutput[] =
|
||||||
|
"<AdaptationSet contentType='video' width='1920'"
|
||||||
|
" height='1080' frameRate='3000/100'>"
|
||||||
|
" <ContentProtection value='cenc'"
|
||||||
|
" schemeIdUri='urn:mpeg:dash:mp4protection:2011'"
|
||||||
|
" cenc:default_KID='30313233-3435-3637-3839-3a3b3c3d3e3f'/>"
|
||||||
|
" <ContentProtection"
|
||||||
|
" schemeIdUri='urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95'>"
|
||||||
|
" <cenc:pssh>"
|
||||||
|
"AAAAOHBzc2gBAAAAmgTweZhAQoarkuZb4IhflQAAAAERIjNEVWZ3iJkAqrvM3e7/AAAABDAxMjM="
|
||||||
|
" </cenc:pssh>"
|
||||||
|
" </ContentProtection>"
|
||||||
|
" <Representation id='0' bandwidth='0' codecs='avc1' mimeType='video/mp4'/>"
|
||||||
|
"</AdaptationSet>";
|
||||||
|
|
||||||
|
EXPECT_THAT(adaptation_set_.GetXml().get(), XmlNodeEqual(kExpectedOutput));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -83,6 +83,10 @@ struct MpdParams {
|
||||||
/// If enabled, allow switching between different codecs, if they have the
|
/// If enabled, allow switching between different codecs, if they have the
|
||||||
/// same language, media type (audio, video etc) and container type.
|
/// same language, media type (audio, video etc) and container type.
|
||||||
bool allow_codec_switching = false;
|
bool allow_codec_switching = false;
|
||||||
|
/// If enabled, PlayReady Object <mspr:pro> will be inserted into
|
||||||
|
/// <ContentProtection ...> element alongside with <cenc:pssh>
|
||||||
|
/// when using PlayReady protection system.
|
||||||
|
bool include_mspr_pro = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
Loading…
Reference in New Issue