From 0fe31423cb5e3bf6e870f69d45799637384a10c6 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Mon, 6 Aug 2018 16:12:19 -0700 Subject: [PATCH] Multi-DRM flag refactoring - Added flag --additional_protection_systems to specify multi-DRM options. - Deprecated old multi-DRM flags: --generate_widevine_pssh --generate_playready_pssh --generate_common_pssh Issue: #245. Change-Id: If926bc9d481e941aa2269b6672bf2ba5411c3a50 --- CHANGELOG.md | 2 +- .../options/general_encryption_options.rst | 19 +++------- .../options/playready_encryption_options.rst | 12 ++----- .../options/raw_key_encryption_options.rst | 11 ++++-- .../options/widevine_encryption_options.rst | 4 ++- docs/source/tutorials/raw_key.rst | 13 +++---- docs/source/tutorials/widevine.rst | 9 +++-- packager/app/crypto_flags.h | 2 +- packager/app/packager_main.cc | 35 +++++++++++++++++-- packager/app/packager_util.cc | 32 ++++++++++++----- .../app/playready_key_encryption_flags.cc | 4 +-- packager/app/protection_system_flags.cc | 22 ++++-------- packager/app/protection_system_flags.h | 4 +-- packager/app/retired_flags.cc | 25 +++++++++++++ packager/app/retired_flags.h | 3 ++ packager/media/base/playready_key_source.cc | 4 +-- packager/media/base/playready_key_source.h | 2 +- packager/media/public/crypto_params.h | 29 ++++++--------- 18 files changed, 138 insertions(+), 94 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27fbbe57bf..7a1acdac90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ ## [2.1.0] - 2018-05-22 ### Added -- Support Widevine and Playready PSSH generation internally in packager (#245). +- Support Widevine and PlayReady PSSH generation internally in packager (#245). Documentation will be updated later. - Support removing segments outside of live window in DASH and HLS (#223). - Support UTCTiming for DASH (#311). diff --git a/docs/source/options/general_encryption_options.rst b/docs/source/options/general_encryption_options.rst index 101a641647..b455f895cf 100644 --- a/docs/source/options/general_encryption_options.rst +++ b/docs/source/options/general_encryption_options.rst @@ -14,19 +14,8 @@ General encryption options Clear lead in seconds if encryption is enabled. ---generate_widevine_pssh +--additional_protection_systems - Generate a Widevine PSSH box. This option is always true - when using :doc:`/tutorials/widevine` key source. - ---generate_common_pssh - - Generate a v1 PSSH box for the common system ID that includes - the key IDs. See https://goo.gl/s8RIhr. This option is default to be - true when using :doc:`/tutorials/raw_key` source and no other pssh - flag is specified. - ---generate_playready_pssh - - Generate a PlayReady PSSH box. This option is always - true when using :doc:`/tutorials/playready` key source. + Generate additional protection systems in addition to the native protection + system provided by the key source. Supported protection systems include + Widevine, PlayReady, 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 6b10e8b772..9e530a39b9 100644 --- a/docs/source/options/playready_encryption_options.rst +++ b/docs/source/options/playready_encryption_options.rst @@ -3,7 +3,9 @@ PlayReady encryption options --enable_playready_encryption - Enable encryption with playready key. + Enable encryption with PlayReady key. This generates PlayReady protection + system. Additional protection systems can be generated with + --additional_protection_systems option. --playready_server_url @@ -13,14 +15,6 @@ PlayReady encryption options Program identifier for packaging request. ---playready_key_id - - PlayReady key id in hex. - ---playready_key - - PlayReady key in hex. - --ca_file Absolute path to the certificate authority file for the server cert. diff --git a/docs/source/options/raw_key_encryption_options.rst b/docs/source/options/raw_key_encryption_options.rst index cdda7ee32e..be95b86190 100644 --- a/docs/source/options/raw_key_encryption_options.rst +++ b/docs/source/options/raw_key_encryption_options.rst @@ -3,7 +3,11 @@ Raw key encryption options --enable_raw_key_encryption - Enable encryption with raw key (keys provided in command line)). + 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. --enable_raw_key_decryption @@ -31,5 +35,6 @@ Raw key encryption options --pssh - One or more concatenated PSSH boxes in hex string format. If not specified, - a `v1 common PSSH box `_ will be generated. + One or more concatenated PSSH boxes in hex string format. If neither this + flag nor --additional_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 7b95e978fc..98c21e8b30 100644 --- a/docs/source/options/widevine_encryption_options.rst +++ b/docs/source/options/widevine_encryption_options.rst @@ -5,7 +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). + (--rsa_signing_key_path). This generates Widevine protection system by + default. Additional protection systems can be generated with + --additional_protection_systems option. --enable_widevine_decryption diff --git a/docs/source/tutorials/raw_key.rst b/docs/source/tutorials/raw_key.rst index c914dc0122..da7aa4b087 100644 --- a/docs/source/tutorials/raw_key.rst +++ b/docs/source/tutorials/raw_key.rst @@ -51,7 +51,7 @@ Common PSSH (different keys for different streams):: --keys label=AUDIO:key_id=f3c5e0361e6654b28f8049c778b23946:key=a4631a153a443df9eed0593043db7519,label=SD:key_id=abba271e8bcf552bbd2e86a434a9a5d9:key=69eaa802a6763af979e8d1940fb88392,label=HD:key_id=6d76f25cb17f5e16b8eaef6bbf582d8e:key=cb541084c99731aef4fff74500c12ead \ --mpd_output h264.mpd -Widevine PSSH (with pre-generated Widevine PSSH):: +Widevine (with pre-generated Widevine PSSH):: $ packager \ in=h264_baseline_360p_600.mp4,stream=audio,output=audio.mp4,drm_label=AUDIO \ @@ -64,7 +64,7 @@ Widevine PSSH (with pre-generated Widevine PSSH):: --pssh 000000317073736800000000EDEF8BA979D64ACEA3C827DCD51D21ED00000011220F7465737420636F6E74656E74206964 \ --mpd_output h264.mpd -Widevine PSSH and PlayReady PSSH:: +Widevine and PlayReady:: $ packager \ in=h264_baseline_360p_600.mp4,stream=audio,output=audio.mp4,drm_label=AUDIO \ @@ -74,12 +74,13 @@ Widevine PSSH and PlayReady PSSH:: 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 \ - --generate_widevine_pssh \ - --generate_playready_pssh \ + --additional_protection_systems Widevine,PlayReady \ --mpd_output h264.mpd -Note that user is responsible for setting up Widevine and PlayReady license server -and managing keys there. +.. note:: + + User is responsible for setting up Widevine and PlayReady license server and + managing keys there. Refer to `player setup `_ diff --git a/docs/source/tutorials/widevine.rst b/docs/source/tutorials/widevine.rst index a8c9ba0bc7..11fd07d5ae 100644 --- a/docs/source/tutorials/widevine.rst +++ b/docs/source/tutorials/widevine.rst @@ -72,7 +72,7 @@ The examples below uses the H264 streams created in :doc:`encoding`. --aes_signing_key 1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f947ab9 \ --aes_signing_iv d58ce954203b7c9a9a9d467f59839249 -* One example with multi-DRM support (Playready PSSH in addition to Widevine PSSH):: +* One example with multi-DRM support (PlayReady in addition to Widevine):: $ packager \ in=h264_baseline_360p_600.mp4,stream=audio,output=audio.mp4 \ @@ -88,9 +88,12 @@ The examples below uses the H264 streams created in :doc:`encoding`. --signer widevine_test \ --aes_signing_key 1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f947ab9 \ --aes_signing_iv d58ce954203b7c9a9a9d467f59839249 \ - --generate_playready_pssh + --additional_protection_systems PlayReady -Note that user is responsible for setting up the PlayReady server and managing keys there. +.. note:: + + User is responsible for setting up the PlayReady server and managing keys + there. Refer to `player setup `_ diff --git a/packager/app/crypto_flags.h b/packager/app/crypto_flags.h index d1bd891677..4d9e16fead 100644 --- a/packager/app/crypto_flags.h +++ b/packager/app/crypto_flags.h @@ -5,7 +5,7 @@ // https://developers.google.com/open-source/licenses/bsd // // Defines common command line flags for encryption and decryption, which -// applies to all key sources, i.e. fixed key, widevine and playready. +// applies to all key sources, i.e. raw key, Widevine and PlayReady. #ifndef PACKAGER_APP_CRYPTO_FLAGS_H_ #define PACKAGER_APP_CRYPTO_FLAGS_H_ diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 9418fc606f..d8357240fa 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -257,6 +257,32 @@ bool ParseAdCues(const std::string& ad_cues, std::vector* cuepoints) { return true; } +bool ParseProtectionSystems( + const std::string& protection_systems_str, + std::vector* protection_systems) { + protection_systems->clear(); + + std::map mapping = { + {"common", EncryptionParams::ProtectionSystem::kCommonSystem}, + {"commonsystem", EncryptionParams::ProtectionSystem::kCommonSystem}, + {"playready", EncryptionParams::ProtectionSystem::kPlayReady}, + {"widevine", EncryptionParams::ProtectionSystem::kWidevine}, + }; + + for (const std::string& protection_system : + base::SplitString(base::ToLowerASCII(protection_systems_str), ",", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + auto iter = mapping.find(protection_system); + if (iter == mapping.end()) { + LOG(ERROR) << "Seeing unrecognized protection system: " + << protection_system; + return false; + } + protection_systems->push_back(iter->second); + } + return true; +} + base::Optional GetPackagingParams() { PackagingParams packaging_params; @@ -276,9 +302,6 @@ base::Optional GetPackagingParams() { int num_key_providers = 0; EncryptionParams& encryption_params = packaging_params.encryption_params; - encryption_params.generate_common_pssh = FLAGS_generate_common_pssh; - encryption_params.generate_playready_pssh = FLAGS_generate_playready_pssh; - encryption_params.generate_widevine_pssh = FLAGS_generate_widevine_pssh; if (FLAGS_enable_widevine_encryption) { encryption_params.key_provider = KeyProvider::kWidevine; ++num_key_providers; @@ -298,6 +321,12 @@ base::Optional GetPackagingParams() { return base::nullopt; } + if (!ParseProtectionSystems( + FLAGS_additional_protection_systems, + &encryption_params.additional_protection_systems)) { + return base::nullopt; + } + if (encryption_params.key_provider != KeyProvider::kNone) { encryption_params.clear_lead_in_seconds = FLAGS_clear_lead; if (!GetProtectionScheme(&encryption_params.protection_scheme)) diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index 8fee8f7fdf..74117aec58 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -44,18 +44,32 @@ std::unique_ptr CreateSigner(const WidevineSigner& signer) { return request_signer; } +int GetProtectionSystemsFlag( + const std::vector& protection_systems) { + int protection_systems_flags = 0; + for (const auto protection_system : protection_systems) { + switch (protection_system) { + case EncryptionParams::ProtectionSystem::kCommonSystem: + protection_systems_flags |= COMMON_PROTECTION_SYSTEM_FLAG; + break; + case EncryptionParams::ProtectionSystem::kPlayReady: + protection_systems_flags |= PLAYREADY_PROTECTION_SYSTEM_FLAG; + break; + case EncryptionParams::ProtectionSystem::kWidevine: + protection_systems_flags |= WIDEVINE_PROTECTION_SYSTEM_FLAG; + break; + } + } + return protection_systems_flags; +} + } // namespace std::unique_ptr CreateEncryptionKeySource( FourCC protection_scheme, const EncryptionParams& encryption_params) { - int protection_systems_flags(0); - if (encryption_params.generate_common_pssh) - protection_systems_flags |= COMMON_PROTECTION_SYSTEM_FLAG; - if (encryption_params.generate_playready_pssh) - protection_systems_flags |= PLAYREADY_PROTECTION_SYSTEM_FLAG; - if (encryption_params.generate_widevine_pssh) - protection_systems_flags |= WIDEVINE_PROTECTION_SYSTEM_FLAG; + int protection_systems_flags = + GetProtectionSystemsFlag(encryption_params.additional_protection_systems); std::unique_ptr encryption_key_source; switch (encryption_params.key_provider) { @@ -105,7 +119,7 @@ std::unique_ptr CreateEncryptionKeySource( !playready.program_identifier.empty()) { if (playready.key_server_url.empty() || playready.program_identifier.empty()) { - LOG(ERROR) << "Either playready key_server_url or program_identifier " + LOG(ERROR) << "Either PlayReady key_server_url or program_identifier " "is not set."; return nullptr; } @@ -115,7 +129,7 @@ std::unique_ptr CreateEncryptionKeySource( !playready.client_cert_private_key_file.empty()) { if (playready.client_cert_file.empty() || playready.client_cert_private_key_file.empty()) { - LOG(ERROR) << "Either playready client_cert_file or " + LOG(ERROR) << "Either PlayReady client_cert_file or " "client_cert_private_key_file is not set."; return nullptr; } diff --git a/packager/app/playready_key_encryption_flags.cc b/packager/app/playready_key_encryption_flags.cc index 10d1ae12fd..4a28110a06 100644 --- a/packager/app/playready_key_encryption_flags.cc +++ b/packager/app/playready_key_encryption_flags.cc @@ -4,7 +4,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd // -// Defines command line flags for playready encryption. +// Defines command line flags for PlayReady encryption. #include "packager/app/playready_key_encryption_flags.h" @@ -12,7 +12,7 @@ DEFINE_bool(enable_playready_encryption, false, - "Enable encryption with playready key."); + "Enable encryption with PlayReady key."); DEFINE_string(playready_server_url, "", "PlayReady packaging server url."); DEFINE_string(program_identifier, "", "Program identifier for packaging request."); diff --git a/packager/app/protection_system_flags.cc b/packager/app/protection_system_flags.cc index 4550d0eb67..48c9efcdb0 100644 --- a/packager/app/protection_system_flags.cc +++ b/packager/app/protection_system_flags.cc @@ -8,19 +8,9 @@ #include "packager/app/protection_system_flags.h" -DEFINE_bool(generate_common_pssh, - false, - "When specified, generate an additional v1 PSSH box for the common " - "system ID. See: https://goo.gl/s8RIhr." - "The flag is default to be true if --enable_raw_key_encryption " - "is set and no other pssh flags are specified."); -DEFINE_bool(generate_playready_pssh, - false, - "When specified, include a PlayReady PSSH box." - "A playready PSSH is always generated regardless of the value of " - "--generate_playready_pssh for --enable_playready_encryption."); -DEFINE_bool(generate_widevine_pssh, - false, - "When specified, include a Widevine PSSH box. " - "A widevine PSSH is always generated regardless of the value of " - "--generate_widevine_pssh for --enable_widevine_encryption."); +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, and " + "CommonSystem (https://goo.gl/s8RIhr)."); diff --git a/packager/app/protection_system_flags.h b/packager/app/protection_system_flags.h index 39c185e16d..e3e00236bb 100644 --- a/packager/app/protection_system_flags.h +++ b/packager/app/protection_system_flags.h @@ -11,8 +11,6 @@ #include -DECLARE_bool(generate_common_pssh); -DECLARE_bool(generate_playready_pssh); -DECLARE_bool(generate_widevine_pssh); +DECLARE_string(additional_protection_systems); #endif // PACKAGER_APP_PROTECTION_SYSTEM_FLAGS_H_ diff --git a/packager/app/retired_flags.cc b/packager/app/retired_flags.cc index b2c6be8e0f..62cf3e4a62 100644 --- a/packager/app/retired_flags.cc +++ b/packager/app/retired_flags.cc @@ -35,6 +35,18 @@ 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."); // 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, @@ -70,6 +82,16 @@ bool InformRetiredDefaultInt32Flag(const char* flagname, int32_t value) { return true; } +bool InformRetiredPsshGenerationFlag(const char* flagname, bool value) { + if (value) { + fprintf(stderr, + "WARNING: %s is deprecated and ignored. Please switch to " + "--additional_protection_systems.\n", + flagname); + } + return true; +} + DEFINE_validator(profile, &InformRetiredStringFlag); DEFINE_validator(single_segment, &InformRetiredDefaultTrueFlag); DEFINE_validator(webm_subsample_encryption, &InformRetiredDefaultTrueFlag); @@ -79,3 +101,6 @@ DEFINE_validator(playready_key, &InformRetiredStringFlag); DEFINE_validator(mp4_use_decoding_timestamp_in_timeline, &InformRetiredDefaultFalseFlag); DEFINE_validator(num_subsegments_per_sidx, &InformRetiredDefaultInt32Flag); +DEFINE_validator(generate_widevine_pssh, &InformRetiredPsshGenerationFlag); +DEFINE_validator(generate_playready_pssh, &InformRetiredPsshGenerationFlag); +DEFINE_validator(generate_common_pssh, &InformRetiredPsshGenerationFlag); diff --git a/packager/app/retired_flags.h b/packager/app/retired_flags.h index 679fe958c9..730804426d 100644 --- a/packager/app/retired_flags.h +++ b/packager/app/retired_flags.h @@ -14,3 +14,6 @@ DECLARE_string(playready_key_id); DECLARE_string(playready_key); DECLARE_bool(mp4_use_decoding_timestamp_in_timeline); DECLARE_int32(num_subsegments_per_sidx); +DECLARE_bool(generate_widevine_pssh); +DECLARE_bool(generate_playready_pssh); +DECLARE_bool(generate_common_pssh); diff --git a/packager/media/base/playready_key_source.cc b/packager/media/base/playready_key_source.cc index bb0797dffb..9beff55cdb 100644 --- a/packager/media/base/playready_key_source.cc +++ b/packager/media/base/playready_key_source.cc @@ -185,7 +185,7 @@ Status PlayReadyKeySource::FetchKeysWithProgramIdentifier( } status = SetKeyInformationFromServerResponse(acquire_license_response, encryption_key.get()); - // Playready does not specify different streams. + // PlayReady does not specify different streams. const char kEmptyDrmLabel[] = ""; EncryptionKeyMap encryption_key_map; encryption_key_map[kEmptyDrmLabel] = std::move(encryption_key); @@ -199,7 +199,7 @@ Status PlayReadyKeySource::FetchKeysWithProgramIdentifier( Status PlayReadyKeySource::FetchKeys(EmeInitDataType init_data_type, const std::vector& init_data) { - // Do nothing for playready encryption/decryption. + // Do nothing for PlayReady encryption/decryption. return Status::OK; } diff --git a/packager/media/base/playready_key_source.h b/packager/media/base/playready_key_source.h index 1d2f7c45d6..bfeed139d7 100644 --- a/packager/media/base/playready_key_source.h +++ b/packager/media/base/playready_key_source.h @@ -16,7 +16,7 @@ namespace shaka { namespace media { -/// A key source that uses playready for encryption. +/// A key source that uses PlayReady for encryption. class PlayReadyKeySource : public KeySource { public: /// Creates a new PlayReadyKeySource from the given packaging information. diff --git a/packager/media/public/crypto_params.h b/packager/media/public/crypto_params.h index 9dfb407069..e0029dc7a2 100644 --- a/packager/media/public/crypto_params.h +++ b/packager/media/public/crypto_params.h @@ -64,12 +64,8 @@ struct WidevineEncryptionParams { }; /// PlayReady encryption parameters. -/// Two different modes of playready key acquisition is supported: -/// (1) Fetch from a key server. `key_server_url` and `program_identifier` are -/// required. The presence of other parameters may be necessary depends -/// on server configuration. -/// (2) Provide the raw key directly. Both `key_id` and `key` are required. -/// We are planning to merge this mode with `RawKeyParams`. +/// `key_server_url` and `program_identifier` are required. The presence of +/// other parameters may be necessary depends on server configuration. struct PlayReadyEncryptionParams { /// PlayReady license / key server URL. std::string key_server_url; @@ -119,19 +115,14 @@ struct EncryptionParams { PlayReadyEncryptionParams playready; RawKeyParams raw_key; - /// When it is true, generate a v1 PSSH box for the common - /// system ID. See: https://goo.gl/s8RIhr. - /// The flag is default to be true if --enable_raw_key_encryption - /// is set and no other pssh flags are specified. - bool generate_common_pssh = false; - /// When it is true, include a PlayReady PSSH box. - /// A playready PSSH is always generated regardless of the value of - /// --generate_playready_pssh for --enable_playready_encryption. - bool generate_playready_pssh = false; - /// When it is true, include a widevine PSSH box. - /// A widevine PSSH is always generated regardless of the value of - /// --generate_widevine_pssh for --enable_widevine_encryption. - bool generate_widevine_pssh = false; + /// Supported protection systems. + enum class ProtectionSystem { + kWidevine, + kPlayReady, + kCommonSystem, + }; + /// Additional protection systems to be generated. + std::vector additional_protection_systems; /// Clear lead duration in seconds. double clear_lead_in_seconds = 0;