Move hex string out of packager.h

Also added validation failure tests in packager_test.py.

Change-Id: I6697a3138d57889110250404205536dd5cd53cd0
This commit is contained in:
KongQun Yang 2017-06-14 16:18:16 -07:00
parent abbd495ad4
commit 03889e6465
25 changed files with 520 additions and 304 deletions

View File

@ -16,17 +16,19 @@ DEFINE_bool(enable_fixed_key_encryption,
DEFINE_bool(enable_fixed_key_decryption, DEFINE_bool(enable_fixed_key_decryption,
false, false,
"Enable decryption with fixed key."); "Enable decryption with fixed key.");
DEFINE_string(key_id, "", "Key id in hex string format."); DEFINE_hex_bytes(key_id, "", "Key id in hex string format.");
DEFINE_string(key, "", "Key in hex string format."); DEFINE_hex_bytes(key, "", "Key in hex string format.");
DEFINE_string(iv, 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."); "IV in hex string format. If not specified, a random IV will be "
DEFINE_string(pssh, "generated. This flag should only be used for testing.");
"", DEFINE_hex_bytes(
"One or more PSSH boxes in hex string format. If not specified, " pssh,
"will generate a v1 common PSSH box as specified in " "",
"https://goo.gl/s8RIhr."); "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 { namespace shaka {
@ -38,20 +40,20 @@ bool ValidateFixedCryptoFlags() {
const char fixed_crypto_label[] = "--enable_fixed_key_encryption/decryption"; const char fixed_crypto_label[] = "--enable_fixed_key_encryption/decryption";
// --key_id and --key are associated with --enable_fixed_key_encryption and // --key_id and --key are associated with --enable_fixed_key_encryption and
// --enable_fixed_key_decryption. // --enable_fixed_key_decryption.
if (!ValidateFlag( if (!ValidateFlag("key_id", FLAGS_key_id_bytes, fixed_crypto, false,
"key_id", FLAGS_key_id, fixed_crypto, false, fixed_crypto_label)) { fixed_crypto_label)) {
success = false; success = false;
} }
if (!ValidateFlag( if (!ValidateFlag("key", FLAGS_key_bytes, fixed_crypto, false,
"key", FLAGS_key, fixed_crypto, false, fixed_crypto_label)) { fixed_crypto_label)) {
success = false; success = false;
} }
if (!ValidateFlag("iv", FLAGS_iv, FLAGS_enable_fixed_key_encryption, true, if (!ValidateFlag("iv", FLAGS_iv_bytes, FLAGS_enable_fixed_key_encryption,
"--enable_fixed_key_encryption")) { true, "--enable_fixed_key_encryption")) {
success = false; success = false;
} }
if (!FLAGS_iv.empty()) { if (!FLAGS_iv_bytes.empty()) {
if (FLAGS_iv.size() != 8 * 2 && FLAGS_iv.size() != 16 * 2) { if (FLAGS_iv_bytes.size() != 8 && FLAGS_iv_bytes.size() != 16) {
PrintError( PrintError(
"--iv should be either 8 bytes (16 hex digits) or 16 bytes (32 hex " "--iv should be either 8 bytes (16 hex digits) or 16 bytes (32 hex "
"digits)."); "digits).");
@ -60,11 +62,8 @@ bool ValidateFixedCryptoFlags() {
} }
// --pssh is associated with --enable_fix_key_encryption. // --pssh is associated with --enable_fix_key_encryption.
if (!ValidateFlag("pssh", if (!ValidateFlag("pssh", FLAGS_pssh_bytes, FLAGS_enable_fixed_key_encryption,
FLAGS_pssh, true, "--enable_fixed_key_encryption")) {
FLAGS_enable_fixed_key_encryption,
true,
"--enable_fixed_key_encryption")) {
success = false; success = false;
} }
return success; return success;

View File

@ -11,13 +11,15 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "packager/app/gflags_hex_bytes.h"
// TODO(kqyang): s/fixed/raw/. // TODO(kqyang): s/fixed/raw/.
DECLARE_bool(enable_fixed_key_encryption); DECLARE_bool(enable_fixed_key_encryption);
DECLARE_bool(enable_fixed_key_decryption); DECLARE_bool(enable_fixed_key_decryption);
DECLARE_string(key_id); DECLARE_hex_bytes(key_id);
DECLARE_string(key); DECLARE_hex_bytes(key);
DECLARE_string(iv); DECLARE_hex_bytes(iv);
DECLARE_string(pssh); DECLARE_hex_bytes(pssh);
namespace shaka { namespace shaka {

View File

@ -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<uint8_t>* value_bytes) {
std::vector<uint8_t> 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

View File

@ -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 <gflags/gflags.h>
#include <string>
#include <vector>
namespace shaka {
bool ValidateHexString(const char* flagname,
const std::string& value,
std::vector<uint8_t>* 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<uint8_t> 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<uint8_t> 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_

View File

@ -97,6 +97,24 @@ enum ExitStatus {
kInternalError, 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<PackagingParams> GetPackagingParams() { base::Optional<PackagingParams> GetPackagingParams() {
PackagingParams packaging_params; PackagingParams packaging_params;
@ -143,33 +161,10 @@ base::Optional<PackagingParams> GetPackagingParams() {
widevine.key_server_url = FLAGS_key_server_url; widevine.key_server_url = FLAGS_key_server_url;
widevine.include_common_pssh = FLAGS_include_common_pssh; widevine.include_common_pssh = FLAGS_include_common_pssh;
if (!base::HexStringToBytes(FLAGS_content_id, &widevine.content_id)) { widevine.content_id = FLAGS_content_id_bytes;
LOG(ERROR) << "Invalid content_id hex string specified.";
return base::nullopt;
}
widevine.policy = FLAGS_policy; widevine.policy = FLAGS_policy;
widevine.signer.signer_name = FLAGS_signer; if (!GetWidevineSigner(&widevine.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.";
return base::nullopt; 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; break;
} }
case KeyProvider::kPlayready: { case KeyProvider::kPlayready: {
@ -182,19 +177,18 @@ base::Optional<PackagingParams> GetPackagingParams() {
FLAGS_client_cert_private_key_file; FLAGS_client_cert_private_key_file;
playready.client_cert_private_key_password = playready.client_cert_private_key_password =
FLAGS_client_cert_private_key_password; FLAGS_client_cert_private_key_password;
playready.key_id = FLAGS_playready_key_id; playready.key_id = FLAGS_playready_key_id_bytes;
playready.key = FLAGS_playready_key; playready.key = FLAGS_playready_key_bytes;
break; break;
} }
case KeyProvider::kRawKey: { case KeyProvider::kRawKey: {
RawKeyEncryptionParams& raw_key = encryption_params.raw_key; RawKeyEncryptionParams& raw_key = encryption_params.raw_key;
raw_key.iv = FLAGS_iv; raw_key.iv = FLAGS_iv_bytes;
raw_key.pssh = FLAGS_pssh; raw_key.pssh = FLAGS_pssh_bytes;
// An empty TrackType specifies the default KeyPair. // An empty StreamLabel specifies the default KeyPair.
RawKeyEncryptionParams::KeyPair& key_pair = raw_key.key_map[""]; RawKeyEncryptionParams::KeyPair& key_pair = raw_key.key_map[""];
// TODO(kqyang): Take care of hex conversion here. key_pair.key_id = FLAGS_key_id_bytes;
key_pair.key_id = FLAGS_key_id; key_pair.key = FLAGS_key_bytes;
key_pair.key = FLAGS_key;
break; break;
} }
case KeyProvider::kNone: case KeyProvider::kNone:
@ -220,42 +214,20 @@ base::Optional<PackagingParams> GetPackagingParams() {
case KeyProvider::kWidevine: { case KeyProvider::kWidevine: {
WidevineDecryptionParams& widevine = decryption_params.widevine; WidevineDecryptionParams& widevine = decryption_params.widevine;
widevine.key_server_url = FLAGS_key_server_url; widevine.key_server_url = FLAGS_key_server_url;
if (!GetWidevineSigner(&widevine.signer))
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.";
return base::nullopt; 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; break;
} }
case KeyProvider::kRawKey: { case KeyProvider::kRawKey: {
RawKeyDecryptionParams& raw_key = decryption_params.raw_key; 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[""]; RawKeyDecryptionParams::KeyPair& key_pair = raw_key.key_map[""];
// TODO(kqyang): Take care of hex conversion here. key_pair.key_id = FLAGS_key_id_bytes;
key_pair.key_id = FLAGS_key_id; key_pair.key = FLAGS_key_bytes;
key_pair.key = FLAGS_key;
break; break;
} }
case KeyProvider::kNone:
case KeyProvider::kPlayready: case KeyProvider::kPlayready:
case KeyProvider::kNone:
break; break;
} }

View File

@ -103,7 +103,7 @@ std::unique_ptr<KeySource> CreateEncryptionKeySource(
const RawKeyEncryptionParams& raw_key = encryption_params.raw_key; const RawKeyEncryptionParams& raw_key = encryption_params.raw_key;
const std::string kDefaultTrackType; const std::string kDefaultTrackType;
// TODO(kqyang): Refactor FixedKeySource. // 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_id,
raw_key.key_map.find("")->second.key, raw_key.pssh, raw_key.iv); raw_key.key_map.find("")->second.key, raw_key.pssh, raw_key.iv);
break; break;
@ -171,9 +171,9 @@ std::unique_ptr<KeySource> CreateDecryptionKeySource(
} }
case KeyProvider::kRawKey: { case KeyProvider::kRawKey: {
const RawKeyDecryptionParams& raw_key = decryption_params.raw_key; const RawKeyDecryptionParams& raw_key = decryption_params.raw_key;
const char kNoPssh[] = ""; const std::vector<uint8_t> kNoPssh;
const char kNoIv[] = ""; const std::vector<uint8_t> kNoIv;
decryption_key_source = FixedKeySource::CreateFromHexStrings( decryption_key_source = FixedKeySource::Create(
raw_key.key_map.find("")->second.key_id, raw_key.key_map.find("")->second.key_id,
raw_key.key_map.find("")->second.key, kNoPssh, kNoIv); raw_key.key_map.find("")->second.key, kNoPssh, kNoIv);
break; break;

View File

@ -16,8 +16,8 @@ DEFINE_bool(enable_playready_encryption,
DEFINE_string(playready_server_url, "", "PlayReady packaging server url."); DEFINE_string(playready_server_url, "", "PlayReady packaging server url.");
DEFINE_string(program_identifier, "", DEFINE_string(program_identifier, "",
"Program identifier for packaging request."); "Program identifier for packaging request.");
DEFINE_string(playready_key_id, "", "PlayReady key id in hex."); DEFINE_hex_bytes(playready_key_id, "", "PlayReady key id in hex.");
DEFINE_string(playready_key, "", "PlayReady key in hex."); DEFINE_hex_bytes(playready_key, "", "PlayReady key in hex.");
DEFINE_string(ca_file, "", DEFINE_string(ca_file, "",
"Absolute path to the Certificate Authority file for the " "Absolute path to the Certificate Authority file for the "
"server cert. PEM format"); "server cert. PEM format");
@ -45,16 +45,16 @@ bool ValidatePRCryptoFlags() {
} }
bool use_packaging = !FLAGS_playready_server_url.empty() && bool use_packaging = !FLAGS_playready_server_url.empty() &&
!FLAGS_program_identifier.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)) { playready_enabled, true, playready_label)) {
success = false; success = false;
} }
if (!ValidateFlag("playready_key", FLAGS_playready_key, if (!ValidateFlag("playready_key", FLAGS_playready_key_bytes,
playready_enabled, true, playready_label)) { playready_enabled, true, playready_label)) {
success = false; success = false;
} }
bool use_fixed_key = !FLAGS_playready_key_id.empty() && bool use_fixed_key = !FLAGS_playready_key_id_bytes.empty() &&
!FLAGS_playready_key.empty(); !FLAGS_playready_key_bytes.empty();
if (playready_enabled && !use_packaging && !use_fixed_key) { if (playready_enabled && !use_packaging && !use_fixed_key) {
PrintError("combination of --playready_server_url and " PrintError("combination of --playready_server_url and "

View File

@ -11,11 +11,13 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "packager/app/gflags_hex_bytes.h"
DECLARE_bool(enable_playready_encryption); DECLARE_bool(enable_playready_encryption);
DECLARE_string(playready_server_url); DECLARE_string(playready_server_url);
DECLARE_string(program_identifier); DECLARE_string(program_identifier);
DECLARE_string(playready_key_id); DECLARE_hex_bytes(playready_key_id);
DECLARE_string(playready_key); DECLARE_hex_bytes(playready_key);
DECLARE_string(ca_file); DECLARE_string(ca_file);
DECLARE_string(client_cert_file); DECLARE_string(client_cert_file);
DECLARE_string(client_cert_private_key_file); DECLARE_string(client_cert_private_key_file);

View File

@ -52,8 +52,9 @@ class PackagerApp(object):
# Put single-quotes around each entry so that things like '$' signs in # Put single-quotes around each entry so that things like '$' signs in
# segment templates won't be interpreted as shell variables. # segment templates won't be interpreted as shell variables.
self.packaging_command_line = ' '.join(["'%s'" % entry for entry in cmd]) self.packaging_command_line = ' '.join(["'%s'" % entry for entry in cmd])
assert 0 == subprocess.call(cmd), ('%s returned non-0 status' % self.packaging_result = subprocess.call(cmd)
self.packaging_command_line) if self.packaging_result != 0:
print '%s returned non-0 status' % self.packaging_command_line
def GetCommandLine(self): def GetCommandLine(self):
return self.packaging_command_line return self.packaging_command_line

View File

@ -42,6 +42,18 @@ class PackagerAppTest(unittest.TestCase):
self.hls_master_playlist_output = self.output_prefix + '.m3u8' self.hls_master_playlist_output = self.output_prefix + '.m3u8'
self.output = None 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): def tearDown(self):
if test_env.options.remove_temp_files_after_test: if test_env.options.remove_temp_files_after_test:
shutil.rmtree(self.tmp_dir) shutil.rmtree(self.tmp_dir)
@ -83,6 +95,7 @@ class PackagerAppTest(unittest.TestCase):
def testPackageFirstStream(self): def testPackageFirstStream(self):
self.packager.Package(self._GetStreams(['0']), self._GetFlags()) 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.output[0], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-v-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-v-golden.mpd')
@ -90,6 +103,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['text'], test_files=['subtitle-english.vtt']), self._GetStreams(['text'], test_files=['subtitle-english.vtt']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'subtitle-english-golden.vtt') self._DiffGold(self.output[0], 'subtitle-english-golden.vtt')
self._DiffGold(self.mpd_output, 'subtitle-english-vtt-golden.mpd') self._DiffGold(self.mpd_output, 'subtitle-english-vtt-golden.mpd')
@ -97,6 +111,7 @@ class PackagerAppTest(unittest.TestCase):
def testPackageAudioVideo(self): def testPackageAudioVideo(self):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video']), self._GetFlags()) 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[0], 'bear-640x360-a-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-av-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-av-golden.mpd')
@ -105,6 +120,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']), self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.output[2], 'bear-640x360-v-trick-1-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', self._GetStreams(['audio', 'video', 'video,trick_play_factor=1',
'video,trick_play_factor=2']), 'video,trick_play_factor=2']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.output[2], 'bear-640x360-v-trick-1-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', self._GetStreams(['audio', 'video', 'video,trick_play_factor=2',
'video,trick_play_factor=1']), 'video,trick_play_factor=1']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4') self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.output[2], 'bear-640x360-v-trick-2-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.packager.Package(
self._GetStreams(['audio', 'video'], language_override='por-BR'), self._GetStreams(['audio', 'video'], language_override='por-BR'),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-640x360-a-por-golden.mp4') self._DiffGold(self.output[0], 'bear-640x360-a-por-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-av-por-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-av-por-golden.mpd')
@ -148,6 +167,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video'], language_override='por-BR'), self._GetStreams(['audio', 'video'], language_override='por-BR'),
self._GetFlags()) 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[0], 'bear-640x360-a-por-BR-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-av-por-BR-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-av-por-BR-golden.mpd')
@ -157,6 +177,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetStreams( self._GetStreams(
['audio'], test_files=['bear-640x360-aac_he-silent_right.mp4']), ['audio'], test_files=['bear-640x360-aac_he-silent_right.mp4']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], self._DiffGold(self.output[0],
'bear-640x360-aac_he-silent_right-golden.mp4') 'bear-640x360-aac_he-silent_right-golden.mp4')
self._DiffGold(self.mpd_output, self._DiffGold(self.mpd_output,
@ -168,6 +189,7 @@ class PackagerAppTest(unittest.TestCase):
text_stream = self._GetStreams(['text'], text_stream = self._GetStreams(['text'],
test_files=['subtitle-english.vtt']) test_files=['subtitle-english.vtt'])
self.packager.Package(audio_video_streams + text_stream, self._GetFlags()) 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[0], 'bear-640x360-a-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4') self._DiffGold(self.output[1], 'bear-640x360-v-golden.mp4')
self._DiffGold(self.output[2], 'subtitle-english-golden.vtt') self._DiffGold(self.output[2], 'subtitle-english-golden.vtt')
@ -181,6 +203,7 @@ class PackagerAppTest(unittest.TestCase):
live=True, live=True,
test_files=['bear-640x360.ts']), test_files=['bear-640x360.ts']),
self._GetFlags(output_hls=True)) self._GetFlags(output_hls=True))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffLiveGold(self.output[0], self._DiffLiveGold(self.output[0],
'bear-640x360-a-golden', 'bear-640x360-a-golden',
output_format='ts') output_format='ts')
@ -200,6 +223,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='webm', output_format='webm',
test_files=['bear-640x360.webm']), test_files=['bear-640x360.webm']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-640x360-vp8-golden.webm') self._DiffGold(self.output[0], 'bear-640x360-vp8-golden.webm')
self._DiffGold(self.mpd_output, 'bear-640x360-vp8-webm-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-vp8-webm-golden.mpd')
@ -209,6 +233,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='webm', output_format='webm',
test_files=['bear-320x240-vp9-opus.webm']), test_files=['bear-320x240-vp9-opus.webm']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-320x240-opus-golden.webm') self._DiffGold(self.output[0], 'bear-320x240-opus-golden.webm')
self._DiffGold(self.output[1], 'bear-320x240-vp9-golden.webm') self._DiffGold(self.output[1], 'bear-320x240-vp9-golden.webm')
self._DiffGold(self.mpd_output, 'bear-320x240-vp9-opus-webm-golden.mpd') self._DiffGold(self.mpd_output, 'bear-320x240-vp9-opus-webm-golden.mpd')
@ -219,6 +244,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='webm', output_format='webm',
test_files=['bear-vp9-blockgroup.webm']), test_files=['bear-vp9-blockgroup.webm']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-vp9-blockgroup-golden.webm') self._DiffGold(self.output[0], 'bear-vp9-blockgroup-golden.webm')
def testPackageVorbisWebm(self): def testPackageVorbisWebm(self):
@ -227,6 +253,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='webm', output_format='webm',
test_files=['bear-320x240-audio-only.webm']), test_files=['bear-320x240-audio-only.webm']),
self._GetFlags()) self._GetFlags())
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-320x240-vorbis-golden.webm') self._DiffGold(self.output[0], 'bear-320x240-vorbis-golden.webm')
self._DiffGold(self.mpd_output, 'bear-320x240-vorbis-webm-golden.mpd') self._DiffGold(self.mpd_output, 'bear-320x240-vorbis-webm-golden.mpd')
@ -234,16 +261,84 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True)) 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[0], 'bear-640x360-a-cenc-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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._DiffGold(self.mpd_output, 'bear-640x360-av-cenc-golden.mpd')
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4') self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
self._VerifyDecryption(self.output[1], 'bear-640x360-v-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): def testPackageWithEncryptionOfOnlyVideoStream(self):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio,skip_encryption=1', 'video']), self._GetStreams(['audio,skip_encryption=1', 'video']),
self._GetFlags(encryption=True)) 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[0], 'bear-640x360-a-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-cenc-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') 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.packager.Package(
self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']), self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']),
self._GetFlags(encryption=True)) 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[0], 'bear-640x360-a-cenc-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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') 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', self._GetStreams(['audio', 'video', 'video,trick_play_factor=1',
'video,trick_play_factor=2']), 'video,trick_play_factor=2']),
self._GetFlags(encryption=True)) 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[0], 'bear-640x360-a-cenc-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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') 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.packager.Package(
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, clear_lead=0)) self._GetFlags(encryption=True, clear_lead=0))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], self._DiffGold(self.output[0],
'bear-640x360-a-cenc-no-clear-lead-golden.mp4') 'bear-640x360-a-cenc-no-clear-lead-golden.mp4')
self._DiffGold(self.output[1], self._DiffGold(self.output[1],
@ -296,6 +394,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, include_pssh_in_stream=False)) 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[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.output[1], 'bear-640x360-v-cenc-no-pssh-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-av-cenc-no-pssh-golden.mpd') 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._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, self._GetFlags(encryption=True,
protection_scheme='cbc1')) 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[0], 'bear-640x360-a-cbc1-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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') self._DiffGold(self.mpd_output, 'bear-640x360-av-cbc1-golden.mpd')
@ -318,6 +418,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, self._GetFlags(encryption=True,
protection_scheme='cens')) 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[0], 'bear-640x360-a-cens-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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') self._DiffGold(self.mpd_output, 'bear-640x360-av-cens-golden.mpd')
@ -329,6 +430,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, self._GetFlags(encryption=True,
protection_scheme='cbcs')) 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[0], 'bear-640x360-a-cbcs-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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') self._DiffGold(self.mpd_output, 'bear-640x360-av-cbcs-golden.mpd')
@ -341,6 +443,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='webm', output_format='webm',
test_files=['bear-320x180-vp9-altref.webm']), test_files=['bear-320x180-vp9-altref.webm']),
self._GetFlags(encryption=True)) self._GetFlags(encryption=True))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], 'bear-320x180-vp9-altref-enc-golden.webm') self._DiffGold(self.output[0], 'bear-320x180-vp9-altref-enc-golden.webm')
self._VerifyDecryption(self.output[0], self._VerifyDecryption(self.output[0],
'bear-320x180-vp9-altref-dec-golden.webm') 'bear-320x180-vp9-altref-dec-golden.webm')
@ -351,6 +454,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='webm', output_format='webm',
test_files=['bear-320x180-vp9-altref.webm']), test_files=['bear-320x180-vp9-altref.webm']),
self._GetFlags(encryption=True, vp9_subsample_encryption=False)) self._GetFlags(encryption=True, vp9_subsample_encryption=False))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[0], self._DiffGold(self.output[0],
'bear-320x180-vp9-fullsample-enc-golden.webm') 'bear-320x180-vp9-fullsample-enc-golden.webm')
self._VerifyDecryption(self.output[0], self._VerifyDecryption(self.output[0],
@ -364,6 +468,7 @@ class PackagerAppTest(unittest.TestCase):
live=True, live=True,
test_files=['bear-640x360.ts']), test_files=['bear-640x360.ts']),
self._GetFlags(encryption=True, output_hls=True)) self._GetFlags(encryption=True, output_hls=True))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffLiveGold(self.output[0], self._DiffLiveGold(self.output[0],
'bear-640x360-a-enc-golden', 'bear-640x360-a-enc-golden',
output_format='ts') output_format='ts')
@ -380,6 +485,7 @@ class PackagerAppTest(unittest.TestCase):
'bear-640x360-v-enc-golden.m3u8') 'bear-640x360-v-enc-golden.m3u8')
def testPackageAvcTsWithEncryptionExerciseEmulationPrevention(self): def testPackageAvcTsWithEncryptionExerciseEmulationPrevention(self):
self.encryption_key = 'ad7e9786def9159db6724be06dfcde7a'
# Currently we only support live packaging for ts. # Currently we only support live packaging for ts.
self.packager.Package( self.packager.Package(
self._GetStreams( self._GetStreams(
@ -389,8 +495,8 @@ class PackagerAppTest(unittest.TestCase):
test_files=['sintel-1024x436.mp4']), test_files=['sintel-1024x436.mp4']),
self._GetFlags( self._GetFlags(
encryption=True, encryption=True,
encryption_key='ad7e9786def9159db6724be06dfcde7a',
output_hls=True)) output_hls=True))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffLiveGold(self.output[0], self._DiffLiveGold(self.output[0],
'sintel-1024x436-v-enc-golden', 'sintel-1024x436-v-enc-golden',
output_format='ts') output_format='ts')
@ -406,6 +512,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='webm', output_format='webm',
test_files=['bear-640x360.webm']), test_files=['bear-640x360.webm']),
self._GetFlags(encryption=True)) 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.output[0], 'bear-640x360-vp8-cenc-golden.webm')
self._DiffGold(self.mpd_output, 'bear-640x360-vp8-cenc-webm-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-vp8-cenc-webm-golden.mpd')
self._VerifyDecryption(self.output[0], 'bear-640x360-vp8-golden.webm') self._VerifyDecryption(self.output[0], 'bear-640x360-vp8-golden.webm')
@ -415,6 +522,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetStreams(['video'], self._GetStreams(['video'],
test_files=['bear-640x360-hevc.mp4']), test_files=['bear-640x360-hevc.mp4']),
self._GetFlags(encryption=True)) 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.output[0], 'bear-640x360-hevc-cenc-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-hevc-cenc-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-hevc-cenc-golden.mpd')
self._VerifyDecryption(self.output[0], 'bear-640x360-hevc-golden.mp4') self._VerifyDecryption(self.output[0], 'bear-640x360-hevc-golden.mp4')
@ -425,6 +533,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='mp4', output_format='mp4',
test_files=['bear-640x360.webm']), test_files=['bear-640x360.webm']),
self._GetFlags(encryption=True)) 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.output[0], 'bear-640x360-vp8-cenc-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-vp8-cenc-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-vp8-cenc-golden.mpd')
self._VerifyDecryption(self.output[0], 'bear-640x360-vp8-golden.mp4') self._VerifyDecryption(self.output[0], 'bear-640x360-vp8-golden.mp4')
@ -435,6 +544,7 @@ class PackagerAppTest(unittest.TestCase):
output_format='mp4', output_format='mp4',
test_files=['bear-320x240-vp9-opus.webm']), test_files=['bear-320x240-vp9-opus.webm']),
self._GetFlags(encryption=True)) 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[0], 'bear-320x240-opus-cenc-golden.mp4')
self._DiffGold(self.output[1], 'bear-320x240-vp9-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') 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') self._VerifyDecryption(self.output[1], 'bear-320x240-vp9-golden.mp4')
def testPackageWvmInput(self): def testPackageWvmInput(self):
self.encryption_key = '9248d245390e0a49d483ba9b43fc69c3'
self.packager.Package( self.packager.Package(
self._GetStreams( self._GetStreams(
['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']), ['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']),
self._GetFlags( self._GetFlags(decryption=True))
decryption=True, encryption_key='9248d245390e0a49d483ba9b43fc69c3')) self.assertEqual(self.packager.packaging_result, 0)
# Output timescale is 90000. # Output timescale is 90000.
self._DiffGold(self.output[0], 'bear-320x180-v-wvm-golden.mp4') self._DiffGold(self.output[0], 'bear-320x180-v-wvm-golden.mp4')
self._DiffGold(self.output[1], 'bear-320x180-a-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.' '--strip_parameter_set_nalus flag.'
) )
def testPackageWvmInputWithoutStrippingParameterSetNalus(self): def testPackageWvmInputWithoutStrippingParameterSetNalus(self):
self.encryption_key = '9248d245390e0a49d483ba9b43fc69c3'
self.packager.Package( self.packager.Package(
self._GetStreams( self._GetStreams(
['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']), ['0', '1', '2', '3'], test_files=['bear-multi-configs.wvm']),
self._GetFlags( self._GetFlags(strip_parameter_set_nalus=False, decryption=True))
strip_parameter_set_nalus=False, self.assertEqual(self.packager.packaging_result, 0)
decryption=True,
encryption_key='9248d245390e0a49d483ba9b43fc69c3'))
# Output timescale is 90000. # Output timescale is 90000.
self._DiffGold(self.output[0], 'bear-320x180-avc3-wvm-golden.mp4') self._DiffGold(self.output[0], 'bear-320x180-avc3-wvm-golden.mp4')
self._DiffGold(self.output[1], 'bear-320x180-a-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.packager.Package(
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, random_iv=True)) 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[0], 'is_encrypted: true')
self._AssertStreamInfo(self.output[1], '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 # 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.packager.Package(
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, use_fake_clock=False)) 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[0], 'is_encrypted: true')
self._AssertStreamInfo(self.output[1], '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 # 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.packager.Package(
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, dash_if_iop=False)) 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[0], 'bear-640x360-a-cenc-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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') 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.packager.Package(
self._GetStreams(['audio', 'video']), self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True, output_media_info=True)) 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[0], 'bear-640x360-a-cenc-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-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') self._DiffMediaInfoGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4')
@ -528,6 +642,7 @@ class PackagerAppTest(unittest.TestCase):
def testPackageWithLiveProfile(self): def testPackageWithLiveProfile(self):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video'], live=True), self._GetFlags()) 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[0], 'bear-640x360-a-live-golden')
self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-golden')
self._DiffLiveMpdGold(self.mpd_output, 'bear-640x360-av-live-golden.mpd') self._DiffLiveMpdGold(self.mpd_output, 'bear-640x360-av-live-golden.mpd')
@ -536,6 +651,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video'], live=True), self._GetStreams(['audio', 'video'], live=True),
self._GetFlags(generate_static_mpd=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[0], 'bear-640x360-a-live-golden')
self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-golden')
self._DiffGold(self.mpd_output, 'bear-640x360-av-live-static-golden.mpd') self._DiffGold(self.mpd_output, 'bear-640x360-av-live-static-golden.mpd')
@ -544,6 +660,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video'], live=True), self._GetStreams(['audio', 'video'], live=True),
self._GetFlags(encryption=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[0], 'bear-640x360-a-live-cenc-golden')
self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden')
self._DiffLiveMpdGold(self.mpd_output, self._DiffLiveMpdGold(self.mpd_output,
@ -553,6 +670,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video'], live=True), self._GetStreams(['audio', 'video'], live=True),
self._GetFlags(encryption=True, dash_if_iop=False)) 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[0], 'bear-640x360-a-live-cenc-golden')
self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden') self._DiffLiveGold(self.output[1], 'bear-640x360-v-live-cenc-golden')
self._DiffLiveMpdGold(self.mpd_output, self._DiffLiveMpdGold(self.mpd_output,
@ -565,6 +683,7 @@ class PackagerAppTest(unittest.TestCase):
test_files=['bear-1280x720.mp4', 'bear-640x360.mp4', test_files=['bear-1280x720.mp4', 'bear-640x360.mp4',
'bear-320x180.mp4']), 'bear-320x180.mp4']),
self._GetFlags(encryption=True)) 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[2], 'bear-640x360-a-live-cenc-golden')
self._DiffLiveGold(self.output[3], 'bear-640x360-v-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 # Mpd cannot be validated right now since we don't generate determinstic
@ -575,6 +694,7 @@ class PackagerAppTest(unittest.TestCase):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video'], live=True), self._GetStreams(['audio', 'video'], live=True),
self._GetFlags(encryption=True, key_rotation=True)) self._GetFlags(encryption=True, key_rotation=True))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffLiveGold(self.output[0], self._DiffLiveGold(self.output[0],
'bear-640x360-a-live-cenc-rotation-golden') 'bear-640x360-a-live-cenc-rotation-golden')
self._DiffLiveGold(self.output[1], self._DiffLiveGold(self.output[1],
@ -587,6 +707,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetStreams(['audio', 'video'], live=True), self._GetStreams(['audio', 'video'], live=True),
self._GetFlags( self._GetFlags(
encryption=True, key_rotation=True, include_pssh_in_stream=False)) encryption=True, key_rotation=True, include_pssh_in_stream=False))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffLiveGold(self.output[0], self._DiffLiveGold(self.output[0],
'bear-640x360-a-live-cenc-rotation-no-pssh-golden') 'bear-640x360-a-live-cenc-rotation-no-pssh-golden')
self._DiffLiveGold(self.output[1], self._DiffLiveGold(self.output[1],
@ -601,6 +722,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetFlags(encryption=True, self._GetFlags(encryption=True,
key_rotation=True, key_rotation=True,
dash_if_iop=False)) dash_if_iop=False))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffLiveGold(self.output[0], self._DiffLiveGold(self.output[0],
'bear-640x360-a-live-cenc-rotation-golden') 'bear-640x360-a-live-cenc-rotation-golden')
self._DiffLiveGold(self.output[1], self._DiffLiveGold(self.output[1],
@ -612,21 +734,98 @@ class PackagerAppTest(unittest.TestCase):
@unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.') @unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.')
def testWidevineEncryptionWithAes(self): def testWidevineEncryptionWithAes(self):
flags = self._GetFlags(widevine_encryption=True) flags = self._GetFlags(widevine_encryption=True)
flags += ['--aes_signing_key=' + test_env.options.aes_signing_key, flags += [
'--aes_signing_iv=' + test_env.options.aes_signing_iv] '--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.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[0], 'is_encrypted: true')
self._AssertStreamInfo(self.output[1], '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.') @unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.')
def testWidevineEncryptionWithAesAndMultFiles(self): def testWidevineEncryptionWithAesAndMultFiles(self):
flags = self._GetFlags(widevine_encryption=True) flags = self._GetFlags(widevine_encryption=True)
flags += ['--aes_signing_key=' + test_env.options.aes_signing_key, flags += [
'--aes_signing_iv=' + test_env.options.aes_signing_iv] '--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.packager.Package(
self._GetStreams(['audio', 'video'], self._GetStreams(['audio', 'video'],
test_files=['bear-1280x720.mp4', 'bear-640x360.mp4', test_files=['bear-1280x720.mp4', 'bear-640x360.mp4',
'bear-320x180.mp4']), flags) 'bear-320x180.mp4']), flags)
self.assertEqual(self.packager.packaging_result, 0)
with open(self.mpd_output, 'rb') as f: with open(self.mpd_output, 'rb') as f:
print f.read() print f.read()
# TODO(kqyang): Add some validations. # TODO(kqyang): Add some validations.
@ -634,17 +833,25 @@ class PackagerAppTest(unittest.TestCase):
@unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.') @unittest.skipUnless(test_env.has_aes_flags, 'Requires AES credentials.')
def testKeyRotationWithAes(self): def testKeyRotationWithAes(self):
flags = self._GetFlags(widevine_encryption=True, key_rotation=True) flags = self._GetFlags(widevine_encryption=True, key_rotation=True)
flags += ['--aes_signing_key=' + test_env.options.aes_signing_key, flags += [
'--aes_signing_iv=' + test_env.options.aes_signing_iv] '--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.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[0], 'is_encrypted: true')
self._AssertStreamInfo(self.output[1], 'is_encrypted: true') self._AssertStreamInfo(self.output[1], 'is_encrypted: true')
@unittest.skipUnless(test_env.has_rsa_flags, 'Requires RSA credentials.') @unittest.skipUnless(test_env.has_rsa_flags, 'Requires RSA credentials.')
def testWidevineEncryptionWithRsa(self): def testWidevineEncryptionWithRsa(self):
flags = self._GetFlags(widevine_encryption=True) 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.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[0], 'is_encrypted: true')
self._AssertStreamInfo(self.output[1], 'is_encrypted: true') self._AssertStreamInfo(self.output[1], 'is_encrypted: true')
@ -715,8 +922,6 @@ class PackagerAppTest(unittest.TestCase):
protection_scheme=None, protection_scheme=None,
vp9_subsample_encryption=True, vp9_subsample_encryption=True,
decryption=False, decryption=False,
encryption_key='32333435363738393021323334353637',
encryption_iv='3334353637383930',
random_iv=False, random_iv=False,
widevine_encryption=False, widevine_encryption=False,
key_rotation=False, key_rotation=False,
@ -734,21 +939,19 @@ class PackagerAppTest(unittest.TestCase):
if widevine_encryption: if widevine_encryption:
widevine_server_url = ('https://license.uat.widevine.com/cenc' widevine_server_url = ('https://license.uat.widevine.com/cenc'
'/getcontentkey/widevine_test') '/getcontentkey/widevine_test')
flags += ['--enable_widevine_encryption', flags += [
'--key_server_url=' + widevine_server_url, '--enable_widevine_encryption',
'--content_id=3031323334353637', '--signer=widevine_test'] '--key_server_url=' + widevine_server_url,
'--content_id=' + self.widevine_content_id,
]
elif encryption: elif encryption:
flags += ['--enable_fixed_key_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)] '--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 not random_iv:
if test_env.options.encryption_iv: flags.append('--iv=' + self.encryption_iv)
encryption_iv = test_env.options.encryption_iv
flags.append('--iv=' + encryption_iv)
if protection_scheme: if protection_scheme:
flags += ['--protection_scheme', protection_scheme] flags += ['--protection_scheme', protection_scheme]
if not vp9_subsample_encryption: if not vp9_subsample_encryption:
@ -756,8 +959,8 @@ class PackagerAppTest(unittest.TestCase):
if decryption: if decryption:
flags += ['--enable_fixed_key_decryption', flags += ['--enable_fixed_key_decryption',
'--key_id=31323334353637383930313233343536', '--key_id=' + self.encryption_key_id,
'--key=' + encryption_key] '--key=' + self.encryption_key]
if key_rotation: if key_rotation:
flags.append('--crypto_period_duration=1') flags.append('--crypto_period_duration=1')
@ -878,6 +1081,7 @@ class PackagerAppTest(unittest.TestCase):
output_format=output_extension, output_format=output_extension,
test_files=[test_encrypted_file]), test_files=[test_encrypted_file]),
self._GetFlags(decryption=True)) self._GetFlags(decryption=True))
self.assertEqual(self.packager.packaging_result, 0)
self._DiffGold(self.output[-1], golden_clear_file) self._DiffGold(self.output[-1], golden_clear_file)

