diff --git a/packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-audio.mp4 b/packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-audio.mp4 index 1c199b8264..68521c6fb4 100644 Binary files a/packager/app/test/testdata/encryption-with-multi-drms/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-multi-drms/bear-640x360-video.mp4 b/packager/app/test/testdata/encryption-with-multi-drms/bear-640x360-video.mp4 index fd44066ee9..7b643856d7 100644 Binary files a/packager/app/test/testdata/encryption-with-multi-drms/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-multi-drms/output.mpd b/packager/app/test/testdata/encryption-with-multi-drms/output.mpd index 3815d7834f..954d789ba9 100644 --- a/packager/app/test/testdata/encryption-with-multi-drms/output.mpd +++ b/packager/app/test/testdata/encryption-with-multi-drms/output.mpd @@ -5,7 +5,7 @@ - AAACOnBzc2gBAAAAmgTweZhAQoarkuZb4IhflQAAAAExMjM0NTY3ODkwMTIzNDU2AAACBgYCAAABAAEA/AE8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AE4ARABNAHkATQBUAFkAMQBPAEQAYwA1AE0ARABFAHkATQB6AFEAMQBOAGcAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AbAA1AEwAbwBVAGcASwA5AEsAQwBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBOAEQATQB5AE0AVABZADEATwBEAGMANQBNAEQARQB5AE0AegBRADEATgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AGwANQBMAG8AVQBnAEsAOQBLAEMAZwA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY= @@ -17,15 +17,15 @@ bear-640x360-video.mp4 - - + + - AAACOnBzc2gBAAAAmgTweZhAQoarkuZb4IhflQAAAAExMjM0NTY3ODkwMTIzNDU2AAACBgYCAAABAAEA/AE8AFcAUgBNAEgARQBBAEQARQBSACAAeABtAGwAbgBzAD0AIgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8ARABSAE0ALwAyADAAMAA3AC8AMAAzAC8AUABsAGEAeQBSAGUAYQBkAHkASABlAGEAZABlAHIAIgAgAHYAZQByAHMAaQBvAG4APQAiADQALgAwAC4AMAAuADAAIgA+ADwARABBAFQAQQA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEUAWQBMAEUATgA+ADEANgA8AC8ASwBFAFkATABFAE4APgA8AEEATABHAEkARAA+AEEARQBTAEMAVABSADwALwBBAEwARwBJAEQAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARAA+AE4ARABNAHkATQBUAFkAMQBPAEQAYwA1AE0ARABFAHkATQB6AFEAMQBOAGcAPQA9ADwALwBLAEkARAA+ADwAQwBIAEUAQwBLAFMAVQBNAD4AbAA1AEwAbwBVAGcASwA5AEsAQwBnAD0APAAvAEMASABFAEMASwBTAFUATQA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBOAEQATQB5AE0AVABZADEATwBEAGMANQBNAEQARQB5AE0AegBRADEATgBnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AGwANQBMAG8AVQBnAEsAOQBLAEMAZwA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== AAAAOHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABgSEDEyMzQ1Njc4OTAxMjM0NTZI49yVmwY= @@ -38,8 +38,8 @@ bear-640x360-audio.mp4 - - + + diff --git a/packager/app/test/testdata/encryption-with-multi-drms/stream_0.m3u8 b/packager/app/test/testdata/encryption-with-multi-drms/stream_0.m3u8 index 62ca40212a..af241c654d 100644 --- a/packager/app/test/testdata/encryption-with-multi-drms/stream_0.m3u8 +++ b/packager/app/test/testdata/encryption-with-multi-drms/stream_0.m3u8 @@ -3,11 +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="1577@0" +#EXT-X-MAP:URI="bear-640x360-audio.mp4",BYTERANGE="1557@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@1645 +#EXT-X-BYTERANGE:17028@1625 bear-640x360-audio.mp4 #EXTINF:0.998, #EXT-X-BYTERANGE:16682 diff --git a/packager/app/test/testdata/encryption-with-multi-drms/stream_1.m3u8 b/packager/app/test/testdata/encryption-with-multi-drms/stream_1.m3u8 index c9e346a3c8..7a42c87ef0 100644 --- a/packager/app/test/testdata/encryption-with-multi-drms/stream_1.m3u8 +++ b/packager/app/test/testdata/encryption-with-multi-drms/stream_1.m3u8 @@ -3,11 +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="1701@0" +#EXT-X-MAP:URI="bear-640x360-video.mp4",BYTERANGE="1681@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@1769 +#EXT-X-BYTERANGE:99313@1749 bear-640x360-video.mp4 #EXTINF:1.001, #EXT-X-BYTERANGE:122340 diff --git a/packager/app/test/testdata/live-profile-and-encryption-and-mult-files/output.mpd b/packager/app/test/testdata/live-profile-and-encryption-and-mult-files/output.mpd index a37f0e0204..5a82778bb8 100644 --- a/packager/app/test/testdata/live-profile-and-encryption-and-mult-files/output.mpd +++ b/packager/app/test/testdata/live-profile-and-encryption-and-mult-files/output.mpd @@ -7,15 +7,7 @@ AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA== - - - - - - - - - + @@ -23,7 +15,7 @@ - + @@ -31,23 +23,21 @@ + + + + + + + + AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA== - - - - - - - - - - - + @@ -57,7 +47,7 @@ - + @@ -67,6 +57,16 @@ + + + + + + + + + + diff --git a/packager/media/base/key_source.cc b/packager/media/base/key_source.cc index 8972394c63..6679f91088 100644 --- a/packager/media/base/key_source.cc +++ b/packager/media/base/key_source.cc @@ -22,7 +22,8 @@ KeySource::KeySource(int protection_systems_flags, FourCC protection_scheme) { } if (protection_systems_flags & PLAYREADY_PROTECTION_SYSTEM_FLAG) { - pssh_generators_.emplace_back(new PlayReadyPsshGenerator()); + pssh_generators_.emplace_back( + new PlayReadyPsshGenerator(protection_scheme)); } if (protection_systems_flags & WIDEVINE_PROTECTION_SYSTEM_FLAG) { diff --git a/packager/media/base/playready_pssh_generator.cc b/packager/media/base/playready_pssh_generator.cc index 0c1b168564..59928d36f3 100644 --- a/packager/media/base/playready_pssh_generator.cc +++ b/packager/media/base/playready_pssh_generator.cc @@ -23,20 +23,25 @@ namespace shaka { namespace media { namespace { -const uint8_t kPlayReadyPsshBoxVersion = 1; -const std::string kPlayHeaderObject_4_1 = - "" - "" - ""; +const uint8_t kPlayReadyPsshBoxVersion = 0; + +// For PlayReady clients 1.0+ that support CTR keys. const std::string kPlayHeaderObject_4_0 = "16" - "AESCTR$0$1" + "version=\"4.0.0.0\">" + "16AESCTR" + "$0$1" ""; +// For PlayReady clients 4.0+ that support CBC keys. +const std::string kPlayHeaderObject_4_3 = + "" + "" + ""; + // Converts the key_id's endianness. std::vector ConvertGuidEndianness(const std::vector& input) { std::vector output = input; @@ -55,11 +60,11 @@ std::vector ConvertGuidEndianness(const std::vector& input) { } // Generates the data section of a PlayReady PSSH. -// PlayReady PSSH Data is a PlayReady Header Object. -// Format is outlined in the following document. -// http://download.microsoft.com/download/2/3/8/238F67D9-1B8B-48D3-AB83-9C00112268B2/PlayReady%20Header%20Object%202015-08-13-FINAL-CL.PDF +// PlayReady PSSH Data is a PlayReady Header Object, which is described at +// https://docs.microsoft.com/en-us/playready/specifications/playready-header-specification Status GeneratePlayReadyPsshData(const std::vector& key_id, const std::vector& key, + const FourCC protection_scheme, std::vector* output) { CHECK(output); std::vector key_id_converted = ConvertGuidEndianness(key_id); @@ -77,11 +82,30 @@ Status GeneratePlayReadyPsshData(const std::vector& key_id, base::Base64Encode( std::string(key_id_converted.begin(), key_id_converted.end()), &base64_key_id); - std::string playready_header = kPlayHeaderObject_4_0; - base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$0", - base64_key_id); - base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$1", - base64_checksum); + + std::string playready_header; + + switch (protection_scheme) { + case FOURCC_cbc1: + case FOURCC_cbcs: + playready_header = kPlayHeaderObject_4_3; + base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$0", + base64_key_id); + break; + + case FOURCC_cenc: + case FOURCC_cens: + playready_header = kPlayHeaderObject_4_0; + base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$0", + base64_key_id); + base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$1", + base64_checksum); + break; + + default: + return Status(error::INVALID_ARGUMENT, + "The provided protection scheme is not supported."); + } // Create a PlayReady Record. // Outline in section '2.PlayReady Records' of @@ -126,10 +150,11 @@ Status GeneratePlayReadyPsshData(const std::vector& key_id, } } // namespace -PlayReadyPsshGenerator::PlayReadyPsshGenerator() +PlayReadyPsshGenerator::PlayReadyPsshGenerator(FourCC protection_scheme) : PsshGenerator(std::vector(std::begin(kPlayReadySystemId), std::end(kPlayReadySystemId)), - kPlayReadyPsshBoxVersion) {} + kPlayReadyPsshBoxVersion), + protection_scheme_(protection_scheme) {} PlayReadyPsshGenerator::~PlayReadyPsshGenerator() {} @@ -142,7 +167,8 @@ PlayReadyPsshGenerator::GeneratePsshDataFromKeyIdAndKey( const std::vector& key_id, const std::vector& key) const { std::vector pssh_data; - Status status = GeneratePlayReadyPsshData(key_id, key, &pssh_data); + Status status = + GeneratePlayReadyPsshData(key_id, key, protection_scheme_, &pssh_data); if (!status.ok()) { LOG(ERROR) << status.ToString(); return base::nullopt; diff --git a/packager/media/base/playready_pssh_generator.h b/packager/media/base/playready_pssh_generator.h index 485568e214..dc5cd7a42c 100644 --- a/packager/media/base/playready_pssh_generator.h +++ b/packager/media/base/playready_pssh_generator.h @@ -7,6 +7,7 @@ #ifndef MEDIA_BASE_PLAYREADY_PSSH_GENERATOR_H_ #define MEDIA_BASE_PLAYREADY_PSSH_GENERATOR_H_ +#include "packager/media/base/fourccs.h" #include "packager/media/base/pssh_generator.h" namespace shaka { @@ -14,7 +15,7 @@ namespace media { class PlayReadyPsshGenerator : public PsshGenerator { public: - PlayReadyPsshGenerator(); + explicit PlayReadyPsshGenerator(FourCC protection_scheme); ~PlayReadyPsshGenerator() override; /// @name PsshGenerator implemetation overrides. @@ -34,6 +35,8 @@ class PlayReadyPsshGenerator : public PsshGenerator { base::Optional> GeneratePsshDataFromKeyIdAndKey( const std::vector& key_id, const std::vector& key) const override; + + FourCC protection_scheme_ = FOURCC_NULL; }; } // namespace media diff --git a/packager/media/base/pssh_generator_unittest.cc b/packager/media/base/pssh_generator_unittest.cc index 5a82050bd8..ecfa30ccc0 100644 --- a/packager/media/base/pssh_generator_unittest.cc +++ b/packager/media/base/pssh_generator_unittest.cc @@ -25,71 +25,126 @@ const uint8_t kTestKey1[] = {'c', 'o', 'n', 't', 'e', 'n', 't', 'k', const uint8_t kTestKeyId2[] = {'k', 'e', 'y', 'i', 'd', '2', '~', '~', '~', '~', '~', '~', '~', '~', '~', '~'}; -const char kExpectedPlayReadyPssh[] = { - '\x0', '\x0', '\x2', '\x3A', 'p', 's', 's', 'h', '\x1', +const char kExpectedPlayReadyPsshWithCtrKey[] = { + '\x0', '\x0', '\x2', '\x26', 'p', 's', 's', 'h', '\x0', '\x0', '\x0', '\x0', '\x9A', '\x04', '\xf0', '\x79', '\x98', '\x40', '\x42', '\x86', '\xab', '\x92', '\xe6', '\x5b', '\xe0', '\x88', '\x5f', - '\x95', '\x0', '\x0', '\x0', '\x1', 'k', 'e', 'y', 'i', - 'd', '1', '~', '~', '~', '~', '~', '~', '~', - '~', '~', '~', '\x0', '\x0', '\x2', '\x6', '\x6', '\x2', - '\x0', '\x0', '\x1', '\x0', '\x1', '\x0', '\xfc', '\x1', '<', - '\x0', 'W', '\x0', 'R', '\x0', 'M', '\x0', 'H', '\x0', - 'E', '\x0', 'A', '\x0', 'D', '\x0', 'E', '\x0', 'R', - '\x0', ' ', '\x0', 'x', '\x0', 'm', '\x0', 'l', '\x0', - 'n', '\x0', 's', '\x0', '=', '\x0', '"', '\x0', 'h', - '\x0', 't', '\x0', 't', '\x0', 'p', '\x0', ':', '\x0', - '/', '\x0', '/', '\x0', 's', '\x0', 'c', '\x0', 'h', - '\x0', 'e', '\x0', 'm', '\x0', 'a', '\x0', 's', '\x0', - '.', '\x0', 'm', '\x0', 'i', '\x0', 'c', '\x0', 'r', - '\x0', 'o', '\x0', 's', '\x0', 'o', '\x0', 'f', '\x0', - 't', '\x0', '.', '\x0', 'c', '\x0', 'o', '\x0', 'm', - '\x0', '/', '\x0', 'D', '\x0', 'R', '\x0', 'M', '\x0', - '/', '\x0', '2', '\x0', '0', '\x0', '0', '\x0', '7', - '\x0', '/', '\x0', '0', '\x0', '3', '\x0', '/', '\x0', - 'P', '\x0', 'l', '\x0', 'a', '\x0', 'y', '\x0', 'R', - '\x0', 'e', '\x0', 'a', '\x0', 'd', '\x0', 'y', '\x0', - 'H', '\x0', 'e', '\x0', 'a', '\x0', 'd', '\x0', 'e', - '\x0', 'r', '\x0', '"', '\x0', ' ', '\x0', 'v', '\x0', - 'e', '\x0', 'r', '\x0', 's', '\x0', 'i', '\x0', 'o', - '\x0', 'n', '\x0', '=', '\x0', '"', '\x0', '4', '\x0', - '.', '\x0', '0', '\x0', '.', '\x0', '0', '\x0', '.', - '\x0', '0', '\x0', '"', '\x0', '>', '\x0', '<', '\x0', - 'D', '\x0', 'A', '\x0', 'T', '\x0', 'A', '\x0', '>', - '\x0', '<', '\x0', 'P', '\x0', 'R', '\x0', 'O', '\x0', - 'T', '\x0', 'E', '\x0', 'C', '\x0', 'T', '\x0', 'I', - '\x0', 'N', '\x0', 'F', '\x0', 'O', '\x0', '>', '\x0', - '<', '\x0', 'K', '\x0', 'E', '\x0', 'Y', '\x0', 'L', - '\x0', 'E', '\x0', 'N', '\x0', '>', '\x0', '1', '\x0', - '6', '\x0', '<', '\x0', '/', '\x0', 'K', '\x0', 'E', - '\x0', 'Y', '\x0', 'L', '\x0', 'E', '\x0', 'N', '\x0', - '>', '\x0', '<', '\x0', 'A', '\x0', 'L', '\x0', 'G', - '\x0', 'I', '\x0', 'D', '\x0', '>', '\x0', 'A', '\x0', - 'E', '\x0', 'S', '\x0', 'C', '\x0', 'T', '\x0', 'R', - '\x0', '<', '\x0', '/', '\x0', 'A', '\x0', 'L', '\x0', - 'G', '\x0', 'I', '\x0', 'D', '\x0', '>', '\x0', '<', - '\x0', '/', '\x0', 'P', '\x0', 'R', '\x0', 'O', '\x0', - 'T', '\x0', 'E', '\x0', 'C', '\x0', 'T', '\x0', 'I', - '\x0', 'N', '\x0', 'F', '\x0', 'O', '\x0', '>', '\x0', - '<', '\x0', 'K', '\x0', 'I', '\x0', 'D', '\x0', '>', + '\x95', '\x0', '\x0', '\x2', '\x6', '\x6', '\x2', '\x0', '\x0', + '\x1', '\x0', '\x1', '\x0', '\xfc', '\x1', '<', '\x0', 'W', + '\x0', 'R', '\x0', 'M', '\x0', 'H', '\x0', 'E', '\x0', + 'A', '\x0', 'D', '\x0', 'E', '\x0', 'R', '\x0', ' ', + '\x0', 'x', '\x0', 'm', '\x0', 'l', '\x0', 'n', '\x0', + 's', '\x0', '=', '\x0', '"', '\x0', 'h', '\x0', 't', + '\x0', 't', '\x0', 'p', '\x0', ':', '\x0', '/', '\x0', + '/', '\x0', 's', '\x0', 'c', '\x0', 'h', '\x0', 'e', + '\x0', 'm', '\x0', 'a', '\x0', 's', '\x0', '.', '\x0', + 'm', '\x0', 'i', '\x0', 'c', '\x0', 'r', '\x0', 'o', + '\x0', 's', '\x0', 'o', '\x0', 'f', '\x0', 't', '\x0', + '.', '\x0', 'c', '\x0', 'o', '\x0', 'm', '\x0', '/', + '\x0', 'D', '\x0', 'R', '\x0', 'M', '\x0', '/', '\x0', + '2', '\x0', '0', '\x0', '0', '\x0', '7', '\x0', '/', + '\x0', '0', '\x0', '3', '\x0', '/', '\x0', 'P', '\x0', + 'l', '\x0', 'a', '\x0', 'y', '\x0', 'R', '\x0', 'e', + '\x0', 'a', '\x0', 'd', '\x0', 'y', '\x0', 'H', '\x0', + 'e', '\x0', 'a', '\x0', 'd', '\x0', 'e', '\x0', 'r', + '\x0', '"', '\x0', ' ', '\x0', 'v', '\x0', 'e', '\x0', + 'r', '\x0', 's', '\x0', 'i', '\x0', 'o', '\x0', 'n', + '\x0', '=', '\x0', '"', '\x0', '4', '\x0', '.', '\x0', + '0', '\x0', '.', '\x0', '0', '\x0', '.', '\x0', '0', + '\x0', '"', '\x0', '>', '\x0', '<', '\x0', 'D', '\x0', + 'A', '\x0', 'T', '\x0', 'A', '\x0', '>', '\x0', '<', + '\x0', 'P', '\x0', 'R', '\x0', 'O', '\x0', 'T', '\x0', + 'E', '\x0', 'C', '\x0', 'T', '\x0', 'I', '\x0', 'N', + '\x0', 'F', '\x0', 'O', '\x0', '>', '\x0', '<', '\x0', + 'K', '\x0', 'E', '\x0', 'Y', '\x0', 'L', '\x0', 'E', + '\x0', 'N', '\x0', '>', '\x0', '1', '\x0', '6', '\x0', + '<', '\x0', '/', '\x0', 'K', '\x0', 'E', '\x0', 'Y', + '\x0', 'L', '\x0', 'E', '\x0', 'N', '\x0', '>', '\x0', + '<', '\x0', 'A', '\x0', 'L', '\x0', 'G', '\x0', 'I', + '\x0', 'D', '\x0', '>', '\x0', 'A', '\x0', 'E', '\x0', + 'S', '\x0', 'C', '\x0', 'T', '\x0', 'R', '\x0', '<', + '\x0', '/', '\x0', 'A', '\x0', 'L', '\x0', 'G', '\x0', + 'I', '\x0', 'D', '\x0', '>', '\x0', '<', '\x0', '/', + '\x0', 'P', '\x0', 'R', '\x0', 'O', '\x0', 'T', '\x0', + 'E', '\x0', 'C', '\x0', 'T', '\x0', 'I', '\x0', 'N', + '\x0', 'F', '\x0', 'O', '\x0', '>', '\x0', '<', '\x0', + 'K', '\x0', 'I', '\x0', 'D', '\x0', '>', '\x0', 'a', + '\x0', 'X', '\x0', 'l', '\x0', 'l', '\x0', 'a', '\x0', + 'z', '\x0', 'F', '\x0', 'k', '\x0', 'f', '\x0', 'n', + '\x0', '5', '\x0', '+', '\x0', 'f', '\x0', 'n', '\x0', + '5', '\x0', '+', '\x0', 'f', '\x0', 'n', '\x0', '5', + '\x0', '+', '\x0', 'f', '\x0', 'g', '\x0', '=', '\x0', + '=', '\x0', '<', '\x0', '/', '\x0', 'K', '\x0', 'I', + '\x0', 'D', '\x0', '>', '\x0', '<', '\x0', 'C', '\x0', + 'H', '\x0', 'E', '\x0', 'C', '\x0', 'K', '\x0', 'S', + '\x0', 'U', '\x0', 'M', '\x0', '>', '\x0', 'u', '\x0', + 'F', '\x0', 'Y', '\x0', '/', '\x0', 'O', '\x0', 'i', + '\x0', 'r', '\x0', 'Q', '\x0', 'j', '\x0', '/', '\x0', + 'U', '\x0', '=', '\x0', '<', '\x0', '/', '\x0', 'C', + '\x0', 'H', '\x0', 'E', '\x0', 'C', '\x0', 'K', '\x0', + 'S', '\x0', 'U', '\x0', 'M', '\x0', '>', '\x0', '<', + '\x0', '/', '\x0', 'D', '\x0', 'A', '\x0', 'T', '\x0', + 'A', '\x0', '>', '\x0', '<', '\x0', '/', '\x0', 'W', + '\x0', 'R', '\x0', 'M', '\x0', 'H', '\x0', 'E', '\x0', + 'A', '\x0', 'D', '\x0', 'E', '\x0', 'R', '\x0', '>', + '\x0', +}; + +const char kExpectedPlayReadyPsshWithCbcKey[] = { + '\x0', '\x0', '\x1', '\xde', 'p', 's', 's', 'h', '\x0', + '\x0', '\x0', '\x0', '\x9A', '\x04', '\xf0', '\x79', '\x98', '\x40', + '\x42', '\x86', '\xab', '\x92', '\xe6', '\x5b', '\xe0', '\x88', '\x5f', + '\x95', '\x0', '\x0', '\x1', '\xbe', '\xbe', '\x1', '\x0', '\x0', + '\x1', '\x0', '\x1', '\x0', '\xb4', '\x1', '<', '\x0', 'W', + '\x0', 'R', '\x0', 'M', '\x0', 'H', '\x0', 'E', '\x0', + 'A', '\x0', 'D', '\x0', 'E', '\x0', 'R', '\x0', ' ', + '\x0', 'x', '\x0', 'm', '\x0', 'l', '\x0', 'n', '\x0', + 's', '\x0', '=', '\x0', '"', '\x0', 'h', '\x0', 't', + '\x0', 't', '\x0', 'p', '\x0', ':', '\x0', '/', '\x0', + '/', '\x0', 's', '\x0', 'c', '\x0', 'h', '\x0', 'e', + '\x0', 'm', '\x0', 'a', '\x0', 's', '\x0', '.', '\x0', + 'm', '\x0', 'i', '\x0', 'c', '\x0', 'r', '\x0', 'o', + '\x0', 's', '\x0', 'o', '\x0', 'f', '\x0', 't', '\x0', + '.', '\x0', 'c', '\x0', 'o', '\x0', 'm', '\x0', '/', + '\x0', 'D', '\x0', 'R', '\x0', 'M', '\x0', '/', '\x0', + '2', '\x0', '0', '\x0', '0', '\x0', '7', '\x0', '/', + '\x0', '0', '\x0', '3', '\x0', '/', '\x0', 'P', '\x0', + 'l', '\x0', 'a', '\x0', 'y', '\x0', 'R', '\x0', 'e', + '\x0', 'a', '\x0', 'd', '\x0', 'y', '\x0', 'H', '\x0', + 'e', '\x0', 'a', '\x0', 'd', '\x0', 'e', '\x0', 'r', + '\x0', '"', '\x0', ' ', '\x0', 'v', '\x0', 'e', '\x0', + 'r', '\x0', 's', '\x0', 'i', '\x0', 'o', '\x0', 'n', + '\x0', '=', '\x0', '"', '\x0', '4', '\x0', '.', '\x0', + '3', '\x0', '.', '\x0', '0', '\x0', '.', '\x0', '0', + '\x0', '"', '\x0', '>', '\x0', '<', '\x0', 'D', '\x0', + 'A', '\x0', 'T', '\x0', 'A', '\x0', '>', '\x0', '<', + '\x0', 'P', '\x0', 'R', '\x0', 'O', '\x0', 'T', '\x0', + 'E', '\x0', 'C', '\x0', 'T', '\x0', 'I', '\x0', 'N', + '\x0', 'F', '\x0', 'O', '\x0', '>', '\x0', '<', '\x0', + 'K', '\x0', 'I', '\x0', 'D', '\x0', 'S', '\x0', '>', + '\x0', '<', '\x0', 'K', '\x0', 'I', '\x0', 'D', '\x0', + ' ', '\x0', 'A', '\x0', 'L', '\x0', 'G', '\x0', 'I', + '\x0', 'D', '\x0', '=', '\x0', '"', '\x0', 'A', '\x0', + 'E', '\x0', 'S', '\x0', 'C', '\x0', 'B', '\x0', 'C', + '\x0', '"', '\x0', ' ', '\x0', 'V', '\x0', 'A', '\x0', + 'L', '\x0', 'U', '\x0', 'E', '\x0', '=', '\x0', '"', '\x0', 'a', '\x0', 'X', '\x0', 'l', '\x0', 'l', '\x0', 'a', '\x0', 'z', '\x0', 'F', '\x0', 'k', '\x0', 'f', '\x0', 'n', '\x0', '5', '\x0', '+', '\x0', 'f', '\x0', 'n', '\x0', '5', '\x0', '+', '\x0', 'f', '\x0', 'n', '\x0', '5', '\x0', '+', '\x0', 'f', '\x0', 'g', '\x0', - '=', '\x0', '=', '\x0', '<', '\x0', '/', '\x0', 'K', - '\x0', 'I', '\x0', 'D', '\x0', '>', '\x0', '<', '\x0', - 'C', '\x0', 'H', '\x0', 'E', '\x0', 'C', '\x0', 'K', - '\x0', 'S', '\x0', 'U', '\x0', 'M', '\x0', '>', '\x0', - 'u', '\x0', 'F', '\x0', 'Y', '\x0', '/', '\x0', 'O', - '\x0', 'i', '\x0', 'r', '\x0', 'Q', '\x0', 'j', '\x0', - '/', '\x0', 'U', '\x0', '=', '\x0', '<', '\x0', '/', - '\x0', 'C', '\x0', 'H', '\x0', 'E', '\x0', 'C', '\x0', - 'K', '\x0', 'S', '\x0', 'U', '\x0', 'M', '\x0', '>', - '\x0', '<', '\x0', '/', '\x0', 'D', '\x0', 'A', '\x0', - 'T', '\x0', 'A', '\x0', '>', '\x0', '<', '\x0', '/', - '\x0', 'W', '\x0', 'R', '\x0', 'M', '\x0', 'H', '\x0', - 'E', '\x0', 'A', '\x0', 'D', '\x0', 'E', '\x0', 'R', - '\x0', '>', '\x0', + '=', '\x0', '=', '\x0', '"', '\x0', '>', '\x0', '<', + '\x0', '/', '\x0', 'K', '\x0', 'I', '\x0', 'D', '\x0', + '>', '\x0', '<', '\x0', '/', '\x0', 'K', '\x0', 'I', + '\x0', 'D', '\x0', 'S', '\x0', '>', '\x0', '<', '\x0', + '/', '\x0', 'P', '\x0', 'R', '\x0', 'O', '\x0', 'T', + '\x0', 'E', '\x0', 'C', '\x0', 'T', '\x0', 'I', '\x0', + 'N', '\x0', 'F', '\x0', 'O', '\x0', '>', '\x0', '<', + '\x0', '/', '\x0', 'D', '\x0', 'A', '\x0', 'T', '\x0', + 'A', '\x0', '>', '\x0', '<', '\x0', '/', '\x0', 'W', + '\x0', 'R', '\x0', 'M', '\x0', 'H', '\x0', 'E', '\x0', + 'A', '\x0', 'D', '\x0', 'E', '\x0', 'R', '\x0', '>', + '\x0', }; const char kExpectedCommonPssh[] = { @@ -146,23 +201,77 @@ TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIds) { const std::vector> kTestKeyIds = {GetTestKeyId1(), GetTestKeyId2()}; std::unique_ptr playready_pssh_generator( - new PlayReadyPsshGenerator()); + new PlayReadyPsshGenerator(FOURCC_cenc)); ProtectionSystemSpecificInfo info; EXPECT_NOT_OK( playready_pssh_generator->GeneratePsshFromKeyIds(kTestKeyIds, &info)); } -TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKey) { +TEST(PsshGeneratorTest, + GeneratePlayReadyPsshFromKeyIdAndKeyWithoutProtectionScheme) { const std::vector kTestKeyId = GetTestKeyId1(); const std::vector kTestKey = GetTestKey1(); std::unique_ptr playready_pssh_generator( - new PlayReadyPsshGenerator()); + new PlayReadyPsshGenerator(FOURCC_NULL)); + ProtectionSystemSpecificInfo info; + EXPECT_NOT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey( + kTestKeyId, kTestKey, &info)); +} + +TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCenc) { + const std::vector kTestKeyId = GetTestKeyId1(); + const std::vector kTestKey = GetTestKey1(); + std::unique_ptr playready_pssh_generator( + new PlayReadyPsshGenerator(FOURCC_cenc)); ProtectionSystemSpecificInfo info; EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey( kTestKeyId, kTestKey, &info)); - EXPECT_THAT(info.psshs, ElementsAreArray(std::begin(kExpectedPlayReadyPssh), - std::end(kExpectedPlayReadyPssh))); + EXPECT_THAT(info.psshs, + ElementsAreArray(std::begin(kExpectedPlayReadyPsshWithCtrKey), + std::end(kExpectedPlayReadyPsshWithCtrKey))); +} + +TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCens) { + const std::vector kTestKeyId = GetTestKeyId1(); + const std::vector kTestKey = GetTestKey1(); + std::unique_ptr playready_pssh_generator( + new PlayReadyPsshGenerator(FOURCC_cens)); + ProtectionSystemSpecificInfo info; + EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey( + kTestKeyId, kTestKey, &info)); + + EXPECT_THAT(info.psshs, + ElementsAreArray(std::begin(kExpectedPlayReadyPsshWithCtrKey), + std::end(kExpectedPlayReadyPsshWithCtrKey))); +} + +TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCbc1) { + const std::vector kTestKeyId = GetTestKeyId1(); + const std::vector kTestKey = GetTestKey1(); + std::unique_ptr playready_pssh_generator( + new PlayReadyPsshGenerator(FOURCC_cbc1)); + ProtectionSystemSpecificInfo info; + EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey( + kTestKeyId, kTestKey, &info)); + + EXPECT_THAT(info.psshs, + ElementsAreArray(std::begin(kExpectedPlayReadyPsshWithCbcKey), + std::end(kExpectedPlayReadyPsshWithCbcKey))); +} + +TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCbcs) { + const std::vector kTestKeyId = GetTestKeyId1(); + const std::vector kTestKey = GetTestKey1(); + std::unique_ptr playready_pssh_generator( + new PlayReadyPsshGenerator(FOURCC_cbcs)); + ProtectionSystemSpecificInfo info; + EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey( + kTestKeyId, kTestKey, &info)); + + EXPECT_THAT(info.psshs, + ElementsAreArray(std::begin(kExpectedPlayReadyPsshWithCbcKey), + std::end(kExpectedPlayReadyPsshWithCbcKey))); } TEST(PsshGeneratorTest, GenerateCommonPsshFromKeyIds) { @@ -213,7 +322,7 @@ TEST(PsshGeneratorTest, GenerateWidevinePsshFromKeyIdsWithProtectionScheme) { std::end(kExpectedWidevinePsshCbcs))); } -TEST(PsshGeneratorTest, GenerateWidevinyPsshFromKeyIdAndKey) { +TEST(PsshGeneratorTest, GenerateWidevinePsshFromKeyIdAndKey) { const std::vector kTestKeyId = GetTestKeyId1(); const std::vector kTestKey = GetTestKey1(); std::unique_ptr widevine_pssh_generator(