From 8d11e5ea6494dd70513b38d7c1d5bb1b42a56e8c Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Mon, 17 Sep 2018 17:27:02 -0700 Subject: [PATCH] Support Marlin DRM signaling in DASH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only Marlin Adaptive Streaming Specification – Simple Profile is supported. Two additional updates: - Remove FairPlay ContentProtection element from DASH mpd as FairPlay does not define a signaling in DASH. - Updated end to end test to include all DRMs we support. Closes #381. Change-Id: Id12269b471ea34983b782cbd92f687332292ef59 --- README.md | 1 + .../options/general_encryption_options.rst | 3 +- packager/app/packager_main.cc | 1 + packager/app/packager_util.cc | 5 +- packager/app/protection_system_flags.cc | 3 +- packager/app/test/packager_test.py | 27 +++++---- .../encryption-with-fairplay/output.mpd | 27 --------- .../bear-640x360-audio.mp4 | Bin 44588 -> 45214 bytes .../bear-640x360-video.mp4 | Bin 302863 -> 303489 bytes .../output.m3u8 | 0 .../encryption-with-multi-drms/output.mpd | 47 +++++++++++++++ .../stream_0.m3u8 | 5 +- .../stream_1.m3u8 | 5 +- packager/media/base/key_source.cc | 7 +++ packager/media/base/protection_system_ids.h | 7 +++ .../base/protection_system_specific_info.h | 1 + packager/media/public/crypto_params.h | 1 + packager/mpd/base/mpd_builder.cc | 3 + packager/mpd/base/mpd_utils.cc | 56 +++++++++++++++--- packager/mpd/base/xml/xml_node.cc | 7 ++- 20 files changed, 149 insertions(+), 57 deletions(-) delete mode 100644 packager/app/test/testdata/encryption-with-fairplay/output.mpd rename packager/app/test/testdata/{encryption-with-fairplay => encryption-with-multi-drms}/bear-640x360-audio.mp4 (97%) rename packager/app/test/testdata/{encryption-with-fairplay => encryption-with-multi-drms}/bear-640x360-video.mp4 (99%) rename packager/app/test/testdata/{encryption-with-fairplay => encryption-with-multi-drms}/output.m3u8 (100%) create mode 100644 packager/app/test/testdata/encryption-with-multi-drms/output.mpd rename packager/app/test/testdata/{encryption-with-fairplay => encryption-with-multi-drms}/stream_0.m3u8 (59%) rename packager/app/test/testdata/{encryption-with-fairplay => encryption-with-multi-drms}/stream_1.m3u8 (59%) diff --git a/README.md b/README.md index 5b8dd06d7e7..59de1f72cae 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Shaka Packager supports: - [Widevine](http://www.widevine.com/) - [PlayReady](https://www.microsoft.com/playready/)¹ - [FairPlay](https://developer.apple.com/streaming/fps/)¹ + - [Marlin](https://www.intertrust.com/marlin-drm/)¹ - Encryption standards: - [CENC](https://en.wikipedia.org/wiki/MPEG_Common_Encryption) - [SAMPLE-AES](https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption/Intro/Intro.html) diff --git a/docs/source/options/general_encryption_options.rst b/docs/source/options/general_encryption_options.rst index bbd383518ee..580442d050b 100644 --- a/docs/source/options/general_encryption_options.rst +++ b/docs/source/options/general_encryption_options.rst @@ -17,4 +17,5 @@ General encryption options --protection_systems Protection systems to be generated. Supported protection systems include - Widevine, PlayReady, FairPlay, and CommonSystem (https://goo.gl/s8RIhr). + Widevine, PlayReady, FairPlay, Marlin, and + CommonSystem (https://goo.gl/s8RIhr). diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 2a1c193998c..e76f6ce67f5 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -266,6 +266,7 @@ bool ParseProtectionSystems( {"common", EncryptionParams::ProtectionSystem::kCommonSystem}, {"commonsystem", EncryptionParams::ProtectionSystem::kCommonSystem}, {"fairplay", EncryptionParams::ProtectionSystem::kFairPlay}, + {"marlin", EncryptionParams::ProtectionSystem::kMarlin}, {"playready", EncryptionParams::ProtectionSystem::kPlayReady}, {"widevine", EncryptionParams::ProtectionSystem::kWidevine}, }; diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index 0176f0eb804..0d2d4ef16dd 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -16,8 +16,6 @@ #include "packager/media/base/raw_key_source.h" #include "packager/media/base/request_signer.h" #include "packager/media/base/widevine_key_source.h" -#include "packager/media/chunking/chunking_handler.h" -#include "packager/media/crypto/encryption_handler.h" #include "packager/mpd/base/mpd_options.h" #include "packager/status.h" @@ -55,6 +53,9 @@ int GetProtectionSystemsFlag( case EncryptionParams::ProtectionSystem::kFairPlay: protection_systems_flags |= FAIRPLAY_PROTECTION_SYSTEM_FLAG; break; + case EncryptionParams::ProtectionSystem::kMarlin: + protection_systems_flags |= MARLIN_PROTECTION_SYSTEM_FLAG; + break; case EncryptionParams::ProtectionSystem::kPlayReady: protection_systems_flags |= PLAYREADY_PROTECTION_SYSTEM_FLAG; break; diff --git a/packager/app/protection_system_flags.cc b/packager/app/protection_system_flags.cc index 755aa410870..ecb9bd9d0fa 100644 --- a/packager/app/protection_system_flags.cc +++ b/packager/app/protection_system_flags.cc @@ -12,4 +12,5 @@ DEFINE_string( protection_systems, "", "Protection systems to be generated. Supported protection systems include " - "Widevine, PlayReady, FairPlay, and CommonSystem (https://goo.gl/s8RIhr)."); + "Widevine, PlayReady, FairPlay, Marlin and " + "CommonSystem (https://goo.gl/s8RIhr)."); diff --git a/packager/app/test/packager_test.py b/packager/app/test/packager_test.py index 51e3dbb3e52..fecd395acfc 100755 --- a/packager/app/test/packager_test.py +++ b/packager/app/test/packager_test.py @@ -398,7 +398,7 @@ def _GetStreams(self, streams, test_files=None, **kwargs): def _GetFlags(self, strip_parameter_set_nalus=True, encryption=False, - fairplay=False, + protection_systems=None, protection_scheme=None, vp9_subsample_encryption=True, decryption=False, @@ -443,12 +443,13 @@ def _GetFlags(self, if not random_iv: flags.append('--iv=' + self.encryption_iv) - if fairplay: - fairplay_key_uri = ('skd://www.license.com/' - 'getkey?KeyId=31323334-3536-3738-3930-313233343536') - flags += [ - '--protection_systems=FairPlay', '--hls_key_uri=' + fairplay_key_uri - ] + if protection_systems: + flags += ['--protection_systems=' + protection_systems] + if 'FairPlay' in protection_systems: + fairplay_key_uri = ('skd://www.license.com/getkey?' + 'KeyId=31323334-3536-3738-3930-313233343536') + flags += ['--hls_key_uri=' + fairplay_key_uri] + if protection_scheme: flags += ['--protection_scheme', protection_scheme] if not vp9_subsample_encryption: @@ -862,12 +863,15 @@ def testEncryption(self): self._GetFlags(encryption=True, output_dash=True)) self._CheckTestResults('encryption', verify_decryption=True) - def testEncryptionWithFairplay(self): + def testEncryptionWithMultiDrms(self): self.assertPackageSuccess( self._GetStreams(['audio', 'video']), self._GetFlags( - encryption=True, fairplay=True, output_dash=True, output_hls=True)) - self._CheckTestResults('encryption-with-fairplay') + encryption=True, + protection_systems='Widevine,PlayReady,FairPlay,Marlin', + output_dash=True, + output_hls=True)) + self._CheckTestResults('encryption-with-multi-drms') # Test deprecated flag --enable_fixed_key_encryption, which is still # supported currently. @@ -1096,7 +1100,8 @@ def testAvcTsWithEncryptionAndFairPlay(self): segmented=True, hls=True, test_files=['bear-640x360.ts']), - self._GetFlags(encryption=True, output_hls=True, fairplay=True)) + self._GetFlags( + encryption=True, protection_systems='FairPlay', output_hls=True)) self._CheckTestResults('avc-ts-with-encryption-and-fairplay') def testAvcAc3TsWithEncryption(self): diff --git a/packager/app/test/testdata/encryption-with-fairplay/output.mpd b/packager/app/test/testdata/encryption-with-fairplay/output.mpd deleted file mode 100644 index 13dbbdda489..00000000000 --- a/packager/app/test/testdata/encryption-with-fairplay/output.mpd +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - bear-640x360-video.mp4 - - - - - - - - - - - bear-640x360-audio.mp4 - - - - - - - diff --git a/packager/app/test/testdata/encryption-with-fairplay/bear-640x360-audio.mp4 b/packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-audio.mp4 similarity index 97% rename from packager/app/test/testdata/encryption-with-fairplay/bear-640x360-audio.mp4 rename to packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-audio.mp4 index 22fcb0a3ac3870d488d08ccd3275f6b06fc8247f..1c199b82646b09a2dfa38fbe0d7cf4dee2594727 100644 GIT binary patch delta 674 zcmZuvJxhX76n=aQA!vw(XbH-t&DZabFv+yC@+&n$8bZv<$lmZR$(DDEphXHH3R;@_ zSfYQ>)YMj!LlLw|{eXs^s}`YgxaXedIp;q2+>e{8bp9%p4c+>#yrL8VY~+i_WnJHG zV5dWqMz&OSO-J^$^Rsj^Hokv-^uG9Vuv8(XGh3`SyTj>nn;H=y>Gcv5v@e|p3y33( zASU2LfIf~v>>`g1Y(m8-3|PZ9Z3`oiX(}>gvaComHX^SfN2&mYP{9gIjl>EIWC{v# z85WpmPDUnJ>0^{nqr_~M^D?7gGs;rQz!r+c1uEvKv{`S%MqShIFu)5B^?lHibOOXE z7e$h1@Y7Etf=ObLnI)G(h(1DWhJ&2k!g{C@!W7p9SmR@DqOKFK*Z$3kwSV@~+BR!Q zL?{&I$->O1xM`F)13R&}X2I`aj(h~GJl|-urN&whw-!(0XOjucv)0QSv$H{kXqBv+ z!(U&iiGJG41uL%S=XT_OUfRnK0+;wbBB*^FUY4F`9xon-t4{+%HB$Y(J+1#I_*Si) R>6r_tx#eBXclRCZSKs{heI5V+ delta 34 qcmbRDkZH{wrU^cJ#jDn3QMI|#^*d^YkVuniDS{ozOwfqe;RCuWGgT6#3z&z#Vu*5U?>8BCF zB(ccMl8YfkA0ZybC^@Bt^-v{*DXt5!#>d*lnohJ<+nf_?oA%P%HmgfSC=}+&!pz6G z=^Swac4BeOg5Sde`3TZHpSRIceXWOEizo53$we%)R^^S^*;DP9zm_kI%muVevcP#? Sl@C?fz#(yT+^VwtRQUl+oqKNp delta 36 pcmZoXEY!bGXo4CO3;#w9UY6$NZ0*b07=f4xh?%!9XJffF3jo}E3>g3b diff --git a/packager/app/test/testdata/encryption-with-fairplay/output.m3u8 b/packager/app/test/testdata/encryption-with-multi-drms/output.m3u8 similarity index 100% rename from packager/app/test/testdata/encryption-with-fairplay/output.m3u8 rename to packager/app/test/testdata/encryption-with-multi-drms/output.m3u8 diff --git a/packager/app/test/testdata/encryption-with-multi-drms/output.mpd b/packager/app/test/testdata/encryption-with-multi-drms/output.mpd new file mode 100644 index 00000000000..4f9bab24133 --- /dev/null +++ b/packager/app/test/testdata/encryption-with-multi-drms/output.mpd @@ -0,0 +1,47 @@ + + + + + + + + AAACOnBzc2gBAAAAmgTweZhAQoarkuZb4IhflQAAAAExMjM0NTY3ODkwMTIzNDU2AAACBgYCAAABAAEA/AE8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AE4ARABNAHkATQBUAFkAMQBPAEQAYwA1AE0ARABFAHkATQB6AFEAMQBOAGcAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AbAA1AEwAbwBVAGcASwA5AEsAQwBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A + + + AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY= + + + + urn:marlin:kid:31323334353637383930313233343536 + + + + bear-640x360-video.mp4 + + + + + + + + + AAACOnBzc2gBAAAAmgTweZhAQoarkuZb4IhflQAAAAExMjM0NTY3ODkwMTIzNDU2AAACBgYCAAABAAEA/AE8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AE4ARABNAHkATQBUAFkAMQBPAEQAYwA1AE0ARABFAHkATQB6AFEAMQBOAGcAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AbAA1AEwAbwBVAGcASwA5AEsAQwBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A + + + AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY= + + + + urn:marlin:kid:31323334353637383930313233343536 + + + + + bear-640x360-audio.mp4 + + + + + + + diff --git a/packager/app/test/testdata/encryption-with-fairplay/stream_0.m3u8 b/packager/app/test/testdata/encryption-with-multi-drms/stream_0.m3u8 similarity index 59% rename from packager/app/test/testdata/encryption-with-fairplay/stream_0.m3u8 rename to packager/app/test/testdata/encryption-with-multi-drms/stream_0.m3u8 index 41bfea4b0a4..62ca40212ac 100644 --- a/packager/app/test/testdata/encryption-with-fairplay/stream_0.m3u8 +++ b/packager/app/test/testdata/encryption-with-multi-drms/stream_0.m3u8 @@ -3,10 +3,11 @@ ## Generated with https://github.com/google/shaka-packager version -- #EXT-X-TARGETDURATION:2 #EXT-X-PLAYLIST-TYPE:VOD -#EXT-X-MAP:URI="bear-640x360-audio.mp4",BYTERANGE="951@0" +#EXT-X-MAP:URI="bear-640x360-audio.mp4",BYTERANGE="1577@0" +#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,URI="data:text/plain;base64,AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY=",KEYID=0x31323334353637383930313233343536,KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" #EXT-X-KEY:METHOD=SAMPLE-AES-CTR,URI="skd://www.license.com/getkey?KeyId=31323334-3536-3738-3930-313233343536",KEYFORMATVERSIONS="1",KEYFORMAT="com.apple.streamingkeydelivery" #EXTINF:1.022, -#EXT-X-BYTERANGE:17028@1019 +#EXT-X-BYTERANGE:17028@1645 bear-640x360-audio.mp4 #EXTINF:0.998, #EXT-X-BYTERANGE:16682 diff --git a/packager/app/test/testdata/encryption-with-fairplay/stream_1.m3u8 b/packager/app/test/testdata/encryption-with-multi-drms/stream_1.m3u8 similarity index 59% rename from packager/app/test/testdata/encryption-with-fairplay/stream_1.m3u8 rename to packager/app/test/testdata/encryption-with-multi-drms/stream_1.m3u8 index 8ef93290903..c9e346a3c8e 100644 --- a/packager/app/test/testdata/encryption-with-fairplay/stream_1.m3u8 +++ b/packager/app/test/testdata/encryption-with-multi-drms/stream_1.m3u8 @@ -3,10 +3,11 @@ ## Generated with https://github.com/google/shaka-packager version -- #EXT-X-TARGETDURATION:2 #EXT-X-PLAYLIST-TYPE:VOD -#EXT-X-MAP:URI="bear-640x360-video.mp4",BYTERANGE="1075@0" +#EXT-X-MAP:URI="bear-640x360-video.mp4",BYTERANGE="1701@0" +#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,URI="data:text/plain;base64,AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY=",KEYID=0x31323334353637383930313233343536,KEYFORMATVERSIONS="1",KEYFORMAT="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" #EXT-X-KEY:METHOD=SAMPLE-AES-CTR,URI="skd://www.license.com/getkey?KeyId=31323334-3536-3738-3930-313233343536",KEYFORMATVERSIONS="1",KEYFORMAT="com.apple.streamingkeydelivery" #EXTINF:1.001, -#EXT-X-BYTERANGE:99313@1143 +#EXT-X-BYTERANGE:99313@1769 bear-640x360-video.mp4 #EXTINF:1.001, #EXT-X-BYTERANGE:122340 diff --git a/packager/media/base/key_source.cc b/packager/media/base/key_source.cc index 474aa320362..8972394c637 100644 --- a/packager/media/base/key_source.cc +++ b/packager/media/base/key_source.cc @@ -33,6 +33,13 @@ KeySource::KeySource(int protection_systems_flags, FourCC protection_scheme) { no_pssh_systems_.emplace_back(std::begin(kFairPlaySystemId), std::end(kFairPlaySystemId)); } + // We only support Marlin Adaptive Streaming Specification – Simple Profile + // with Implicit Content ID Mapping, which does not need a PSSH. Marlin + // specific PSSH with Explicit Content ID Mapping is not generated. + if (protection_systems_flags & MARLIN_PROTECTION_SYSTEM_FLAG) { + no_pssh_systems_.emplace_back(std::begin(kMarlinSystemId), + std::end(kMarlinSystemId)); + } } KeySource::~KeySource() = default; diff --git a/packager/media/base/protection_system_ids.h b/packager/media/base/protection_system_ids.h index ba4b8689f3f..7948e7ecebc 100644 --- a/packager/media/base/protection_system_ids.h +++ b/packager/media/base/protection_system_ids.h @@ -10,6 +10,8 @@ namespace shaka { namespace media { +// System Ids are defined in https://dashif.org/identifiers/content_protection/. + // Common SystemID defined by EME, which requires Key System implementations // supporting ISO Common Encryption to support this SystemID and format. // https://goo.gl/kUv2Xd @@ -23,6 +25,11 @@ const uint8_t kFairPlaySystemId[] = {0x29, 0x70, 0x1F, 0xE4, 0x3C, 0xC7, 0x4A, 0x34, 0x8C, 0x5B, 0xAE, 0x90, 0xC7, 0x43, 0x9A, 0x47}; +// Marlin Adaptive Streaming Specification – Simple Profile, V1.0. +const uint8_t kMarlinSystemId[] = {0x5E, 0x62, 0x9A, 0xF5, 0x38, 0xDA, + 0x40, 0x63, 0x89, 0x77, 0x97, 0xFF, + 0xBD, 0x99, 0x02, 0xD4}; + const uint8_t kPlayReadySystemId[] = {0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95}; diff --git a/packager/media/base/protection_system_specific_info.h b/packager/media/base/protection_system_specific_info.h index f333e719497..6df39458c2b 100644 --- a/packager/media/base/protection_system_specific_info.h +++ b/packager/media/base/protection_system_specific_info.h @@ -18,6 +18,7 @@ #define PLAYREADY_PROTECTION_SYSTEM_FLAG 0x02 #define WIDEVINE_PROTECTION_SYSTEM_FLAG 0x04 #define FAIRPLAY_PROTECTION_SYSTEM_FLAG 0x08 +#define MARLIN_PROTECTION_SYSTEM_FLAG 0x10 namespace shaka { namespace media { diff --git a/packager/media/public/crypto_params.h b/packager/media/public/crypto_params.h index 91e0d9b1da6..6e3b31b0e82 100644 --- a/packager/media/public/crypto_params.h +++ b/packager/media/public/crypto_params.h @@ -119,6 +119,7 @@ struct EncryptionParams { enum class ProtectionSystem { kCommonSystem, kFairPlay, + kMarlin, kPlayReady, kWidevine, }; diff --git a/packager/mpd/base/mpd_builder.cc b/packager/mpd/base/mpd_builder.cc index c2ec7f69d61..926533d55a8 100644 --- a/packager/mpd/base/mpd_builder.cc +++ b/packager/mpd/base/mpd_builder.cc @@ -46,10 +46,13 @@ void AddMpdNameSpaceInfo(XmlNode* mpd) { mpd->SetStringAttribute("xsi:schemaLocation", kDashSchemaMpd2011); static const char kCencNamespace[] = "urn:mpeg:cenc:2013"; + static const char kMarlinNamespace[] = + "urn:marlin:mas:1-0:services:schemas:mpd"; static const char kXmlNamespaceXlink[] = "http://www.w3.org/1999/xlink"; const std::map uris = { {"cenc", kCencNamespace}, + {"mas", kMarlinNamespace}, {"xlink", kXmlNamespaceXlink}, }; diff --git a/packager/mpd/base/mpd_utils.cc b/packager/mpd/base/mpd_utils.cc index ed0d308959a..f00d85cc837 100644 --- a/packager/mpd/base/mpd_utils.cc +++ b/packager/mpd/base/mpd_utils.cc @@ -302,6 +302,42 @@ void UpdateContentProtectionPsshHelper( } namespace { + +// UUID for Marlin Adaptive Streaming Specification – Simple Profile from +// https://dashif.org/identifiers/content_protection/. +const char kMarlinUUID[] = "5e629af5-38da-4063-8977-97ffbd9902d4"; +// Unofficial FairPlay system id extracted from +// https://forums.developer.apple.com/thread/6185. +const char kFairPlayUUID[] = "29701fe4-3cc7-4a34-8c5b-ae90c7439a47"; + +Element GenerateMarlinContentIds(const std::string& key_id) { + // See https://github.com/google/shaka-packager/issues/381 for details. + static const char kMarlinContentIdName[] = "mas:MarlinContentId"; + static const char kMarlinContentIdPrefix[] = "urn:marlin:kid:"; + static const char kMarlinContentIdsName[] = "mas:MarlinContentIds"; + + Element marlin_content_id; + marlin_content_id.name = kMarlinContentIdName; + marlin_content_id.content = + kMarlinContentIdPrefix + base::HexEncode(key_id.data(), key_id.size()); + + Element marlin_content_ids; + marlin_content_ids.name = kMarlinContentIdsName; + marlin_content_ids.subelements.push_back(marlin_content_id); + + return marlin_content_ids; +} + +Element GenerateCencPsshElement(const std::string& pssh) { + std::string base64_encoded_pssh; + base::Base64Encode(base::StringPiece(pssh.data(), pssh.size()), + &base64_encoded_pssh); + Element cenc_pssh; + cenc_pssh.name = kPsshElementName; + cenc_pssh.content = base64_encoded_pssh; + return cenc_pssh; +} + // Helper function. This works because Representation and AdaptationSet both // have AddContentProtectionElement(). template @@ -349,18 +385,20 @@ void AddContentProtectionElementsHelperTemplated( ContentProtectionElement drm_content_protection; drm_content_protection.scheme_id_uri = "urn:uuid:" + entry.uuid(); + if (entry.has_name_version()) drm_content_protection.value = entry.name_version(); - if (!entry.pssh().empty()) { - std::string base64_encoded_pssh; - base::Base64Encode( - base::StringPiece(entry.pssh().data(), entry.pssh().size()), - &base64_encoded_pssh); - Element cenc_pssh; - cenc_pssh.name = kPsshElementName; - cenc_pssh.content = base64_encoded_pssh; - drm_content_protection.subelements.push_back(cenc_pssh); + if (entry.uuid() == kFairPlayUUID) { + VLOG(1) << "Skipping FairPlay ContentProtection element as FairPlay does " + "not support DASH signaling."; + continue; + } else if (entry.uuid() == kMarlinUUID) { + drm_content_protection.subelements.push_back( + GenerateMarlinContentIds(protected_content.default_key_id())); + } else if (!entry.pssh().empty()) { + drm_content_protection.subelements.push_back( + GenerateCencPsshElement(entry.pssh())); } if (!key_id_uuid_format.empty() && !is_mp4_container) { diff --git a/packager/mpd/base/xml/xml_node.cc b/packager/mpd/base/xml/xml_node.cc index 39dfb50e2de..51df13fcc96 100644 --- a/packager/mpd/base/xml/xml_node.cc +++ b/packager/mpd/base/xml/xml_node.cc @@ -141,12 +141,15 @@ bool XmlNode::AddElements(const std::vector& elements) { child_node.SetStringAttribute(attribute_it->first.c_str(), attribute_it->second); } + + // Note that somehow |SetContent| needs to be called before |AddElements| + // otherwise the added children will be overwritten by the content. + child_node.SetContent(child_element.content); + // Recursively set children for the child. if (!child_node.AddElements(child_element.subelements)) return false; - child_node.SetContent(child_element.content); - if (!xmlAddChild(node_.get(), child_node.GetRawPtr())) { LOG(ERROR) << "Failed to set child " << child_element.name << " to parent element "