diff --git a/README.md b/README.md
index 5b8dd06d7e..59de1f72ca 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 bbd383518e..580442d050 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 2a1c193998..e76f6ce67f 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 0176f0eb80..0d2d4ef16d 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 755aa41087..ecb9bd9d0f 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 51e3dbb3e5..fecd395acf 100755
--- a/packager/app/test/packager_test.py
+++ b/packager/app/test/packager_test.py
@@ -398,7 +398,7 @@ class PackagerAppTest(unittest.TestCase):
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 @@ class PackagerAppTest(unittest.TestCase):
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 @@ class PackagerFunctionalTest(PackagerAppTest):
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 @@ class PackagerFunctionalTest(PackagerAppTest):
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 13dbbdda48..0000000000
--- 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 22fcb0a3ac..1c199b8264 100644
Binary files a/packager/app/test/testdata/encryption-with-fairplay/bear-640x360-audio.mp4 and b/packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-audio.mp4 differ
diff --git a/packager/app/test/testdata/encryption-with-fairplay/bear-640x360-video.mp4 b/packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-video.mp4
similarity index 99%
rename from packager/app/test/testdata/encryption-with-fairplay/bear-640x360-video.mp4
rename to packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-video.mp4
index 81691dafee..fd44066ee9 100644
Binary files a/packager/app/test/testdata/encryption-with-fairplay/bear-640x360-video.mp4 and b/packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-video.mp4 differ
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 0000000000..4f9bab2413
--- /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 41bfea4b0a..62ca40212a 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 8ef9329090..c9e346a3c8 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 474aa32036..8972394c63 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 ba4b8689f3..7948e7eceb 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 f333e71949..6df39458c2 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 91e0d9b1da..6e3b31b0e8 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 c2ec7f69d6..926533d55a 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 ed0d308959..f00d85cc83 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 39dfb50e2d..51df13fcc9 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 "