View File

@ -10,29 +10,8 @@
#include <stdio.h> #include <stdio.h>
#include "packager/base/strings/stringprintf.h"
namespace shaka { 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) { void PrintError(const std::string& error_message) {
fprintf(stderr, "ERROR: %s\n", error_message.c_str()); fprintf(stderr, "ERROR: %s\n", error_message.c_str());
} }

View File

@ -11,8 +11,14 @@
#include <string> #include <string>
#include "packager/base/strings/stringprintf.h"
namespace shaka { 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. /// Validate a flag against the given condition.
/// @param flag_name is the name of the flag. /// @param flag_name is the name of the flag.
/// @param flag_value is the value 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 /// @param label specifies the label associated with the condition. It is used
/// to generate the error message on validation failure. /// to generate the error message on validation failure.
/// @return true on success, false otherwise. /// @return true on success, false otherwise.
template <class FlagType>
bool ValidateFlag(const char* flag_name, bool ValidateFlag(const char* flag_name,
const std::string& flag_value, const FlagType& flag_value,
bool condition, bool condition,
bool optional, bool optional,
const char* label); const char* label) {
if (flag_value.empty()) {
/// Format and print error message. if (!optional && condition) {
/// @param error_message specifies the error message. PrintError(
void PrintError(const std::string& error_message); 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 } // namespace shaka

View File

@ -30,7 +30,7 @@ DEFINE_bool(include_common_pssh,
"https://goo.gl/s8RIhr"); "https://goo.gl/s8RIhr");
DEFINE_string(key_server_url, "", "Key server url. Required for encryption and " DEFINE_string(key_server_url, "", "Key server url. Required for encryption and "
"decryption"); "decryption");
DEFINE_string(content_id, "", "Content Id (hex)."); DEFINE_hex_bytes(content_id, "", "Content Id (hex).");
DEFINE_string(policy, DEFINE_string(policy,
"", "",
"The name of a stored policy, which specifies DRM content " "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." "is higher than max_hd_pixels, but no higher than max_uhd1_pixels."
" Otherwise it is UHD2. Default: 8847360 (4096 x 2160)."); " Otherwise it is UHD2. Default: 8847360 (4096 x 2160).");
DEFINE_string(signer, "", "The name of the signer."); DEFINE_string(signer, "", "The name of the signer.");
DEFINE_string(aes_signing_key, DEFINE_hex_bytes(aes_signing_key,
"", "",
"AES signing key in hex string. --aes_signing_iv is required. " "AES signing key in hex string. --aes_signing_iv is required. "
"Exclusive with --rsa_signing_key_path."); "Exclusive with --rsa_signing_key_path.");
DEFINE_string(aes_signing_iv, DEFINE_hex_bytes(aes_signing_iv, "", "AES signing iv in hex string.");
"",
"AES signing iv in hex string.");
DEFINE_string(rsa_signing_key_path, DEFINE_string(rsa_signing_key_path,
"", "",
"Stores PKCS#1 RSA private key for request signing. Exclusive " "Stores PKCS#1 RSA private key for request signing. Exclusive "
@ -67,6 +65,9 @@ DEFINE_int32(crypto_period_duration,
"rotation is enabled."); "rotation is enabled.");
namespace shaka { namespace shaka {
namespace {
const bool kOptional = true;
} // namespace
bool ValidateWidevineCryptoFlags() { bool ValidateWidevineCryptoFlags() {
bool success = true; bool success = true;
@ -80,14 +81,14 @@ bool ValidateWidevineCryptoFlags() {
if (!ValidateFlag("key_server_url", if (!ValidateFlag("key_server_url",
FLAGS_key_server_url, FLAGS_key_server_url,
widevine_crypto, widevine_crypto,
false, !kOptional,
widevine_crypto_label)) { widevine_crypto_label)) {
success = false; success = false;
} }
if (!ValidateFlag("signer", if (!ValidateFlag("signer",
FLAGS_signer, FLAGS_signer,
widevine_crypto, widevine_crypto,
true, kOptional,
widevine_crypto_label)) { widevine_crypto_label)) {
success = false; success = false;
} }
@ -102,16 +103,16 @@ bool ValidateWidevineCryptoFlags() {
// content_id and policy (optional) are associated with // content_id and policy (optional) are associated with
// enable_widevine_encryption. // enable_widevine_encryption.
if (!ValidateFlag("content_id", if (!ValidateFlag("content_id",
FLAGS_content_id, FLAGS_content_id_bytes,
FLAGS_enable_widevine_encryption, FLAGS_enable_widevine_encryption,
false, !kOptional,
widevine_encryption_label)) { widevine_encryption_label)) {
success = false; success = false;
} }
if (!ValidateFlag("policy", if (!ValidateFlag("policy",
FLAGS_policy, FLAGS_policy,
FLAGS_enable_widevine_encryption, FLAGS_enable_widevine_encryption,
true, kOptional,
widevine_encryption_label)) { widevine_encryption_label)) {
success = false; success = false;
} }
@ -142,40 +143,32 @@ bool ValidateWidevineCryptoFlags() {
success = false; success = false;
} }
const bool aes = !FLAGS_signer.empty() && FLAGS_rsa_signing_key_path.empty(); const bool aes = !FLAGS_aes_signing_key_bytes.empty() ||
const char aes_label[] = !FLAGS_aes_signing_iv_bytes.empty();
"--signer is specified and exclusive with --rsa_signing_key_path"; if (aes && (FLAGS_aes_signing_key_bytes.empty() ||
// aes_signer_key and aes_signing_iv are associated with aes signing. FLAGS_aes_signing_iv_bytes.empty())) {
if (!ValidateFlag( PrintError("--aes_signing_key/iv is required if using aes signing.");
"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)) {
success = false; success = false;
} }
const bool rsa = !FLAGS_signer.empty() && FLAGS_aes_signing_key.empty() && const bool rsa = !FLAGS_rsa_signing_key_path.empty();
FLAGS_aes_signing_iv.empty();
const char rsa_label[] = if (FLAGS_signer.empty() && (aes || rsa)) {
"--signer is specified and exclusive with --aes_signing_key/iv"; PrintError("--signer is required if using aes/rsa signing.");
// rsa_signing_key_path is associated with rsa_signing.
if (!ValidateFlag("rsa_signing_key_path",
FLAGS_rsa_signing_key_path,
rsa,
true,
rsa_label)) {
success = false; success = false;
} }
if (!FLAGS_signer.empty() && !aes && !rsa) {
if (!FLAGS_signer.empty() &&
(FLAGS_aes_signing_key.empty() || FLAGS_aes_signing_iv.empty()) &&
FLAGS_rsa_signing_key_path.empty()) {
PrintError( PrintError(
"--aes_signing_key/iv or --rsa_signing_key_path is required with " "--aes_signing_key/iv or --rsa_signing_key_path is required with "
"--signer."); "--signer.");
success = false; 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) { if (FLAGS_crypto_period_duration < 0) {
PrintError("--crypto_period_duration should not be negative."); PrintError("--crypto_period_duration should not be negative.");

View File

@ -11,18 +11,20 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "packager/app/gflags_hex_bytes.h"
DECLARE_bool(enable_widevine_encryption); DECLARE_bool(enable_widevine_encryption);
DECLARE_bool(enable_widevine_decryption); DECLARE_bool(enable_widevine_decryption);
DECLARE_bool(include_common_pssh); DECLARE_bool(include_common_pssh);
DECLARE_string(key_server_url); DECLARE_string(key_server_url);
DECLARE_string(content_id); DECLARE_hex_bytes(content_id);
DECLARE_string(policy); DECLARE_string(policy);
DECLARE_int32(max_sd_pixels); DECLARE_int32(max_sd_pixels);
DECLARE_int32(max_hd_pixels); DECLARE_int32(max_hd_pixels);
DECLARE_int32(max_uhd1_pixels); DECLARE_int32(max_uhd1_pixels);
DECLARE_string(signer); DECLARE_string(signer);
DECLARE_string(aes_signing_key); DECLARE_hex_bytes(aes_signing_key);
DECLARE_string(aes_signing_iv); DECLARE_hex_bytes(aes_signing_iv);
DECLARE_string(rsa_signing_key_path); DECLARE_string(rsa_signing_key_path);
DECLARE_int32(crypto_period_duration); DECLARE_int32(crypto_period_duration);

View File

@ -75,45 +75,27 @@ Status FixedKeySource::GetCryptoPeriodKey(uint32_t crypto_period_index,
return Status::OK; return Status::OK;
} }
std::unique_ptr<FixedKeySource> FixedKeySource::CreateFromHexStrings( std::unique_ptr<FixedKeySource> FixedKeySource::Create(
const std::string& key_id_hex, const std::vector<uint8_t>& key_id,
const std::string& key_hex, const std::vector<uint8_t>& key,
const std::string& pssh_boxes_hex, const std::vector<uint8_t>& pssh_boxes,
const std::string& iv_hex) { const std::vector<uint8_t>& iv) {
std::unique_ptr<EncryptionKey> encryption_key(new EncryptionKey()); std::unique_ptr<EncryptionKey> encryption_key(new EncryptionKey());
if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) { if (key_id.size() != 16) {
LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex; LOG(ERROR) << "Invalid key ID size '" << key_id.size()
return std::unique_ptr<FixedKeySource>();
} else if (encryption_key->key_id.size() != 16) {
LOG(ERROR) << "Invalid key ID size '" << encryption_key->key_id.size()
<< "', must be 16 bytes."; << "', must be 16 bytes.";
return std::unique_ptr<FixedKeySource>(); return std::unique_ptr<FixedKeySource>();
} }
if (key.size() != 16) {
if (!base::HexStringToBytes(key_hex, &encryption_key->key)) {
LOG(ERROR) << "Cannot parse key_hex " << key_hex;
return std::unique_ptr<FixedKeySource>();
} else if (encryption_key->key.size() != 16) {
// CENC only supports AES-128, i.e. 16 bytes. // CENC only supports AES-128, i.e. 16 bytes.
LOG(ERROR) << "Invalid key size '" << encryption_key->key.size() LOG(ERROR) << "Invalid key size '" << key.size() << "', must be 16 bytes.";
<< "', must be 16 bytes.";
return std::unique_ptr<FixedKeySource>(); return std::unique_ptr<FixedKeySource>();
} }
std::vector<uint8_t> pssh_boxes; encryption_key->key_id = key_id;
if (!pssh_boxes_hex.empty() && encryption_key->key = key;
!base::HexStringToBytes(pssh_boxes_hex, &pssh_boxes)) { encryption_key->iv = iv;
LOG(ERROR) << "Cannot parse pssh_hex " << pssh_boxes_hex;
return std::unique_ptr<FixedKeySource>();
}
if (!iv_hex.empty()) {
if (!base::HexStringToBytes(iv_hex, &encryption_key->iv)) {
LOG(ERROR) << "Cannot parse iv_hex " << iv_hex;
return std::unique_ptr<FixedKeySource>();
}
}
if (!ProtectionSystemSpecificInfo::ParseBoxes( if (!ProtectionSystemSpecificInfo::ParseBoxes(
pssh_boxes.data(), pssh_boxes.size(), pssh_boxes.data(), pssh_boxes.size(),

View File

@ -40,20 +40,20 @@ class FixedKeySource : public KeySource {
EncryptionKey* key) override; 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. /// if the strings are invalid.
/// @param key_id_hex is the key id in hex string. /// @param key_id is the key identifier. Must be 16 bytes.
/// @param key_hex is the key in hex string. /// @param key is the encryption / decryption key. Must be 16 bytes.
/// @param pssh_boxes_hex is the pssh_boxes in hex string. /// @param pssh_boxes is the concatenated pssh boxes.
/// @param iv_hex is the IV in hex string. If not specified, a randomly /// @param iv is the initialization vector. If not specified, a randomly
/// generated IV with the default length will be used. /// generated IV with the default length will be used.
/// Note: GetKey on the created key source will always return the same key /// Note: GetKey on the created key source will always return the same key for
/// for all track types. /// all track types.
static std::unique_ptr<FixedKeySource> CreateFromHexStrings( static std::unique_ptr<FixedKeySource> Create(
const std::string& key_id_hex, const std::vector<uint8_t>& key_id,
const std::string& key_hex, const std::vector<uint8_t>& key,
const std::string& pssh_boxes_hex, const std::vector<uint8_t>& pssh_boxes,
const std::string& iv_hex); const std::vector<uint8_t>& iv);
protected: protected:
// Allow default constructor for mock key sources. // Allow default constructor for mock key sources.

View File

@ -43,13 +43,19 @@ const char kDefaultPsshBoxHex[] =
"00000001" "00000001"
"0101020305080d1522375990e9000000" "0101020305080d1522375990e9000000"
"00000000"; "00000000";
std::vector<uint8_t> HexStringToVector(const std::string& str) {
std::vector<uint8_t> vec;
CHECK(base::HexStringToBytes(str, &vec));
return vec;
}
} }
TEST(FixedKeySourceTest, CreateFromHexStrings_Succes) { TEST(FixedKeySourceTest, Success) {
std::string pssh_boxes = std::string(kPsshBox1Hex) + kPsshBox2Hex; std::string pssh_boxes = std::string(kPsshBox1Hex) + kPsshBox2Hex;
std::unique_ptr<FixedKeySource> key_source = std::unique_ptr<FixedKeySource> key_source = FixedKeySource::Create(
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, pssh_boxes, HexStringToVector(kKeyIdHex), HexStringToVector(kKeyHex),
kIvHex); HexStringToVector(pssh_boxes), HexStringToVector(kIvHex));
ASSERT_NE(nullptr, key_source); ASSERT_NE(nullptr, key_source);
EncryptionKey key; EncryptionKey key;
@ -64,9 +70,10 @@ TEST(FixedKeySourceTest, CreateFromHexStrings_Succes) {
EXPECT_HEX_EQ(kPsshBox2Hex, key.key_system_info[1].CreateBox()); EXPECT_HEX_EQ(kPsshBox2Hex, key.key_system_info[1].CreateBox());
} }
TEST(FixedKeySourceTest, CreateFromHexStrings_EmptyPssh) { TEST(FixedKeySourceTest, EmptyPssh) {
std::unique_ptr<FixedKeySource> key_source = std::unique_ptr<FixedKeySource> key_source = FixedKeySource::Create(
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", kIvHex); HexStringToVector(kKeyIdHex), HexStringToVector(kKeyHex),
std::vector<uint8_t>(), HexStringToVector(kIvHex));
ASSERT_NE(nullptr, key_source); ASSERT_NE(nullptr, key_source);
EncryptionKey key; EncryptionKey key;
@ -80,20 +87,17 @@ TEST(FixedKeySourceTest, CreateFromHexStrings_EmptyPssh) {
EXPECT_HEX_EQ(kDefaultPsshBoxHex, key.key_system_info[0].CreateBox()); EXPECT_HEX_EQ(kDefaultPsshBoxHex, key.key_system_info[0].CreateBox());
} }
TEST(FixedKeySourceTest, CreateFromHexStrings_Failure) { TEST(FixedKeySourceTest, Failure) {
std::unique_ptr<FixedKeySource> key_source =
FixedKeySource::CreateFromHexStrings(kKeyIdHex, "invalid_hex_value",
kPsshBox1Hex, kIvHex);
EXPECT_EQ(nullptr, key_source);
// Invalid key id size. // Invalid key id size.
key_source = FixedKeySource::CreateFromHexStrings("000102030405", kKeyHex, std::unique_ptr<FixedKeySource> key_source = FixedKeySource::Create(
kPsshBox1Hex, kIvHex); HexStringToVector("000102030405"), HexStringToVector(kKeyHex),
HexStringToVector(kPsshBox1Hex), HexStringToVector(kIvHex));
EXPECT_EQ(nullptr, key_source); EXPECT_EQ(nullptr, key_source);
// Invalid pssh box. // Invalid pssh box.
key_source = FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, key_source = FixedKeySource::Create(
"000102030405", kIvHex); HexStringToVector(kKeyIdHex), HexStringToVector(kKeyHex),
HexStringToVector("000102030405"), HexStringToVector(kIvHex));
EXPECT_EQ(nullptr, key_source); EXPECT_EQ(nullptr, key_source);
} }

View File

@ -182,17 +182,11 @@ PlayReadyKeySource::PlayReadyKeySource(
PlayReadyKeySource::~PlayReadyKeySource() {} PlayReadyKeySource::~PlayReadyKeySource() {}
std::unique_ptr<PlayReadyKeySource> PlayReadyKeySource::CreateFromKeyAndKeyId( std::unique_ptr<PlayReadyKeySource> PlayReadyKeySource::CreateFromKeyAndKeyId(
const std::string& key_id_hex, const std::string& key_hex) { const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& key) {
std::unique_ptr<EncryptionKey> encryption_key(new EncryptionKey); std::unique_ptr<EncryptionKey> encryption_key(new EncryptionKey);
if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) { encryption_key->key_id = key_id;
LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex; encryption_key->key = key;
return std::unique_ptr<PlayReadyKeySource>();
}
std::vector<uint8_t> key;
if (!base::HexStringToBytes(key_hex, &encryption_key->key)) {
LOG(ERROR) << "Cannot parse key_hex " << key_hex;
return std::unique_ptr<PlayReadyKeySource>();
}
std::vector<uint8_t> pssh_data; std::vector<uint8_t> pssh_data;
Status status = GeneratePlayReadyPsshData( Status status = GeneratePlayReadyPsshData(
encryption_key->key_id, encryption_key->key, &pssh_data); encryption_key->key_id, encryption_key->key, &pssh_data);

View File

@ -51,14 +51,13 @@ class PlayReadyKeySource : public KeySource {
/// @} /// @}
virtual Status FetchKeysWithProgramIdentifier(const std::string& program_identifier); 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. /// 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 /// Note: GetKey on the created key source will always return the same key
/// for all track types. /// for all track types.
static std::unique_ptr<PlayReadyKeySource> CreateFromKeyAndKeyId( static std::unique_ptr<PlayReadyKeySource> CreateFromKeyAndKeyId(
const std::string& key_id_hex, const std::string& key_hex); const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& key);
/// Sets the Certificate Authority file for validating self-signed certificates. /// Sets the Certificate Authority file for validating self-signed certificates.
void SetCaFile(const std::string& ca_file) { void SetCaFile(const std::string& ca_file) {
ca_file_ = ca_file; ca_file_ = ca_file;

View File

@ -8,7 +8,6 @@
#include "packager/base/logging.h" #include "packager/base/logging.h"
#include "packager/base/sha1.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/aes_encryptor.h"
#include "packager/media/base/rsa_key.h" #include "packager/media/base/rsa_key.h"
@ -26,20 +25,10 @@ AesRequestSigner::AesRequestSigner(const std::string& signer_name,
} }
AesRequestSigner::~AesRequestSigner() {} AesRequestSigner::~AesRequestSigner() {}
AesRequestSigner* AesRequestSigner::CreateSigner(const std::string& signer_name, AesRequestSigner* AesRequestSigner::CreateSigner(
const std::string& aes_key_hex, const std::string& signer_name,
const std::string& iv_hex) { const std::vector<uint8_t>& aes_key,
std::vector<uint8_t> aes_key; const std::vector<uint8_t>& iv) {
if (!base::HexStringToBytes(aes_key_hex, &aes_key)) {
LOG(ERROR) << "Failed to convert hex string to bytes: " << aes_key_hex;
return NULL;
}
std::vector<uint8_t> iv;
if (!base::HexStringToBytes(iv_hex, &iv)) {
LOG(ERROR) << "Failed to convert hex string to bytes: " << iv_hex;
return NULL;
}
std::unique_ptr<AesCbcEncryptor> encryptor( std::unique_ptr<AesCbcEncryptor> encryptor(
new AesCbcEncryptor(kPkcs5Padding, AesCryptor::kUseConstantIv)); new AesCbcEncryptor(kPkcs5Padding, AesCryptor::kUseConstantIv));
if (!encryptor->InitializeWithIv(aes_key, iv)) if (!encryptor->InitializeWithIv(aes_key, iv))

View File

@ -9,6 +9,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include "packager/base/macros.h" #include "packager/base/macros.h"
@ -45,11 +46,11 @@ class AesRequestSigner : public RequestSigner {
public: public:
~AesRequestSigner() override; ~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. /// @return The created AesRequestSigner object on success, NULL otherwise.
static AesRequestSigner* CreateSigner(const std::string& signer_name, static AesRequestSigner* CreateSigner(const std::string& signer_name,
const std::string& aes_key_hex, const std::vector<uint8_t>& aes_key,
const std::string& iv_hex); const std::vector<uint8_t>& iv);
/// RequestSigner implementation override. /// RequestSigner implementation override.
bool GenerateSignature(const std::string& message, bool GenerateSignature(const std::string& message,

View File

@ -8,13 +8,9 @@
#include <memory> #include <memory>
#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/muxer_util.h"
#include "packager/media/base/status.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/muxer_listener.h"
#include "packager/media/event/progress_listener.h"
namespace shaka { namespace shaka {
namespace media { namespace media {

View File

@ -56,6 +56,8 @@
'app/crypto_flags.h', 'app/crypto_flags.h',
'app/fixed_key_encryption_flags.cc', 'app/fixed_key_encryption_flags.cc',
'app/fixed_key_encryption_flags.h', 'app/fixed_key_encryption_flags.h',
'app/gflags_hex_bytes.cc',
'app/gflags_hex_bytes.h',
'app/hls_flags.cc', 'app/hls_flags.cc',
'app/hls_flags.h', 'app/hls_flags.h',
'app/mpd_flags.cc', 'app/mpd_flags.cc',

View File

@ -150,9 +150,9 @@ struct WidevineSigner {
SigningKeyType signing_key_type = SigningKeyType::kNone; SigningKeyType signing_key_type = SigningKeyType::kNone;
struct { struct {
/// AES signing key. /// AES signing key.
std::string key; std::vector<uint8_t> key;
/// AES signing IV. /// AES signing IV.
std::string iv; std::vector<uint8_t> iv;
} aes; } aes;
struct { struct {
/// RSA signing private key. /// RSA signing private key.
@ -201,24 +201,24 @@ struct PlayreadyEncryptionParams {
// TODO(kqyang): move raw playready key generation to RawKey. // TODO(kqyang): move raw playready key generation to RawKey.
/// Provides a raw Playready KeyId. /// Provides a raw Playready KeyId.
std::string key_id; std::vector<uint8_t> key_id;
/// Provides a raw Playready Key. /// Provides a raw Playready Key.
std::string key; std::vector<uint8_t> key;
}; };
/// Raw key encryption parameters, i.e. with key parameters provided. /// Raw key encryption parameters, i.e. with key parameters provided.
struct RawKeyEncryptionParams { struct RawKeyEncryptionParams {
/// An optional initialization vector. If not provided, a random `iv` will be /// An optional initialization vector. If not provided, a random `iv` will be
/// generated. Note that this parameter should only be used during testing. /// generated. Note that this parameter should only be used during testing.
std::string iv; std::vector<uint8_t> iv;
/// Inject a custom `pssh` or multiple concatenated `psshs`. If not provided, /// Inject a custom `pssh` or multiple concatenated `psshs`. If not provided,
/// a common system pssh will be generated. /// a common system pssh will be generated.
std::string pssh; std::vector<uint8_t> pssh;
using StreamLabel = std::string; using StreamLabel = std::string;
struct KeyPair { struct KeyPair {
std::string key_id; std::vector<uint8_t> key_id;
std::string key; std::vector<uint8_t> key;
}; };
/// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the /// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the
/// default `KeyPair`, which applies to all the `StreamLabels` not present in /// default `KeyPair`, which applies to all the `StreamLabels` not present in
@ -324,8 +324,8 @@ struct WidevineDecryptionParams {
struct RawKeyDecryptionParams { struct RawKeyDecryptionParams {
using StreamLabel = std::string; using StreamLabel = std::string;
struct KeyPair { struct KeyPair {
std::string key_id; std::vector<uint8_t> key_id;
std::string key; std::vector<uint8_t> key;
}; };
/// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the /// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the
/// default `KeyPair`, which applies to all the `StreamLabels` not present in /// default `KeyPair`, which applies to all the `StreamLabels` not present in

View File

@ -9,6 +9,7 @@
#include "packager/base/files/file_util.h" #include "packager/base/files/file_util.h"
#include "packager/base/logging.h" #include "packager/base/logging.h"
#include "packager/base/path_service.h" #include "packager/base/path_service.h"
#include "packager/base/strings/string_number_conversions.h"
#include "packager/packager.h" #include "packager/packager.h"
namespace shaka { namespace shaka {
@ -67,8 +68,11 @@ class PackagerTest : public ::testing::Test {
packaging_params.encryption_params.clear_lead_in_seconds = packaging_params.encryption_params.clear_lead_in_seconds =
kClearLeadInSeconds; kClearLeadInSeconds;
packaging_params.encryption_params.key_provider = KeyProvider::kRawKey; packaging_params.encryption_params.key_provider = KeyProvider::kRawKey;
packaging_params.encryption_params.raw_key.key_map[""].key_id = kKeyIdHex; CHECK(base::HexStringToBytes(
packaging_params.encryption_params.raw_key.key_map[""].key = kKeyHex; 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; return packaging_params;
} }