diff --git a/packager/app/fixed_key_encryption_flags.cc b/packager/app/fixed_key_encryption_flags.cc index 7b6d383d42..6c67421353 100644 --- a/packager/app/fixed_key_encryption_flags.cc +++ b/packager/app/fixed_key_encryption_flags.cc @@ -16,17 +16,19 @@ DEFINE_bool(enable_fixed_key_encryption, DEFINE_bool(enable_fixed_key_decryption, false, "Enable decryption with fixed key."); -DEFINE_string(key_id, "", "Key id in hex string format."); -DEFINE_string(key, "", "Key in hex string format."); -DEFINE_string(iv, - "", - "Iv in hex string format. If not specified, a random iv will be " - "generated. This flag should only be used for testing."); -DEFINE_string(pssh, - "", - "One or more PSSH boxes in hex string format. If not specified, " - "will generate a v1 common PSSH box as specified in " - "https://goo.gl/s8RIhr."); +DEFINE_hex_bytes(key_id, "", "Key id in hex string format."); +DEFINE_hex_bytes(key, "", "Key in hex string format."); +DEFINE_hex_bytes( + iv, + "", + "IV in hex string format. If not specified, a random IV will be " + "generated. This flag should only be used for testing."); +DEFINE_hex_bytes( + pssh, + "", + "One or more PSSH boxes in hex string format. If not specified, " + "will generate a v1 common PSSH box as specified in " + "https://goo.gl/s8RIhr."); namespace shaka { @@ -38,20 +40,20 @@ bool ValidateFixedCryptoFlags() { const char fixed_crypto_label[] = "--enable_fixed_key_encryption/decryption"; // --key_id and --key are associated with --enable_fixed_key_encryption and // --enable_fixed_key_decryption. - if (!ValidateFlag( - "key_id", FLAGS_key_id, fixed_crypto, false, fixed_crypto_label)) { + if (!ValidateFlag("key_id", FLAGS_key_id_bytes, fixed_crypto, false, + fixed_crypto_label)) { success = false; } - if (!ValidateFlag( - "key", FLAGS_key, fixed_crypto, false, fixed_crypto_label)) { + if (!ValidateFlag("key", FLAGS_key_bytes, fixed_crypto, false, + fixed_crypto_label)) { success = false; } - if (!ValidateFlag("iv", FLAGS_iv, FLAGS_enable_fixed_key_encryption, true, - "--enable_fixed_key_encryption")) { + if (!ValidateFlag("iv", FLAGS_iv_bytes, FLAGS_enable_fixed_key_encryption, + true, "--enable_fixed_key_encryption")) { success = false; } - if (!FLAGS_iv.empty()) { - if (FLAGS_iv.size() != 8 * 2 && FLAGS_iv.size() != 16 * 2) { + if (!FLAGS_iv_bytes.empty()) { + if (FLAGS_iv_bytes.size() != 8 && FLAGS_iv_bytes.size() != 16) { PrintError( "--iv should be either 8 bytes (16 hex digits) or 16 bytes (32 hex " "digits)."); @@ -60,11 +62,8 @@ bool ValidateFixedCryptoFlags() { } // --pssh is associated with --enable_fix_key_encryption. - if (!ValidateFlag("pssh", - FLAGS_pssh, - FLAGS_enable_fixed_key_encryption, - true, - "--enable_fixed_key_encryption")) { + if (!ValidateFlag("pssh", FLAGS_pssh_bytes, FLAGS_enable_fixed_key_encryption, + true, "--enable_fixed_key_encryption")) { success = false; } return success; diff --git a/packager/app/fixed_key_encryption_flags.h b/packager/app/fixed_key_encryption_flags.h index bf26bff6a4..b3ef29fbdd 100644 --- a/packager/app/fixed_key_encryption_flags.h +++ b/packager/app/fixed_key_encryption_flags.h @@ -11,13 +11,15 @@ #include +#include "packager/app/gflags_hex_bytes.h" + // TODO(kqyang): s/fixed/raw/. DECLARE_bool(enable_fixed_key_encryption); DECLARE_bool(enable_fixed_key_decryption); -DECLARE_string(key_id); -DECLARE_string(key); -DECLARE_string(iv); -DECLARE_string(pssh); +DECLARE_hex_bytes(key_id); +DECLARE_hex_bytes(key); +DECLARE_hex_bytes(iv); +DECLARE_hex_bytes(pssh); namespace shaka { diff --git a/packager/app/gflags_hex_bytes.cc b/packager/app/gflags_hex_bytes.cc new file mode 100644 index 0000000000..c5a68c4ee6 --- /dev/null +++ b/packager/app/gflags_hex_bytes.cc @@ -0,0 +1,25 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "packager/app/gflags_hex_bytes.h" + +#include "packager/base/strings/string_number_conversions.h" + +namespace shaka { + +bool ValidateHexString(const char* flagname, + const std::string& value, + std::vector* value_bytes) { + std::vector temp_value_bytes; + if (!value.empty() && !base::HexStringToBytes(value, &temp_value_bytes)) { + printf("Invalid hex string for --%s: %s\n", flagname, value.c_str()); + return false; + } + value_bytes->swap(temp_value_bytes); + return true; +} + +} // namespace shaka diff --git a/packager/app/gflags_hex_bytes.h b/packager/app/gflags_hex_bytes.h new file mode 100644 index 0000000000..3cfb7cb156 --- /dev/null +++ b/packager/app/gflags_hex_bytes.h @@ -0,0 +1,50 @@ +// Copyright 2017 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd +// +// Extends gflags to support hex formatted bytes. + +#ifndef PACKAGER_APP_GFLAGS_HEX_BYTES_H_ +#define PACKAGER_APP_GFLAGS_HEX_BYTES_H_ + +#include + +#include +#include + +namespace shaka { +bool ValidateHexString(const char* flagname, + const std::string& value, + std::vector* value_bytes); +} // namespace shaka + +// The raw bytes will be available in FLAGS_##name##_bytes. +// The original gflag variable FLAGS_##name is defined in shaka_gflags_extension +// and not exposed directly. +#define DECLARE_hex_bytes(name) \ + namespace shaka_gflags_extension { \ + DECLARE_string(name); \ + } \ + namespace shaka_gflags_extension { \ + extern std::vector FLAGS_##name##_bytes; \ + } \ + using shaka_gflags_extension::FLAGS_##name##_bytes + +#define DEFINE_hex_bytes(name, val, txt) \ + namespace shaka_gflags_extension { \ + DEFINE_string(name, val, txt); \ + } \ + namespace shaka_gflags_extension { \ + std::vector FLAGS_##name##_bytes; \ + static bool hex_validator_##name = gflags::RegisterFlagValidator( \ + &FLAGS_##name, \ + [](const char* flagname, const std::string& value) { \ + return shaka::ValidateHexString(flagname, value, \ + &FLAGS_##name##_bytes); \ + }); \ + } \ + using shaka_gflags_extension::FLAGS_##name##_bytes + +#endif // PACKAGER_APP_GFLAGS_HEX_BYTES_H_ diff --git a/packager/app/packager_main.cc b/packager/app/packager_main.cc index 91b8aa0a43..7cc85b0d47 100644 --- a/packager/app/packager_main.cc +++ b/packager/app/packager_main.cc @@ -97,6 +97,24 @@ enum ExitStatus { kInternalError, }; +bool GetWidevineSigner(WidevineSigner* signer) { + signer->signer_name = FLAGS_signer; + if (!FLAGS_aes_signing_key_bytes.empty()) { + signer->signing_key_type = WidevineSigner::SigningKeyType::kAes; + signer->aes.key = FLAGS_aes_signing_key_bytes; + signer->aes.iv = FLAGS_aes_signing_iv_bytes; + } else if (!FLAGS_rsa_signing_key_path.empty()) { + signer->signing_key_type = WidevineSigner::SigningKeyType::kRsa; + if (!media::File::ReadFileToString(FLAGS_rsa_signing_key_path.c_str(), + &signer->rsa.key)) { + LOG(ERROR) << "Failed to read from '" << FLAGS_rsa_signing_key_path + << "'."; + return false; + } + } + return true; +} + base::Optional GetPackagingParams() { PackagingParams packaging_params; @@ -143,33 +161,10 @@ base::Optional GetPackagingParams() { widevine.key_server_url = FLAGS_key_server_url; widevine.include_common_pssh = FLAGS_include_common_pssh; - if (!base::HexStringToBytes(FLAGS_content_id, &widevine.content_id)) { - LOG(ERROR) << "Invalid content_id hex string specified."; - return base::nullopt; - } + widevine.content_id = FLAGS_content_id_bytes; widevine.policy = FLAGS_policy; - widevine.signer.signer_name = FLAGS_signer; - if (!FLAGS_aes_signing_key.empty() && !FLAGS_rsa_signing_key_path.empty()) { - LOG(ERROR) << "Only one of --aes_signing_key and " - "--rsa_signing_key_path is needed."; + if (!GetWidevineSigner(&widevine.signer)) return base::nullopt; - } - WidevineSigner& signer = widevine.signer; - if (!FLAGS_aes_signing_key.empty()) { - // TODO(kqyang): Take care of hex conversion and file read here. - signer.signing_key_type = WidevineSigner::SigningKeyType::kAes; - signer.aes.key = FLAGS_aes_signing_key; - signer.aes.iv = FLAGS_aes_signing_iv; - } - if (!FLAGS_rsa_signing_key_path.empty()) { - signer.signing_key_type = WidevineSigner::SigningKeyType::kRsa; - if (!media::File::ReadFileToString(FLAGS_rsa_signing_key_path.c_str(), - &signer.rsa.key)) { - LOG(ERROR) << "Failed to read from '" << FLAGS_rsa_signing_key_path - << "'."; - return base::nullopt; - } - } break; } case KeyProvider::kPlayready: { @@ -182,19 +177,18 @@ base::Optional GetPackagingParams() { FLAGS_client_cert_private_key_file; playready.client_cert_private_key_password = FLAGS_client_cert_private_key_password; - playready.key_id = FLAGS_playready_key_id; - playready.key = FLAGS_playready_key; + playready.key_id = FLAGS_playready_key_id_bytes; + playready.key = FLAGS_playready_key_bytes; break; } case KeyProvider::kRawKey: { RawKeyEncryptionParams& raw_key = encryption_params.raw_key; - raw_key.iv = FLAGS_iv; - raw_key.pssh = FLAGS_pssh; - // An empty TrackType specifies the default KeyPair. + raw_key.iv = FLAGS_iv_bytes; + raw_key.pssh = FLAGS_pssh_bytes; + // An empty StreamLabel specifies the default KeyPair. RawKeyEncryptionParams::KeyPair& key_pair = raw_key.key_map[""]; - // TODO(kqyang): Take care of hex conversion here. - key_pair.key_id = FLAGS_key_id; - key_pair.key = FLAGS_key; + key_pair.key_id = FLAGS_key_id_bytes; + key_pair.key = FLAGS_key_bytes; break; } case KeyProvider::kNone: @@ -220,42 +214,20 @@ base::Optional GetPackagingParams() { case KeyProvider::kWidevine: { WidevineDecryptionParams& widevine = decryption_params.widevine; widevine.key_server_url = FLAGS_key_server_url; - - widevine.signer.signer_name = FLAGS_signer; - if (!FLAGS_aes_signing_key.empty() && !FLAGS_rsa_signing_key_path.empty()) { - LOG(ERROR) << "Only one of --aes_signing_key and " - "--rsa_signing_key_path is needed."; + if (!GetWidevineSigner(&widevine.signer)) return base::nullopt; - } - WidevineSigner& signer = widevine.signer; - if (!FLAGS_aes_signing_key.empty()) { - // TODO(kqyang): Take care of hex conversion and file read here. - signer.signing_key_type = WidevineSigner::SigningKeyType::kAes; - signer.aes.key = FLAGS_aes_signing_key; - signer.aes.iv = FLAGS_aes_signing_iv; - } - if (!FLAGS_rsa_signing_key_path.empty()) { - signer.signing_key_type = WidevineSigner::SigningKeyType::kRsa; - if (!media::File::ReadFileToString(FLAGS_rsa_signing_key_path.c_str(), - &signer.rsa.key)) { - LOG(ERROR) << "Failed to read from '" << FLAGS_rsa_signing_key_path - << "'."; - return base::nullopt; - } - } break; } case KeyProvider::kRawKey: { RawKeyDecryptionParams& raw_key = decryption_params.raw_key; - // An empty TrackType specifies the default KeyPair. + // An empty StreamLabel specifies the default KeyPair. RawKeyDecryptionParams::KeyPair& key_pair = raw_key.key_map[""]; - // TODO(kqyang): Take care of hex conversion here. - key_pair.key_id = FLAGS_key_id; - key_pair.key = FLAGS_key; + key_pair.key_id = FLAGS_key_id_bytes; + key_pair.key = FLAGS_key_bytes; break; } - case KeyProvider::kNone: case KeyProvider::kPlayready: + case KeyProvider::kNone: break; } diff --git a/packager/app/packager_util.cc b/packager/app/packager_util.cc index 9a0ce4302a..137cbc2638 100644 --- a/packager/app/packager_util.cc +++ b/packager/app/packager_util.cc @@ -103,7 +103,7 @@ std::unique_ptr CreateEncryptionKeySource( const RawKeyEncryptionParams& raw_key = encryption_params.raw_key; const std::string kDefaultTrackType; // TODO(kqyang): Refactor FixedKeySource. - encryption_key_source = FixedKeySource::CreateFromHexStrings( + encryption_key_source = FixedKeySource::Create( raw_key.key_map.find("")->second.key_id, raw_key.key_map.find("")->second.key, raw_key.pssh, raw_key.iv); break; @@ -171,9 +171,9 @@ std::unique_ptr CreateDecryptionKeySource( } case KeyProvider::kRawKey: { const RawKeyDecryptionParams& raw_key = decryption_params.raw_key; - const char kNoPssh[] = ""; - const char kNoIv[] = ""; - decryption_key_source = FixedKeySource::CreateFromHexStrings( + const std::vector kNoPssh; + const std::vector kNoIv; + decryption_key_source = FixedKeySource::Create( raw_key.key_map.find("")->second.key_id, raw_key.key_map.find("")->second.key, kNoPssh, kNoIv); break; diff --git a/packager/app/playready_key_encryption_flags.cc b/packager/app/playready_key_encryption_flags.cc index d911e9b9e9..c2084c550d 100644 --- a/packager/app/playready_key_encryption_flags.cc +++ b/packager/app/playready_key_encryption_flags.cc @@ -16,8 +16,8 @@ DEFINE_bool(enable_playready_encryption, DEFINE_string(playready_server_url, "", "PlayReady packaging server url."); DEFINE_string(program_identifier, "", "Program identifier for packaging request."); -DEFINE_string(playready_key_id, "", "PlayReady key id in hex."); -DEFINE_string(playready_key, "", "PlayReady key in hex."); +DEFINE_hex_bytes(playready_key_id, "", "PlayReady key id in hex."); +DEFINE_hex_bytes(playready_key, "", "PlayReady key in hex."); DEFINE_string(ca_file, "", "Absolute path to the Certificate Authority file for the " "server cert. PEM format"); @@ -45,16 +45,16 @@ bool ValidatePRCryptoFlags() { } bool use_packaging = !FLAGS_playready_server_url.empty() && !FLAGS_program_identifier.empty(); - if (!ValidateFlag("playready_key_id", FLAGS_playready_key_id, + if (!ValidateFlag("playready_key_id", FLAGS_playready_key_id_bytes, playready_enabled, true, playready_label)) { success = false; } - if (!ValidateFlag("playready_key", FLAGS_playready_key, + if (!ValidateFlag("playready_key", FLAGS_playready_key_bytes, playready_enabled, true, playready_label)) { success = false; } - bool use_fixed_key = !FLAGS_playready_key_id.empty() && - !FLAGS_playready_key.empty(); + bool use_fixed_key = !FLAGS_playready_key_id_bytes.empty() && + !FLAGS_playready_key_bytes.empty(); if (playready_enabled && !use_packaging && !use_fixed_key) { PrintError("combination of --playready_server_url and " diff --git a/packager/app/playready_key_encryption_flags.h b/packager/app/playready_key_encryption_flags.h index 664d00240d..7540040633 100644 --- a/packager/app/playready_key_encryption_flags.h +++ b/packager/app/playready_key_encryption_flags.h @@ -11,11 +11,13 @@ #include +#include "packager/app/gflags_hex_bytes.h" + DECLARE_bool(enable_playready_encryption); DECLARE_string(playready_server_url); DECLARE_string(program_identifier); -DECLARE_string(playready_key_id); -DECLARE_string(playready_key); +DECLARE_hex_bytes(playready_key_id); +DECLARE_hex_bytes(playready_key); DECLARE_string(ca_file); DECLARE_string(client_cert_file); DECLARE_string(client_cert_private_key_file); diff --git a/packager/app/test/packager_app.py b/packager/app/test/packager_app.py index 21736af546..1a0b3706ed 100644 --- a/packager/app/test/packager_app.py +++ b/packager/app/test/packager_app.py @@ -52,8 +52,9 @@ class PackagerApp(object): # Put single-quotes around each entry so that things like '$' signs in # segment templates won't be interpreted as shell variables. self.packaging_command_line = ' '.join(["'%s'" % entry for entry in cmd]) - assert 0 == subprocess.call(cmd), ('%s returned non-0 status' % - self.packaging_command_line) + self.packaging_result = subprocess.call(cmd) + if self.packaging_result != 0: + print '%s returned non-0 status' % self.packaging_command_line def GetCommandLine(self): return self.packaging_command_line diff --git a/packager/app/test/packager_test.py b/packager/app/test/packager_test.py index 150bcb00b1..70b774327e 100755 --- a/packager/app/test/packager_test.py +++ b/packager/app/test/packager_test.py @@ -42,6 +42,18 @@ class PackagerAppTest(unittest.TestCase): self.hls_master_playlist_output = self.output_prefix + '.m3u8' self.output = None + # Test variables. + self.encryption_key_id = '31323334353637383930313233343536' + if test_env.options.encryption_key: + self.encryption_key = test_env.options.encryption_key + else: + self.encryption_key = '32333435363738393021323334353637' + if test_env.options.encryption_iv: + self.encryption_iv = test_env.options.encryption_iv + else: + self.encryption_iv = '3334353637383930' + self.widevine_content_id = '3031323334353637' + def tearDown(self): if test_env.options.remove_temp_files_after_test: shutil.rmtree(self.tmp_dir) @@ -83,6 +95,7 @@ class PackagerAppTest(unittest.TestCase): def testPackageFirstStream(self): self.packager.Package(self._GetStreams(['0']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-v-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-v-golden.mpd') @@ -90,6 +103,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['text'], test_files=['subtitle-english.vtt']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'subtitle-english-golden.vtt') self._DiffGold(self.mpd_output, 'subtitle-english-vtt-golden.mpd') @@ -97,6 +111,7 @@ class PackagerAppTest(unittest.TestCase): def testPackageAudioVideo(self): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-golden.mpd') @@ -105,6 +120,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[2], 'bear-640x360-v-trick-1-golden.mp4') @@ -115,6 +131,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['audio', 'video', 'video,trick_play_factor=1', 'video,trick_play_factor=2']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[2], 'bear-640x360-v-trick-1-golden.mp4') @@ -127,6 +144,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['audio', 'video', 'video,trick_play_factor=2', 'video,trick_play_factor=1']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[2], 'bear-640x360-v-trick-2-golden.mp4') @@ -140,6 +158,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video'], language_override='por-BR'), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-por-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-por-golden.mpd') @@ -148,6 +167,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video'], language_override='por-BR'), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-por-BR-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-por-BR-golden.mpd') @@ -157,6 +177,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams( ['audio'], test_files=['bear-640x360-aac_he-silent_right.mp4']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-aac_he-silent_right-golden.mp4') self._DiffGold(self.mpd_output, @@ -168,6 +189,7 @@ class PackagerAppTest(unittest.TestCase): text_stream = self._GetStreams(['text'], test_files=['subtitle-english.vtt']) self.packager.Package(audio_video_streams + text_stream, self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[2], 'subtitle-english-golden.vtt') @@ -181,6 +203,7 @@ class PackagerAppTest(unittest.TestCase): live=True, test_files=['bear-640x360.ts']), self._GetFlags(output_hls=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-golden', output_format='ts') @@ -200,6 +223,7 @@ class PackagerAppTest(unittest.TestCase): output_format='webm', test_files=['bear-640x360.webm']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-vp8-golden.webm') self._DiffGold(self.mpd_output, 'bear-640x360-vp8-webm-golden.mpd') @@ -209,6 +233,7 @@ class PackagerAppTest(unittest.TestCase): output_format='webm', test_files=['bear-320x240-vp9-opus.webm']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-320x240-opus-golden.webm') self._DiffGold(self.output[1], 'bear-320x240-vp9-golden.webm') self._DiffGold(self.mpd_output, 'bear-320x240-vp9-opus-webm-golden.mpd') @@ -219,6 +244,7 @@ class PackagerAppTest(unittest.TestCase): output_format='webm', test_files=['bear-vp9-blockgroup.webm']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-vp9-blockgroup-golden.webm') def testPackageVorbisWebm(self): @@ -227,6 +253,7 @@ class PackagerAppTest(unittest.TestCase): output_format='webm', test_files=['bear-320x240-audio-only.webm']), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-320x240-vorbis-golden.webm') self._DiffGold(self.mpd_output, 'bear-320x240-vorbis-webm-golden.mpd') @@ -234,16 +261,84 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-cenc-golden.mpd') self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4') self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4') + def testPackageWithEncryptionWithIncorrectKeyIdLength1(self): + self.encryption_key_id = self.encryption_key_id[0:-2] + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithIncorrectKeyIdLength2(self): + self.encryption_key_id += '12' + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithInvalidKeyIdValue(self): + self.encryption_key_id = self.encryption_key_id[0:-1] + 'g' + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithIncorrectKeyLength1(self): + self.encryption_key = self.encryption_key[0:-2] + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithIncorrectKeyLength2(self): + self.encryption_key += '12' + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithInvalidKeyValue(self): + self.encryption_key = self.encryption_key[0:-1] + 'g' + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithIncorrectIvLength1(self): + self.encryption_iv = self.encryption_iv[0:-2] + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithIncorrectIvLength2(self): + self.encryption_iv += '12' + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithInvalidIvValue(self): + self.encryption_iv = self.encryption_iv[0:-1] + 'g' + self.packager.Package( + self._GetStreams(['video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithInvalidPsshValue1(self): + self.packager.Package( + self._GetStreams(['video']), + self._GetFlags(encryption=True) + ['--pssh=ag']) + self.assertEqual(self.packager.packaging_result, 1) + + def testPackageWithEncryptionWithInvalidPsshValue2(self): + self.packager.Package( + self._GetStreams(['video']), + self._GetFlags(encryption=True) + ['--pssh=1122']) + self.assertEqual(self.packager.packaging_result, 1) + def testPackageWithEncryptionOfOnlyVideoStream(self): self.packager.Package( self._GetStreams(['audio,skip_encryption=1', 'video']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-a-clear-v-cenc-golden.mpd') @@ -253,6 +348,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4') self._DiffGold(self.output[2], 'bear-640x360-v-trick-1-cenc-golden.mp4') @@ -268,6 +364,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['audio', 'video', 'video,trick_play_factor=1', 'video,trick_play_factor=2']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4') self._DiffGold(self.output[2], 'bear-640x360-v-trick-1-cenc-golden.mp4') @@ -283,6 +380,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, clear_lead=0)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cenc-no-clear-lead-golden.mp4') self._DiffGold(self.output[1], @@ -296,6 +394,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, include_pssh_in_stream=False)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cenc-no-pssh-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cenc-no-pssh-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-cenc-no-pssh-golden.mpd') @@ -307,6 +406,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, protection_scheme='cbc1')) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cbc1-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cbc1-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-cbc1-golden.mpd') @@ -318,6 +418,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, protection_scheme='cens')) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cens-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cens-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-cens-golden.mpd') @@ -329,6 +430,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, protection_scheme='cbcs')) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cbcs-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cbcs-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-cbcs-golden.mpd') @@ -341,6 +443,7 @@ class PackagerAppTest(unittest.TestCase): output_format='webm', test_files=['bear-320x180-vp9-altref.webm']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-320x180-vp9-altref-enc-golden.webm') self._VerifyDecryption(self.output[0], 'bear-320x180-vp9-altref-dec-golden.webm') @@ -351,6 +454,7 @@ class PackagerAppTest(unittest.TestCase): output_format='webm', test_files=['bear-320x180-vp9-altref.webm']), self._GetFlags(encryption=True, vp9_subsample_encryption=False)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-320x180-vp9-fullsample-enc-golden.webm') self._VerifyDecryption(self.output[0], @@ -364,6 +468,7 @@ class PackagerAppTest(unittest.TestCase): live=True, test_files=['bear-640x360.ts']), self._GetFlags(encryption=True, output_hls=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-enc-golden', output_format='ts') @@ -380,6 +485,7 @@ class PackagerAppTest(unittest.TestCase): 'bear-640x360-v-enc-golden.m3u8') def testPackageAvcTsWithEncryptionExerciseEmulationPrevention(self): + self.encryption_key = 'ad7e9786def9159db6724be06dfcde7a' # Currently we only support live packaging for ts. self.packager.Package( self._GetStreams( @@ -389,8 +495,8 @@ class PackagerAppTest(unittest.TestCase): test_files=['sintel-1024x436.mp4']), self._GetFlags( encryption=True, - encryption_key='ad7e9786def9159db6724be06dfcde7a', output_hls=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'sintel-1024x436-v-enc-golden', output_format='ts') @@ -406,6 +512,7 @@ class PackagerAppTest(unittest.TestCase): output_format='webm', test_files=['bear-640x360.webm']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-vp8-cenc-golden.webm') self._DiffGold(self.mpd_output, 'bear-640x360-vp8-cenc-webm-golden.mpd') self._VerifyDecryption(self.output[0], 'bear-640x360-vp8-golden.webm') @@ -415,6 +522,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['video'], test_files=['bear-640x360-hevc.mp4']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-hevc-cenc-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-hevc-cenc-golden.mpd') self._VerifyDecryption(self.output[0], 'bear-640x360-hevc-golden.mp4') @@ -425,6 +533,7 @@ class PackagerAppTest(unittest.TestCase): output_format='mp4', test_files=['bear-640x360.webm']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-vp8-cenc-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-vp8-cenc-golden.mpd') self._VerifyDecryption(self.output[0], 'bear-640x360-vp8-golden.mp4') @@ -435,6 +544,7 @@ class PackagerAppTest(unittest.TestCase): output_format='mp4', test_files=['bear-320x240-vp9-opus.webm']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-320x240-opus-cenc-golden.mp4') self._DiffGold(self.output[1], 'bear-320x240-vp9-cenc-golden.mp4') self._DiffGold(self.mpd_output, 'bear-320x240-opus-vp9-cenc-golden.mpd') @@ -442,11 +552,12 @@ class PackagerAppTest(unittest.TestCase): self._VerifyDecryption(self.output[1], 'bear-320x240-vp9-golden.mp4') def testPackageWvmInput(self): + self.encryption_key = '9248d245390e0a49d483ba9b43fc69c3' self.packager.Package( self._GetStreams( ['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']), - self._GetFlags( - decryption=True, encryption_key='9248d245390e0a49d483ba9b43fc69c3')) + self._GetFlags(decryption=True)) + self.assertEqual(self.packager.packaging_result, 0) # Output timescale is 90000. self._DiffGold(self.output[0], 'bear-320x180-v-wvm-golden.mp4') self._DiffGold(self.output[1], 'bear-320x180-a-wvm-golden.mp4') @@ -462,13 +573,12 @@ class PackagerAppTest(unittest.TestCase): '--strip_parameter_set_nalus flag.' ) def testPackageWvmInputWithoutStrippingParameterSetNalus(self): + self.encryption_key = '9248d245390e0a49d483ba9b43fc69c3' self.packager.Package( self._GetStreams( ['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']), - self._GetFlags( - strip_parameter_set_nalus=False, - decryption=True, - encryption_key='9248d245390e0a49d483ba9b43fc69c3')) + self._GetFlags(strip_parameter_set_nalus=False, decryption=True)) + self.assertEqual(self.packager.packaging_result, 0) # Output timescale is 90000. self._DiffGold(self.output[0], 'bear-320x180-avc3-wvm-golden.mp4') self._DiffGold(self.output[1], 'bear-320x180-a-wvm-golden.mp4') @@ -480,6 +590,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, random_iv=True)) + self.assertEqual(self.packager.packaging_result, 0) self._AssertStreamInfo(self.output[0], 'is_encrypted: true') self._AssertStreamInfo(self.output[1], 'is_encrypted: true') # The outputs are encrypted with random iv, so they are not the same as @@ -496,6 +607,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, use_fake_clock=False)) + self.assertEqual(self.packager.packaging_result, 0) self._AssertStreamInfo(self.output[0], 'is_encrypted: true') self._AssertStreamInfo(self.output[1], 'is_encrypted: true') # The outputs are generated with real clock, so they are not the same as @@ -512,6 +624,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, dash_if_iop=False)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4') self._DiffGold(self.mpd_output, 'bear-640x360-av-cenc-non-iop-golden.mpd') @@ -520,6 +633,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video']), self._GetFlags(encryption=True, output_media_info=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4') self._DiffMediaInfoGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4') @@ -528,6 +642,7 @@ class PackagerAppTest(unittest.TestCase): def testPackageWithLiveProfile(self): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), self._GetFlags()) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-golden') self._DiffLiveMpdGold(self.mpd_output, 'bear-640x360-av-live-golden.mpd') @@ -536,6 +651,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), self._GetFlags(generate_static_mpd=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-golden') self._DiffGold(self.mpd_output, 'bear-640x360-av-live-static-golden.mpd') @@ -544,6 +660,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden') self._DiffLiveMpdGold(self.mpd_output, @@ -553,6 +670,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), self._GetFlags(encryption=True, dash_if_iop=False)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden') self._DiffLiveMpdGold(self.mpd_output, @@ -565,6 +683,7 @@ class PackagerAppTest(unittest.TestCase): test_files=['bear-1280x720.mp4', 'bear-640x360.mp4', 'bear-320x180.mp4']), self._GetFlags(encryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[2], 'bear-640x360-a-live-cenc-golden') self._DiffLiveGold(self.output[3], 'bear-640x360-v-live-cenc-golden') # Mpd cannot be validated right now since we don't generate determinstic @@ -575,6 +694,7 @@ class PackagerAppTest(unittest.TestCase): self.packager.Package( self._GetStreams(['audio', 'video'], live=True), self._GetFlags(encryption=True, key_rotation=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-rotation-golden') self._DiffLiveGold(self.output[1], @@ -587,6 +707,7 @@ class PackagerAppTest(unittest.TestCase): self._GetStreams(['audio', 'video'], live=True), self._GetFlags( encryption=True, key_rotation=True, include_pssh_in_stream=False)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-rotation-no-pssh-golden') self._DiffLiveGold(self.output[1], @@ -601,6 +722,7 @@ class PackagerAppTest(unittest.TestCase): self._GetFlags(encryption=True, key_rotation=True, dash_if_iop=False)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffLiveGold(self.output[0], 'bear-640x360-a-live-cenc-rotation-golden') self._DiffLiveGold(self.output[1], @@ -612,21 +734,98 @@ class PackagerAppTest(unittest.TestCase): @unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.') def testWidevineEncryptionWithAes(self): flags = self._GetFlags(widevine_encryption=True) - flags += ['--aes_signing_key=' + test_env.options.aes_signing_key, - '--aes_signing_iv=' + test_env.options.aes_signing_iv] + flags += [ + '--signer=widevine_test', + '--aes_signing_key=' + test_env.options.aes_signing_key, + '--aes_signing_iv=' + test_env.options.aes_signing_iv + ] self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 0) self._AssertStreamInfo(self.output[0], 'is_encrypted: true') self._AssertStreamInfo(self.output[1], 'is_encrypted: true') + def testWidevineEncryptionInvalidContentId(self): + self.widevine_content_id += 'ag' + flags = self._GetFlags(widevine_encryption=True) + flags += [ + '--signer=widevine_test', '--aes_signing_key=1122', + '--aes_signing_iv=3344' + ] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionInvalidAesSigningKey(self): + flags = self._GetFlags(widevine_encryption=True) + flags += [ + '--signer=widevine_test', '--aes_signing_key=11ag', + '--aes_signing_iv=3344' + ] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionInvalidAesSigningIv(self): + flags = self._GetFlags(widevine_encryption=True) + flags += [ + '--signer=widevine_test', '--aes_signing_key=1122', + '--aes_signing_iv=33ag' + ] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionMissingAesSigningKey(self): + flags = self._GetFlags(widevine_encryption=True) + flags += ['--signer=widevine_test', '--aes_signing_iv=3344'] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionMissingAesSigningIv(self): + flags = self._GetFlags(widevine_encryption=True) + flags += ['--signer=widevine_test', '--aes_signing_key=1122'] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionMissingSigner1(self): + flags = self._GetFlags(widevine_encryption=True) + flags += ['--aes_signing_key=1122', '--aes_signing_iv=3344'] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionMissingSigner2(self): + flags = self._GetFlags(widevine_encryption=True) + flags += ['--rsa_signing_key_path=/tmp/test'] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionSignerOnly(self): + flags = self._GetFlags(widevine_encryption=True) + flags += ['--signer=widevine_test'] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + + def testWidevineEncryptionAesSigningAndRsaSigning(self): + flags = self._GetFlags(widevine_encryption=True) + flags += [ + '--signer=widevine_test', + '--aes_signing_key=1122', + '--aes_signing_iv=3344', + '--rsa_signing_key_path=/tmp/test', + ] + self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 1) + @unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.') def testWidevineEncryptionWithAesAndMultFiles(self): flags = self._GetFlags(widevine_encryption=True) - flags += ['--aes_signing_key=' + test_env.options.aes_signing_key, - '--aes_signing_iv=' + test_env.options.aes_signing_iv] + flags += [ + '--signer=widevine_test', + '--aes_signing_key=' + test_env.options.aes_signing_key, + '--aes_signing_iv=' + test_env.options.aes_signing_iv + ] self.packager.Package( self._GetStreams(['audio', 'video'], test_files=['bear-1280x720.mp4', 'bear-640x360.mp4', 'bear-320x180.mp4']), flags) + self.assertEqual(self.packager.packaging_result, 0) with open(self.mpd_output, 'rb') as f: print f.read() # TODO(kqyang): Add some validations. @@ -634,17 +833,25 @@ class PackagerAppTest(unittest.TestCase): @unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.') def testKeyRotationWithAes(self): flags = self._GetFlags(widevine_encryption=True, key_rotation=True) - flags += ['--aes_signing_key=' + test_env.options.aes_signing_key, - '--aes_signing_iv=' + test_env.options.aes_signing_iv] + flags += [ + '--signer=widevine_test', + '--aes_signing_key=' + test_env.options.aes_signing_key, + '--aes_signing_iv=' + test_env.options.aes_signing_iv + ] self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 0) self._AssertStreamInfo(self.output[0], 'is_encrypted: true') self._AssertStreamInfo(self.output[1], 'is_encrypted: true') @unittest.skipUnless(test_env.has_rsa_flags, 'Requires RSA credentials.') def testWidevineEncryptionWithRsa(self): flags = self._GetFlags(widevine_encryption=True) - flags += ['--rsa_signing_key_path=' + test_env.options.rsa_signing_key_path] + flags += [ + '--signer=widevine_test', + '--rsa_signing_key_path=' + test_env.options.rsa_signing_key_path + ] self.packager.Package(self._GetStreams(['audio', 'video']), flags) + self.assertEqual(self.packager.packaging_result, 0) self._AssertStreamInfo(self.output[0], 'is_encrypted: true') self._AssertStreamInfo(self.output[1], 'is_encrypted: true') @@ -715,8 +922,6 @@ class PackagerAppTest(unittest.TestCase): protection_scheme=None, vp9_subsample_encryption=True, decryption=False, - encryption_key='32333435363738393021323334353637', - encryption_iv='3334353637383930', random_iv=False, widevine_encryption=False, key_rotation=False, @@ -734,21 +939,19 @@ class PackagerAppTest(unittest.TestCase): if widevine_encryption: widevine_server_url = ('https://license.uat.widevine.com/cenc' '/getcontentkey/widevine_test') - flags += ['--enable_widevine_encryption', - '--key_server_url=' + widevine_server_url, - '--content_id=3031323334353637', '--signer=widevine_test'] + flags += [ + '--enable_widevine_encryption', + '--key_server_url=' + widevine_server_url, + '--content_id=' + self.widevine_content_id, + ] elif encryption: flags += ['--enable_fixed_key_encryption', - '--key_id=31323334353637383930313233343536', + '--key_id=' + self.encryption_key_id, + '--key=' + self.encryption_key, '--clear_lead={0}'.format(clear_lead)] - if test_env.options.encryption_key: - encryption_key = test_env.options.encryption_key - flags.append('--key=' + encryption_key) if not random_iv: - if test_env.options.encryption_iv: - encryption_iv = test_env.options.encryption_iv - flags.append('--iv=' + encryption_iv) + flags.append('--iv=' + self.encryption_iv) if protection_scheme: flags += ['--protection_scheme', protection_scheme] if not vp9_subsample_encryption: @@ -756,8 +959,8 @@ class PackagerAppTest(unittest.TestCase): if decryption: flags += ['--enable_fixed_key_decryption', - '--key_id=31323334353637383930313233343536', - '--key=' + encryption_key] + '--key_id=' + self.encryption_key_id, + '--key=' + self.encryption_key] if key_rotation: flags.append('--crypto_period_duration=1') @@ -878,6 +1081,7 @@ class PackagerAppTest(unittest.TestCase): output_format=output_extension, test_files=[test_encrypted_file]), self._GetFlags(decryption=True)) + self.assertEqual(self.packager.packaging_result, 0) self._DiffGold(self.output[-1], golden_clear_file) diff --git a/packager/app/validate_flag.cc b/packager/app/validate_flag.cc index c752f1de46..583e9aa59b 100644 --- a/packager/app/validate_flag.cc +++ b/packager/app/validate_flag.cc @@ -10,29 +10,8 @@ #include -#include "packager/base/strings/stringprintf.h" - namespace shaka { -bool ValidateFlag(const char* flag_name, - const std::string& flag_value, - bool condition, - bool optional, - const char* label) { - if (flag_value.empty()) { - if (!optional && condition) { - PrintError( - base::StringPrintf("--%s is required if %s.", flag_name, label)); - return false; - } - } else if (!condition) { - PrintError(base::StringPrintf( - "--%s should be specified only if %s.", flag_name, label)); - return false; - } - return true; -} - void PrintError(const std::string& error_message) { fprintf(stderr, "ERROR: %s\n", error_message.c_str()); } diff --git a/packager/app/validate_flag.h b/packager/app/validate_flag.h index c1c0a390c3..b7e5285713 100644 --- a/packager/app/validate_flag.h +++ b/packager/app/validate_flag.h @@ -11,8 +11,14 @@ #include +#include "packager/base/strings/stringprintf.h" + namespace shaka { +/// Format and print error message. +/// @param error_message specifies the error message. +void PrintError(const std::string& error_message); + /// Validate a flag against the given condition. /// @param flag_name is the name of the flag. /// @param flag_value is the value of the flag. @@ -23,15 +29,25 @@ namespace shaka { /// @param label specifies the label associated with the condition. It is used /// to generate the error message on validation failure. /// @return true on success, false otherwise. +template bool ValidateFlag(const char* flag_name, - const std::string& flag_value, + const FlagType& flag_value, bool condition, bool optional, - const char* label); - -/// Format and print error message. -/// @param error_message specifies the error message. -void PrintError(const std::string& error_message); + const char* label) { + if (flag_value.empty()) { + if (!optional && condition) { + PrintError( + base::StringPrintf("--%s is required if %s.", flag_name, label)); + return false; + } + } else if (!condition) { + PrintError(base::StringPrintf( + "--%s should be specified only if %s.", flag_name, label)); + return false; + } + return true; +} } // namespace shaka diff --git a/packager/app/widevine_encryption_flags.cc b/packager/app/widevine_encryption_flags.cc index 3069acb7f5..adc8db327c 100644 --- a/packager/app/widevine_encryption_flags.cc +++ b/packager/app/widevine_encryption_flags.cc @@ -30,7 +30,7 @@ DEFINE_bool(include_common_pssh, "https://goo.gl/s8RIhr"); DEFINE_string(key_server_url, "", "Key server url. Required for encryption and " "decryption"); -DEFINE_string(content_id, "", "Content Id (hex)."); +DEFINE_hex_bytes(content_id, "", "Content Id (hex)."); DEFINE_string(policy, "", "The name of a stored policy, which specifies DRM content " @@ -50,13 +50,11 @@ DEFINE_int32(max_uhd1_pixels, "is higher than max_hd_pixels, but no higher than max_uhd1_pixels." " Otherwise it is UHD2. Default: 8847360 (4096 x 2160)."); DEFINE_string(signer, "", "The name of the signer."); -DEFINE_string(aes_signing_key, - "", - "AES signing key in hex string. --aes_signing_iv is required. " - "Exclusive with --rsa_signing_key_path."); -DEFINE_string(aes_signing_iv, - "", - "AES signing iv in hex string."); +DEFINE_hex_bytes(aes_signing_key, + "", + "AES signing key in hex string. --aes_signing_iv is required. " + "Exclusive with --rsa_signing_key_path."); +DEFINE_hex_bytes(aes_signing_iv, "", "AES signing iv in hex string."); DEFINE_string(rsa_signing_key_path, "", "Stores PKCS#1 RSA private key for request signing. Exclusive " @@ -67,6 +65,9 @@ DEFINE_int32(crypto_period_duration, "rotation is enabled."); namespace shaka { +namespace { +const bool kOptional = true; +} // namespace bool ValidateWidevineCryptoFlags() { bool success = true; @@ -80,14 +81,14 @@ bool ValidateWidevineCryptoFlags() { if (!ValidateFlag("key_server_url", FLAGS_key_server_url, widevine_crypto, - false, + !kOptional, widevine_crypto_label)) { success = false; } if (!ValidateFlag("signer", FLAGS_signer, widevine_crypto, - true, + kOptional, widevine_crypto_label)) { success = false; } @@ -102,16 +103,16 @@ bool ValidateWidevineCryptoFlags() { // content_id and policy (optional) are associated with // enable_widevine_encryption. if (!ValidateFlag("content_id", - FLAGS_content_id, + FLAGS_content_id_bytes, FLAGS_enable_widevine_encryption, - false, + !kOptional, widevine_encryption_label)) { success = false; } if (!ValidateFlag("policy", FLAGS_policy, FLAGS_enable_widevine_encryption, - true, + kOptional, widevine_encryption_label)) { success = false; } @@ -142,40 +143,32 @@ bool ValidateWidevineCryptoFlags() { success = false; } - const bool aes = !FLAGS_signer.empty() && FLAGS_rsa_signing_key_path.empty(); - const char aes_label[] = - "--signer is specified and exclusive with --rsa_signing_key_path"; - // aes_signer_key and aes_signing_iv are associated with aes signing. - if (!ValidateFlag( - "aes_signing_key", FLAGS_aes_signing_key, aes, true, aes_label)) { - success = false; - } - if (!ValidateFlag( - "aes_signing_iv", FLAGS_aes_signing_iv, aes, true, aes_label)) { + const bool aes = !FLAGS_aes_signing_key_bytes.empty() || + !FLAGS_aes_signing_iv_bytes.empty(); + if (aes && (FLAGS_aes_signing_key_bytes.empty() || + FLAGS_aes_signing_iv_bytes.empty())) { + PrintError("--aes_signing_key/iv is required if using aes signing."); success = false; } - const bool rsa = !FLAGS_signer.empty() && FLAGS_aes_signing_key.empty() && - FLAGS_aes_signing_iv.empty(); - const char rsa_label[] = - "--signer is specified and exclusive with --aes_signing_key/iv"; - // rsa_signing_key_path is associated with rsa_signing. - if (!ValidateFlag("rsa_signing_key_path", - FLAGS_rsa_signing_key_path, - rsa, - true, - rsa_label)) { + const bool rsa = !FLAGS_rsa_signing_key_path.empty(); + + if (FLAGS_signer.empty() && (aes || rsa)) { + PrintError("--signer is required if using aes/rsa signing."); success = false; } - - if (!FLAGS_signer.empty() && - (FLAGS_aes_signing_key.empty() || FLAGS_aes_signing_iv.empty()) && - FLAGS_rsa_signing_key_path.empty()) { + if (!FLAGS_signer.empty() && !aes && !rsa) { PrintError( "--aes_signing_key/iv or --rsa_signing_key_path is required with " "--signer."); success = false; } + if (aes && rsa) { + PrintError( + "Only one of --aes_signing_key/iv and --rsa_signing_key_path should be " + "specified."); + success = false; + } if (FLAGS_crypto_period_duration < 0) { PrintError("--crypto_period_duration should not be negative."); diff --git a/packager/app/widevine_encryption_flags.h b/packager/app/widevine_encryption_flags.h index 966d8118a6..7447ceb783 100644 --- a/packager/app/widevine_encryption_flags.h +++ b/packager/app/widevine_encryption_flags.h @@ -11,18 +11,20 @@ #include +#include "packager/app/gflags_hex_bytes.h" + DECLARE_bool(enable_widevine_encryption); DECLARE_bool(enable_widevine_decryption); DECLARE_bool(include_common_pssh); DECLARE_string(key_server_url); -DECLARE_string(content_id); +DECLARE_hex_bytes(content_id); DECLARE_string(policy); DECLARE_int32(max_sd_pixels); DECLARE_int32(max_hd_pixels); DECLARE_int32(max_uhd1_pixels); DECLARE_string(signer); -DECLARE_string(aes_signing_key); -DECLARE_string(aes_signing_iv); +DECLARE_hex_bytes(aes_signing_key); +DECLARE_hex_bytes(aes_signing_iv); DECLARE_string(rsa_signing_key_path); DECLARE_int32(crypto_period_duration); diff --git a/packager/media/base/fixed_key_source.cc b/packager/media/base/fixed_key_source.cc index 2688d01294..532c73c1bd 100644 --- a/packager/media/base/fixed_key_source.cc +++ b/packager/media/base/fixed_key_source.cc @@ -75,45 +75,27 @@ Status FixedKeySource::GetCryptoPeriodKey(uint32_t crypto_period_index, return Status::OK; } -std::unique_ptr FixedKeySource::CreateFromHexStrings( - const std::string& key_id_hex, - const std::string& key_hex, - const std::string& pssh_boxes_hex, - const std::string& iv_hex) { +std::unique_ptr FixedKeySource::Create( + const std::vector& key_id, + const std::vector& key, + const std::vector& pssh_boxes, + const std::vector& iv) { std::unique_ptr encryption_key(new EncryptionKey()); - if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) { - LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex; - return std::unique_ptr(); - } else if (encryption_key->key_id.size() != 16) { - LOG(ERROR) << "Invalid key ID size '" << encryption_key->key_id.size() + if (key_id.size() != 16) { + LOG(ERROR) << "Invalid key ID size '" << key_id.size() << "', must be 16 bytes."; return std::unique_ptr(); } - - if (!base::HexStringToBytes(key_hex, &encryption_key->key)) { - LOG(ERROR) << "Cannot parse key_hex " << key_hex; - return std::unique_ptr(); - } else if (encryption_key->key.size() != 16) { + if (key.size() != 16) { // CENC only supports AES-128, i.e. 16 bytes. - LOG(ERROR) << "Invalid key size '" << encryption_key->key.size() - << "', must be 16 bytes."; + LOG(ERROR) << "Invalid key size '" << key.size() << "', must be 16 bytes."; return std::unique_ptr(); } - std::vector pssh_boxes; - if (!pssh_boxes_hex.empty() && - !base::HexStringToBytes(pssh_boxes_hex, &pssh_boxes)) { - LOG(ERROR) << "Cannot parse pssh_hex " << pssh_boxes_hex; - return std::unique_ptr(); - } - - if (!iv_hex.empty()) { - if (!base::HexStringToBytes(iv_hex, &encryption_key->iv)) { - LOG(ERROR) << "Cannot parse iv_hex " << iv_hex; - return std::unique_ptr(); - } - } + encryption_key->key_id = key_id; + encryption_key->key = key; + encryption_key->iv = iv; if (!ProtectionSystemSpecificInfo::ParseBoxes( pssh_boxes.data(), pssh_boxes.size(), diff --git a/packager/media/base/fixed_key_source.h b/packager/media/base/fixed_key_source.h index 0a8ed06b76..944cccfb37 100644 --- a/packager/media/base/fixed_key_source.h +++ b/packager/media/base/fixed_key_source.h @@ -40,20 +40,20 @@ class FixedKeySource : public KeySource { EncryptionKey* key) override; /// @} - /// Creates a new FixedKeySource from the given hex strings. Returns null + /// Creates a new FixedKeySource from the given data. Returns null /// if the strings are invalid. - /// @param key_id_hex is the key id in hex string. - /// @param key_hex is the key in hex string. - /// @param pssh_boxes_hex is the pssh_boxes in hex string. - /// @param iv_hex is the IV in hex string. If not specified, a randomly + /// @param key_id is the key identifier. Must be 16 bytes. + /// @param key is the encryption / decryption key. Must be 16 bytes. + /// @param pssh_boxes is the concatenated pssh boxes. + /// @param iv is the initialization vector. If not specified, a randomly /// generated IV with the default length will be used. - /// Note: GetKey on the created key source will always return the same key - /// for all track types. - static std::unique_ptr CreateFromHexStrings( - const std::string& key_id_hex, - const std::string& key_hex, - const std::string& pssh_boxes_hex, - const std::string& iv_hex); + /// Note: GetKey on the created key source will always return the same key for + /// all track types. + static std::unique_ptr Create( + const std::vector& key_id, + const std::vector& key, + const std::vector& pssh_boxes, + const std::vector& iv); protected: // Allow default constructor for mock key sources. diff --git a/packager/media/base/fixed_key_source_unittest.cc b/packager/media/base/fixed_key_source_unittest.cc index 9f5aa4b8cb..e86f469f60 100644 --- a/packager/media/base/fixed_key_source_unittest.cc +++ b/packager/media/base/fixed_key_source_unittest.cc @@ -43,13 +43,19 @@ const char kDefaultPsshBoxHex[] = "00000001" "0101020305080d1522375990e9000000" "00000000"; + +std::vector HexStringToVector(const std::string& str) { + std::vector vec; + CHECK(base::HexStringToBytes(str, &vec)); + return vec; +} } -TEST(FixedKeySourceTest, CreateFromHexStrings_Succes) { +TEST(FixedKeySourceTest, Success) { std::string pssh_boxes = std::string(kPsshBox1Hex) + kPsshBox2Hex; - std::unique_ptr key_source = - FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, pssh_boxes, - kIvHex); + std::unique_ptr key_source = FixedKeySource::Create( + HexStringToVector(kKeyIdHex), HexStringToVector(kKeyHex), + HexStringToVector(pssh_boxes), HexStringToVector(kIvHex)); ASSERT_NE(nullptr, key_source); EncryptionKey key; @@ -64,9 +70,10 @@ TEST(FixedKeySourceTest, CreateFromHexStrings_Succes) { EXPECT_HEX_EQ(kPsshBox2Hex, key.key_system_info[1].CreateBox()); } -TEST(FixedKeySourceTest, CreateFromHexStrings_EmptyPssh) { - std::unique_ptr key_source = - FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", kIvHex); +TEST(FixedKeySourceTest, EmptyPssh) { + std::unique_ptr key_source = FixedKeySource::Create( + HexStringToVector(kKeyIdHex), HexStringToVector(kKeyHex), + std::vector(), HexStringToVector(kIvHex)); ASSERT_NE(nullptr, key_source); EncryptionKey key; @@ -80,20 +87,17 @@ TEST(FixedKeySourceTest, CreateFromHexStrings_EmptyPssh) { EXPECT_HEX_EQ(kDefaultPsshBoxHex, key.key_system_info[0].CreateBox()); } -TEST(FixedKeySourceTest, CreateFromHexStrings_Failure) { - std::unique_ptr key_source = - FixedKeySource::CreateFromHexStrings(kKeyIdHex, "invalid_hex_value", - kPsshBox1Hex, kIvHex); - EXPECT_EQ(nullptr, key_source); - +TEST(FixedKeySourceTest, Failure) { // Invalid key id size. - key_source = FixedKeySource::CreateFromHexStrings("000102030405", kKeyHex, - kPsshBox1Hex, kIvHex); + std::unique_ptr key_source = FixedKeySource::Create( + HexStringToVector("000102030405"), HexStringToVector(kKeyHex), + HexStringToVector(kPsshBox1Hex), HexStringToVector(kIvHex)); EXPECT_EQ(nullptr, key_source); // Invalid pssh box. - key_source = FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, - "000102030405", kIvHex); + key_source = FixedKeySource::Create( + HexStringToVector(kKeyIdHex), HexStringToVector(kKeyHex), + HexStringToVector("000102030405"), HexStringToVector(kIvHex)); EXPECT_EQ(nullptr, key_source); } diff --git a/packager/media/base/playready_key_source.cc b/packager/media/base/playready_key_source.cc index bbca55c362..8094d3979e 100644 --- a/packager/media/base/playready_key_source.cc +++ b/packager/media/base/playready_key_source.cc @@ -182,17 +182,11 @@ PlayReadyKeySource::PlayReadyKeySource( PlayReadyKeySource::~PlayReadyKeySource() {} std::unique_ptr PlayReadyKeySource::CreateFromKeyAndKeyId( - const std::string& key_id_hex, const std::string& key_hex) { + const std::vector& key_id, + const std::vector& key) { std::unique_ptr encryption_key(new EncryptionKey); - if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) { - LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex; - return std::unique_ptr(); - } - std::vector key; - if (!base::HexStringToBytes(key_hex, &encryption_key->key)) { - LOG(ERROR) << "Cannot parse key_hex " << key_hex; - return std::unique_ptr(); - } + encryption_key->key_id = key_id; + encryption_key->key = key; std::vector pssh_data; Status status = GeneratePlayReadyPsshData( encryption_key->key_id, encryption_key->key, &pssh_data); diff --git a/packager/media/base/playready_key_source.h b/packager/media/base/playready_key_source.h index 90b9fb5f87..778ecf4091 100644 --- a/packager/media/base/playready_key_source.h +++ b/packager/media/base/playready_key_source.h @@ -51,14 +51,13 @@ class PlayReadyKeySource : public KeySource { /// @} virtual Status FetchKeysWithProgramIdentifier(const std::string& program_identifier); - /// Creates a new PlayReadyKeySource from the hex string information. + /// Creates a new PlayReadyKeySource from the given data. /// Returns null if the strings are invalid. - /// @param key_id_hex is the key id in hex string. - /// @param key_hex is the key in hex string. /// Note: GetKey on the created key source will always return the same key /// for all track types. static std::unique_ptr CreateFromKeyAndKeyId( - const std::string& key_id_hex, const std::string& key_hex); + const std::vector& key_id, + const std::vector& key); /// Sets the Certificate Authority file for validating self-signed certificates. void SetCaFile(const std::string& ca_file) { ca_file_ = ca_file; diff --git a/packager/media/base/request_signer.cc b/packager/media/base/request_signer.cc index e3800528e7..0f62d23d0e 100644 --- a/packager/media/base/request_signer.cc +++ b/packager/media/base/request_signer.cc @@ -8,7 +8,6 @@ #include "packager/base/logging.h" #include "packager/base/sha1.h" -#include "packager/base/strings/string_number_conversions.h" #include "packager/media/base/aes_encryptor.h" #include "packager/media/base/rsa_key.h" @@ -26,20 +25,10 @@ AesRequestSigner::AesRequestSigner(const std::string& signer_name, } AesRequestSigner::~AesRequestSigner() {} -AesRequestSigner* AesRequestSigner::CreateSigner(const std::string& signer_name, - const std::string& aes_key_hex, - const std::string& iv_hex) { - std::vector aes_key; - if (!base::HexStringToBytes(aes_key_hex, &aes_key)) { - LOG(ERROR) << "Failed to convert hex string to bytes: " << aes_key_hex; - return NULL; - } - std::vector iv; - if (!base::HexStringToBytes(iv_hex, &iv)) { - LOG(ERROR) << "Failed to convert hex string to bytes: " << iv_hex; - return NULL; - } - +AesRequestSigner* AesRequestSigner::CreateSigner( + const std::string& signer_name, + const std::vector& aes_key, + const std::vector& iv) { std::unique_ptr encryptor( new AesCbcEncryptor(kPkcs5Padding, AesCryptor::kUseConstantIv)); if (!encryptor->InitializeWithIv(aes_key, iv)) diff --git a/packager/media/base/request_signer.h b/packager/media/base/request_signer.h index b69818e1b5..a89ee153d9 100644 --- a/packager/media/base/request_signer.h +++ b/packager/media/base/request_signer.h @@ -9,6 +9,7 @@ #include #include +#include #include "packager/base/macros.h" @@ -45,11 +46,11 @@ class AesRequestSigner : public RequestSigner { public: ~AesRequestSigner() override; - /// Create an AesSigner object from key and iv in hex. + /// Create an AesSigner object from key and iv. /// @return The created AesRequestSigner object on success, NULL otherwise. static AesRequestSigner* CreateSigner(const std::string& signer_name, - const std::string& aes_key_hex, - const std::string& iv_hex); + const std::vector& aes_key, + const std::vector& iv); /// RequestSigner implementation override. bool GenerateSignature(const std::string& message, diff --git a/packager/media/formats/mp2t/ts_segmenter.cc b/packager/media/formats/mp2t/ts_segmenter.cc index 0a36e84306..7d5209590b 100644 --- a/packager/media/formats/mp2t/ts_segmenter.cc +++ b/packager/media/formats/mp2t/ts_segmenter.cc @@ -8,13 +8,9 @@ #include -#include "packager/media/base/aes_encryptor.h" -#include "packager/media/base/key_source.h" #include "packager/media/base/muxer_util.h" #include "packager/media/base/status.h" -#include "packager/media/base/video_stream_info.h" #include "packager/media/event/muxer_listener.h" -#include "packager/media/event/progress_listener.h" namespace shaka { namespace media { diff --git a/packager/packager.gyp b/packager/packager.gyp index 46e2730243..3f50052a5c 100644 --- a/packager/packager.gyp +++ b/packager/packager.gyp @@ -56,6 +56,8 @@ 'app/crypto_flags.h', 'app/fixed_key_encryption_flags.cc', 'app/fixed_key_encryption_flags.h', + 'app/gflags_hex_bytes.cc', + 'app/gflags_hex_bytes.h', 'app/hls_flags.cc', 'app/hls_flags.h', 'app/mpd_flags.cc', diff --git a/packager/packager.h b/packager/packager.h index c9a78337e4..e2f1aa8b75 100644 --- a/packager/packager.h +++ b/packager/packager.h @@ -150,9 +150,9 @@ struct WidevineSigner { SigningKeyType signing_key_type = SigningKeyType::kNone; struct { /// AES signing key. - std::string key; + std::vector key; /// AES signing IV. - std::string iv; + std::vector iv; } aes; struct { /// RSA signing private key. @@ -201,24 +201,24 @@ struct PlayreadyEncryptionParams { // TODO(kqyang): move raw playready key generation to RawKey. /// Provides a raw Playready KeyId. - std::string key_id; + std::vector key_id; /// Provides a raw Playready Key. - std::string key; + std::vector key; }; /// Raw key encryption parameters, i.e. with key parameters provided. struct RawKeyEncryptionParams { /// An optional initialization vector. If not provided, a random `iv` will be /// generated. Note that this parameter should only be used during testing. - std::string iv; + std::vector iv; /// Inject a custom `pssh` or multiple concatenated `psshs`. If not provided, /// a common system pssh will be generated. - std::string pssh; + std::vector pssh; using StreamLabel = std::string; struct KeyPair { - std::string key_id; - std::string key; + std::vector key_id; + std::vector key; }; /// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the /// default `KeyPair`, which applies to all the `StreamLabels` not present in @@ -324,8 +324,8 @@ struct WidevineDecryptionParams { struct RawKeyDecryptionParams { using StreamLabel = std::string; struct KeyPair { - std::string key_id; - std::string key; + std::vector key_id; + std::vector key; }; /// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the /// default `KeyPair`, which applies to all the `StreamLabels` not present in diff --git a/packager/packager_test.cc b/packager/packager_test.cc index ac727f3331..36fc349b3c 100644 --- a/packager/packager_test.cc +++ b/packager/packager_test.cc @@ -9,6 +9,7 @@ #include "packager/base/files/file_util.h" #include "packager/base/logging.h" #include "packager/base/path_service.h" +#include "packager/base/strings/string_number_conversions.h" #include "packager/packager.h" namespace shaka { @@ -67,8 +68,11 @@ class PackagerTest : public ::testing::Test { packaging_params.encryption_params.clear_lead_in_seconds = kClearLeadInSeconds; packaging_params.encryption_params.key_provider = KeyProvider::kRawKey; - packaging_params.encryption_params.raw_key.key_map[""].key_id = kKeyIdHex; - packaging_params.encryption_params.raw_key.key_map[""].key = kKeyHex; + CHECK(base::HexStringToBytes( + kKeyIdHex, + &packaging_params.encryption_params.raw_key.key_map[""].key_id)); + CHECK(base::HexStringToBytes( + kKeyHex, &packaging_params.encryption_params.raw_key.key_map[""].key)); return packaging_params; }