diff --git a/docs/source/options/general_encryption_options.rst b/docs/source/options/general_encryption_options.rst index b03dbdb9fe..bbd383518e 100644 --- a/docs/source/options/general_encryption_options.rst +++ b/docs/source/options/general_encryption_options.rst @@ -14,8 +14,7 @@ General encryption options Clear lead in seconds if encryption is enabled. ---additional_protection_systems +--protection_systems - Generate additional protection systems in addition to the native protection - system provided by the key source. Supported protection systems include + Protection systems to be generated. Supported protection systems include Widevine, PlayReady, FairPlay, and CommonSystem (https://goo.gl/s8RIhr). diff --git a/docs/source/options/playready_encryption_options.rst b/docs/source/options/playready_encryption_options.rst index 9e530a39b9..5917d84de0 100644 --- a/docs/source/options/playready_encryption_options.rst +++ b/docs/source/options/playready_encryption_options.rst @@ -4,8 +4,8 @@ PlayReady encryption options --enable_playready_encryption Enable encryption with PlayReady key. This generates PlayReady protection - system. Additional protection systems can be generated with - --additional_protection_systems option. + system if --protection_systems is not specified. Use --protection_system to + generate multiple protection systems. --playready_server_url diff --git a/docs/source/options/raw_key_encryption_options.rst b/docs/source/options/raw_key_encryption_options.rst index be95b86190..92c66d6823 100644 --- a/docs/source/options/raw_key_encryption_options.rst +++ b/docs/source/options/raw_key_encryption_options.rst @@ -5,9 +5,9 @@ Raw key encryption options Enable encryption with raw key (keys provided in command line)). This generates `Common protection system `_ if neither - --pssh nor --additional_protection_systems is specified. Use --pssh to - provide custom protection systems or use --additional_protection_systems to - generate protection systems automatically. + --pssh nor --protection_systems is specified. Use --pssh to provide custom + protection systems or use --protection_systems to generate protection + systems automatically. --enable_raw_key_decryption @@ -36,5 +36,5 @@ Raw key encryption options --pssh One or more concatenated PSSH boxes in hex string format. If neither this - flag nor --additional_protection_systems is specified, a + flag nor --protection_systems is specified, a `v1 common PSSH box `_ will be generated. diff --git a/docs/source/options/widevine_encryption_options.rst b/docs/source/options/widevine_encryption_options.rst index 98c21e8b30..9d875a6975 100644 --- a/docs/source/options/widevine_encryption_options.rst +++ b/docs/source/options/widevine_encryption_options.rst @@ -5,9 +5,9 @@ Widevine encryption options Enable encryption with Widevine key server. User should provide either AES signing key (--aes_signing_key, --aes_signing_iv) or RSA signing key - (--rsa_signing_key_path). This generates Widevine protection system by - default. Additional protection systems can be generated with - --additional_protection_systems option. + (--rsa_signing_key_path). This generates Widevine protection system if + --protection_systems is not specified. Use --protection_systems to generate + multiple protection systems. --enable_widevine_decryption diff --git a/docs/source/tutorials/raw_key.rst b/docs/source/tutorials/raw_key.rst index da7aa4b087..87808cf449 100644 --- a/docs/source/tutorials/raw_key.rst +++ b/docs/source/tutorials/raw_key.rst @@ -74,7 +74,7 @@ Widevine and PlayReady:: in=h264_high_1080p_6000.mp4,stream=video,output=h264_1080p.mp4,drm_label=HD \ --enable_raw_key_encryption \ --keys label=AUDIO:key_id=f3c5e0361e6654b28f8049c778b23946:key=a4631a153a443df9eed0593043db7519,label=SD:key_id=abba271e8bcf552bbd2e86a434a9a5d9:key=69eaa802a6763af979e8d1940fb88392,label=HD:key_id=6d76f25cb17f5e16b8eaef6bbf582d8e:key=cb541084c99731aef4fff74500c12ead \ - --additional_protection_systems Widevine,PlayReady \ + --protection_systems Widevine,PlayReady \ --mpd_output h264.mpd .. note:: diff --git a/docs/source/tutorials/widevine.rst b/docs/source/tutorials/widevine.rst index 11fd07d5ae..63a9dfe0e7 100644 --- a/docs/source/tutorials/widevine.rst +++ b/docs/source/tutorials/widevine.rst @@ -88,7 +88,7 @@ The examples below uses the H264 streams created in :doc:`encoding`. --signer widevine_test \ --aes_signing_key 1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f947ab9 \ --aes_signing_iv d58ce954203b7c9a9a9d467f59839249 \ - --additional_protection_systems PlayReady + --protection_systems Widevine,PlayReady .. note:: diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 7b6efb0953..2a1c193998 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -322,9 +322,8 @@ base::Optional GetPackagingParams() { return base::nullopt; } - if (!ParseProtectionSystems( - FLAGS_additional_protection_systems, - &encryption_params.additional_protection_systems)) { + if (!ParseProtectionSystems(FLAGS_protection_systems, + &encryption_params.protection_systems)) { return base::nullopt; } diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index c91419b8c7..0176f0eb80 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -72,7 +72,7 @@ std::unique_ptr CreateEncryptionKeySource( FourCC protection_scheme, const EncryptionParams& encryption_params) { int protection_systems_flags = - GetProtectionSystemsFlag(encryption_params.additional_protection_systems); + GetProtectionSystemsFlag(encryption_params.protection_systems); std::unique_ptr encryption_key_source; switch (encryption_params.key_provider) { diff --git a/packager/app/protection_system_flags.cc b/packager/app/protection_system_flags.cc index c1cbd371e6..755aa41087 100644 --- a/packager/app/protection_system_flags.cc +++ b/packager/app/protection_system_flags.cc @@ -8,9 +8,8 @@ #include "packager/app/protection_system_flags.h" -DEFINE_string(additional_protection_systems, - "", - "Generate additional protection systems in addition to the " - "native protection system provided by the key source. Supported " - "protection systems include Widevine, PlayReady, FairPlay, and " - "CommonSystem (https://goo.gl/s8RIhr)."); +DEFINE_string( + protection_systems, + "", + "Protection systems to be generated. Supported protection systems include " + "Widevine, PlayReady, FairPlay, and CommonSystem (https://goo.gl/s8RIhr)."); diff --git a/packager/app/protection_system_flags.h b/packager/app/protection_system_flags.h index e3e00236bb..35660ec228 100644 --- a/packager/app/protection_system_flags.h +++ b/packager/app/protection_system_flags.h @@ -11,6 +11,6 @@ #include -DECLARE_string(additional_protection_systems); +DECLARE_string(protection_systems); #endif // PACKAGER_APP_PROTECTION_SYSTEM_FLAGS_H_ diff --git a/packager/app/retired_flags.cc b/packager/app/retired_flags.cc index 62cf3e4a62..84d1c30587 100644 --- a/packager/app/retired_flags.cc +++ b/packager/app/retired_flags.cc @@ -35,18 +35,15 @@ DEFINE_int32( num_subsegments_per_sidx, 0, "This flag is deprecated. Use --generate_sidx_in_media_segments instead."); -DEFINE_bool( - generate_widevine_pssh, - false, - "This flag is deprecated. Use --additional_protection_systems instead."); -DEFINE_bool( - generate_playready_pssh, - false, - "This flag is deprecated. Use --additional_protection_systems instead."); -DEFINE_bool( - generate_common_pssh, - false, - "This flag is deprecated. Use --additional_protection_systems instead."); +DEFINE_bool(generate_widevine_pssh, + false, + "This flag is deprecated. Use --protection_systems instead."); +DEFINE_bool(generate_playready_pssh, + false, + "This flag is deprecated. Use --protection_systems instead."); +DEFINE_bool(generate_common_pssh, + false, + "This flag is deprecated. Use --protection_systems instead."); // The current gflags library does not provide a way to check whether a flag is // set in command line. If a flag has a different value to its default value, @@ -86,7 +83,7 @@ bool InformRetiredPsshGenerationFlag(const char* flagname, bool value) { if (value) { fprintf(stderr, "WARNING: %s is deprecated and ignored. Please switch to " - "--additional_protection_systems.\n", + "--protection_systems.\n", flagname); } return true; diff --git a/packager/app/test/packager_test.py b/packager/app/test/packager_test.py index 85af128be2..56b5524376 100755 --- a/packager/app/test/packager_test.py +++ b/packager/app/test/packager_test.py @@ -444,8 +444,7 @@ class PackagerAppTest(unittest.TestCase): fairplay_key_uri = ('skd://www.license.com/' 'getkey?KeyId=31323334-3536-3738-3930-313233343536') flags += [ - '--additional_protection_systems=FairPlay', - '--hls_key_uri=' + fairplay_key_uri + '--protection_systems=FairPlay', '--hls_key_uri=' + fairplay_key_uri ] if protection_scheme: flags += ['--protection_scheme', protection_scheme] diff --git a/packager/media/base/playready_key_source.cc b/packager/media/base/playready_key_source.cc index d7185eb682..fa13ba0d96 100644 --- a/packager/media/base/playready_key_source.cc +++ b/packager/media/base/playready_key_source.cc @@ -68,6 +68,11 @@ PlayReadyKeySource::PlayReadyKeySource(const std::string& server_url, // PlayReady PSSH is retrived from PlayReady server response. : KeySource(protection_system_flags & ~PLAYREADY_PROTECTION_SYSTEM_FLAG, protection_scheme), + generate_playready_protection_system_( + // Generate PlayReady protection system if there are no other + // protection system specified. + protection_system_flags == NO_PROTECTION_SYSTEM_FLAG || + protection_system_flags & PLAYREADY_PROTECTION_SYSTEM_FLAG), encryption_key_(new EncryptionKey), server_url_(server_url) {} @@ -113,8 +118,10 @@ Status RetrieveTextInXMLElement(const std::string& element, return Status::OK; } -Status SetKeyInformationFromServerResponse(const std::string& response, - EncryptionKey* encryption_key) { +Status SetKeyInformationFromServerResponse( + const std::string& response, + bool generate_playready_protection_system, + EncryptionKey* encryption_key) { // TODO(robinconnell): Currently all tracks are encrypted using the same // key_id and key. Add the ability to retrieve multiple key_id/keys from // the packager response and encrypt multiple tracks using differnt @@ -135,20 +142,23 @@ Status SetKeyInformationFromServerResponse(const std::string& response, return Status(error::SERVER_ERROR, "Cannot parse key."); } - std::string pssh_data_b64; - RETURN_IF_ERROR(RetrieveTextInXMLElement("Data", response, &pssh_data_b64)); - std::vector pssh_data; - if (!Base64StringToBytes(pssh_data_b64, &pssh_data)) { - LOG(ERROR) << "Cannot parse pssh data, " << pssh_data_b64; - return Status(error::SERVER_ERROR, "Cannot parse pssh."); - } + if (generate_playready_protection_system) { + std::string pssh_data_b64; + RETURN_IF_ERROR(RetrieveTextInXMLElement("Data", response, &pssh_data_b64)); + std::vector pssh_data; + if (!Base64StringToBytes(pssh_data_b64, &pssh_data)) { + LOG(ERROR) << "Cannot parse pssh data, " << pssh_data_b64; + return Status(error::SERVER_ERROR, "Cannot parse pssh."); + } - PsshBoxBuilder pssh_builder; - pssh_builder.add_key_id(encryption_key->key_id); - pssh_builder.set_system_id(kPlayReadySystemId, arraysize(kPlayReadySystemId)); - pssh_builder.set_pssh_data(pssh_data); - encryption_key->key_system_info.push_back( - {pssh_builder.system_id(), pssh_builder.CreateBox()}); + PsshBoxBuilder pssh_builder; + pssh_builder.add_key_id(encryption_key->key_id); + pssh_builder.set_system_id(kPlayReadySystemId, + arraysize(kPlayReadySystemId)); + pssh_builder.set_pssh_data(pssh_data); + encryption_key->key_system_info.push_back( + {pssh_builder.system_id(), pssh_builder.CreateBox()}); + } return Status::OK; } @@ -174,8 +184,9 @@ Status PlayReadyKeySource::FetchKeysWithProgramIdentifier( VLOG(1) << "Server response: " << acquire_license_response; RETURN_IF_ERROR(status); - RETURN_IF_ERROR(SetKeyInformationFromServerResponse(acquire_license_response, - encryption_key.get())); + RETURN_IF_ERROR(SetKeyInformationFromServerResponse( + acquire_license_response, generate_playready_protection_system_, + encryption_key.get())); // PlayReady does not specify different streams. const char kEmptyDrmLabel[] = ""; diff --git a/packager/media/base/playready_key_source.h b/packager/media/base/playready_key_source.h index 971c9d367d..d119ab3f75 100644 --- a/packager/media/base/playready_key_source.h +++ b/packager/media/base/playready_key_source.h @@ -77,6 +77,9 @@ class PlayReadyKeySource : public KeySource { Status GetKeyInternal(); Status GetCryptoPeriodKeyInternal(); + // Indicates whether PlayReady protection system should be generated. + bool generate_playready_protection_system_ = true; + std::unique_ptr encryption_key_; std::string server_url_; std::string ca_file_; diff --git a/packager/media/base/widevine_key_source.cc b/packager/media/base/widevine_key_source.cc index 67c74944b0..30e5465d5b 100644 --- a/packager/media/base/widevine_key_source.cc +++ b/packager/media/base/widevine_key_source.cc @@ -83,6 +83,11 @@ WidevineKeySource::WidevineKeySource(const std::string& server_url, // Widevine PSSH is fetched from Widevine license server. : KeySource(protection_system_flags & ~WIDEVINE_PROTECTION_SYSTEM_FLAG, protection_scheme), + generate_widevine_protection_system_( + // Generate Widevine protection system if there are no other + // protection system specified. + protection_system_flags == NO_PROTECTION_SYSTEM_FLAG || + protection_system_flags & WIDEVINE_PROTECTION_SYSTEM_FLAG), key_production_thread_("KeyProductionThread", base::Bind(&WidevineKeySource::FetchKeysTask, base::Unretained(this))), @@ -90,11 +95,8 @@ WidevineKeySource::WidevineKeySource(const std::string& server_url, server_url_(server_url), crypto_period_count_(kDefaultCryptoPeriodCount), protection_scheme_(protection_scheme), - key_production_started_(false), start_key_production_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), - first_crypto_period_index_(0), - enable_entitlement_license_(false) { + base::WaitableEvent::InitialState::NOT_SIGNALED) { key_production_thread_.Start(); } @@ -445,13 +447,15 @@ bool WidevineKeySource::ExtractEncryptionKey( encryption_key->key_id.assign(track.key_id().begin(), track.key_id().end()); - if (track.pssh_size() != 1) { - LOG(ERROR) << "Expecting one and only one pssh, seeing " - << track.pssh_size(); - return false; + if (generate_widevine_protection_system_) { + if (track.pssh_size() != 1) { + LOG(ERROR) << "Expecting one and only one pssh, seeing " + << track.pssh_size(); + return false; + } + encryption_key->key_system_info.push_back( + ProtectionSystemInfoFromPsshProto(track.pssh(0))); } - encryption_key->key_system_info.push_back( - ProtectionSystemInfoFromPsshProto(track.pssh(0))); } encryption_key_map[stream_label] = std::move(encryption_key); } diff --git a/packager/media/base/widevine_key_source.h b/packager/media/base/widevine_key_source.h index 2c73d48c66..a76590dca4 100644 --- a/packager/media/base/widevine_key_source.h +++ b/packager/media/base/widevine_key_source.h @@ -111,6 +111,9 @@ class WidevineKeySource : public KeySource { // Push the keys to the key pool. bool PushToKeyPool(EncryptionKeyMap* encryption_key_map); + // Indicates whether Widevine protection system should be generated. + bool generate_widevine_protection_system_ = true; + ClosureThread key_production_thread_; // The fetcher object used to fetch keys from the license service. // It is initialized to a default fetcher on class initialization. @@ -121,13 +124,13 @@ class WidevineKeySource : public KeySource { std::unique_ptr common_encryption_request_; const int crypto_period_count_; - FourCC protection_scheme_; + FourCC protection_scheme_ = FOURCC_NULL; base::Lock lock_; - bool key_production_started_; + bool key_production_started_ = false; base::WaitableEvent start_key_production_; - uint32_t first_crypto_period_index_; + uint32_t first_crypto_period_index_ = 0; std::vector group_id_; - bool enable_entitlement_license_; + bool enable_entitlement_license_ = false; std::unique_ptr key_pool_; EncryptionKeyMap encryption_key_map_; // For non key rotation request. Status common_encryption_request_status_; diff --git a/packager/media/base/widevine_key_source_unittest.cc b/packager/media/base/widevine_key_source_unittest.cc index f46e55e4d3..954ce43d3e 100644 --- a/packager/media/base/widevine_key_source_unittest.cc +++ b/packager/media/base/widevine_key_source_unittest.cc @@ -13,7 +13,6 @@ #include "packager/base/strings/string_number_conversions.h" #include "packager/base/strings/stringprintf.h" #include "packager/media/base/key_fetcher.h" -#include "packager/media/base/playready_pssh_generator.h" #include "packager/media/base/raw_key_pssh_generator.h" #include "packager/media/base/request_signer.h" #include "packager/media/base/widevine_key_source.h" @@ -228,11 +227,11 @@ class WidevineKeySourceTest : public Test { } void CreateWidevineKeySource() { - int protection_system_flags = WIDEVINE_PROTECTION_SYSTEM_FLAG; + int protection_system_flags = NO_PROTECTION_SYSTEM_FLAG; + if (add_widevine_pssh_) + protection_system_flags |= WIDEVINE_PROTECTION_SYSTEM_FLAG; if (add_common_pssh_) protection_system_flags |= COMMON_PROTECTION_SYSTEM_FLAG; - if (add_playready_pssh_) - protection_system_flags |= PLAYREADY_PROTECTION_SYSTEM_FLAG; widevine_key_source_.reset(new WidevineKeySource( kServerUrl, protection_system_flags, protection_scheme_)); widevine_key_source_->set_key_fetcher(std::move(mock_key_fetcher_)); @@ -246,32 +245,31 @@ class WidevineKeySourceTest : public Test { EXPECT_EQ(GetMockKey(stream_label), ToString(encryption_key.key)); if (!classic) { size_t num_key_system_info = - 1 + (add_common_pssh_ ? 1 : 0) + (add_playready_pssh_ ? 1 : 0); + (add_widevine_pssh_ && add_common_pssh_) ? 2 : 1; ASSERT_EQ(num_key_system_info, encryption_key.key_system_info.size()); EXPECT_EQ(GetMockKeyId(stream_label), ToString(encryption_key.key_id)); - const std::vector& pssh = - encryption_key.key_system_info[0].psshs; - std::unique_ptr pssh_builder = - PsshBoxBuilder::ParseFromBox(pssh.data(), pssh.size()); - ASSERT_TRUE(pssh_builder); - EXPECT_EQ(GetMockPsshData(), ToString(pssh_builder->pssh_data())); + auto key_system_info_iter = encryption_key.key_system_info.begin(); + + // Default to Widevine if neither are set. + if (add_widevine_pssh_ || !add_common_pssh_) { + const std::vector widevine_system_id( + std::begin(kWidevineSystemId), std::end(kWidevineSystemId)); + ASSERT_EQ(widevine_system_id, key_system_info_iter->system_id); + + const std::vector& pssh = key_system_info_iter->psshs; + std::unique_ptr pssh_builder = + PsshBoxBuilder::ParseFromBox(pssh.data(), pssh.size()); + ASSERT_TRUE(pssh_builder); + EXPECT_EQ(GetMockPsshData(), ToString(pssh_builder->pssh_data())); + + ++key_system_info_iter; + } if (add_common_pssh_) { const std::vector common_system_id( - kCommonSystemId, kCommonSystemId + arraysize(kCommonSystemId)); - ASSERT_EQ(common_system_id, - encryption_key.key_system_info[1].system_id); - } - - if (add_playready_pssh_) { - const std::vector playready_system_id( - kPlayReadySystemId, - kPlayReadySystemId + arraysize(kPlayReadySystemId)); - // PlayReady pssh index depends on if there has common pssh box. - const uint8_t playready_index = 1 + (add_common_pssh_ ? 1 : 0); - ASSERT_EQ(playready_system_id, - encryption_key.key_system_info[playready_index].system_id); + std::begin(kCommonSystemId), std::end(kCommonSystemId)); + ASSERT_EQ(common_system_id, key_system_info_iter->system_id); } } } @@ -280,8 +278,8 @@ class WidevineKeySourceTest : public Test { std::unique_ptr mock_key_fetcher_; std::unique_ptr widevine_key_source_; std::vector content_id_; + bool add_widevine_pssh_ = false; bool add_common_pssh_ = false; - bool add_playready_pssh_ = false; FourCC protection_scheme_ = FOURCC_cenc; private: @@ -371,8 +369,8 @@ class WidevineKeySourceParameterizedTest public WithParamInterface> { public: WidevineKeySourceParameterizedTest() { - add_common_pssh_ = std::tr1::get<0>(GetParam()); - add_playready_pssh_ = std::tr1::get<1>(GetParam()); + add_widevine_pssh_ = std::tr1::get<0>(GetParam()); + add_common_pssh_ = std::tr1::get<1>(GetParam()); protection_scheme_ = std::tr1::get<2>(GetParam()); } }; @@ -415,10 +413,9 @@ TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencOK) { VerifyKeys(false); } -TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencNotOK) { +TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencMalformedResponse) { std::string mock_response = base::StringPrintf( - kHttpResponseFormat, Base64Encode( - GenerateMockClassicLicenseResponse()).c_str()); + kHttpResponseFormat, Base64Encode("malformed response").c_str()); EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _)) .WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK))); @@ -444,16 +441,15 @@ TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencWithPsshBoxOK) { CreateWidevineKeySource(); widevine_key_source_->set_signer(std::move(mock_request_signer_)); - std::vector pssh_box(kRequestPsshBox, - kRequestPsshBox + arraysize(kRequestPsshBox)); + std::vector pssh_box(std::begin(kRequestPsshBox), + std::end(kRequestPsshBox)); ASSERT_OK(widevine_key_source_->FetchKeys(EmeInitDataType::CENC, pssh_box)); VerifyKeys(false); } TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencWithKeyIdsOK) { - std::string expected_pssh_data( - kRequestPsshDataFromKeyIds, - kRequestPsshDataFromKeyIds + arraysize(kRequestPsshDataFromKeyIds)); + std::string expected_pssh_data(std::begin(kRequestPsshDataFromKeyIds), + std::end(kRequestPsshDataFromKeyIds)); std::string expected_message = base::StringPrintf(kExpectedRequestMessageWithPsshFormat, Base64Encode(expected_pssh_data).c_str()); @@ -468,8 +464,8 @@ TEST_P(WidevineKeySourceParameterizedTest, LicenseStatusCencWithKeyIdsOK) { CreateWidevineKeySource(); widevine_key_source_->set_signer(std::move(mock_request_signer_)); - std::vector key_id(kRequestKeyId, - kRequestKeyId + arraysize(kRequestKeyId)); + std::vector key_id(std::begin(kRequestKeyId), + std::end(kRequestKeyId)); ASSERT_OK(widevine_key_source_->FetchKeys(EmeInitDataType::WEBM, key_id)); VerifyKeys(false); } diff --git a/packager/media/public/crypto_params.h b/packager/media/public/crypto_params.h index a08f5c8b56..91e0d9b1da 100644 --- a/packager/media/public/crypto_params.h +++ b/packager/media/public/crypto_params.h @@ -122,8 +122,8 @@ struct EncryptionParams { kPlayReady, kWidevine, }; - /// Additional protection systems to be generated. - std::vector additional_protection_systems; + /// Protection systems to be generated. + std::vector protection_systems; /// Clear lead duration in seconds. double clear_lead_in_seconds = 0;