Move hex string out of packager.h
Also added validation failure tests in packager_test.py. Change-Id: I6697a3138d57889110250404205536dd5cd53cd0
This commit is contained in:
parent
abbd495ad4
commit
03889e6465
|
@ -16,13 +16,15 @@ 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,
|
||||
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 "
|
||||
"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,
|
||||
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 "
|
||||
|
@ -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;
|
||||
|
|
|
@ -11,13 +11,15 @@
|
|||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#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 {
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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<PackagingParams> GetPackagingParams() {
|
||||
PackagingParams packaging_params;
|
||||
|
||||
|
@ -143,33 +161,10 @@ base::Optional<PackagingParams> 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<PackagingParams> 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<PackagingParams> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ std::unique_ptr<KeySource> 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<KeySource> 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<uint8_t> kNoPssh;
|
||||
const std::vector<uint8_t> kNoIv;
|
||||
decryption_key_source = FixedKeySource::Create(
|
||||
raw_key.key_map.find("")->second.key_id,
|
||||
raw_key.key_map.find("")->second.key, kNoPssh, kNoIv);
|
||||
break;
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
flags += [
|
||||
'--enable_widevine_encryption',
|
||||
'--key_server_url=' + widevine_server_url,
|
||||
'--content_id=3031323334353637', '--signer=widevine_test']
|
||||
'--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)
|
||||
|
||||
|
||||
|
|
|
@ -10,29 +10,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#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());
|
||||
}
|
||||
|
|
|
@ -11,8 +11,14 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#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 <class FlagType>
|
||||
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
|
||||
|
||||
|
|
|
@ -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,
|
||||
DEFINE_hex_bytes(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_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.");
|
||||
|
|
|
@ -11,18 +11,20 @@
|
|||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
|
|
@ -75,45 +75,27 @@ Status FixedKeySource::GetCryptoPeriodKey(uint32_t crypto_period_index,
|
|||
return Status::OK;
|
||||
}
|
||||
|
||||
std::unique_ptr<FixedKeySource> 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> FixedKeySource::Create(
|
||||
const std::vector<uint8_t>& key_id,
|
||||
const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& pssh_boxes,
|
||||
const std::vector<uint8_t>& iv) {
|
||||
std::unique_ptr<EncryptionKey> 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<FixedKeySource>();
|
||||
} 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<FixedKeySource>();
|
||||
}
|
||||
|
||||
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) {
|
||||
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<FixedKeySource>();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> 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<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>();
|
||||
}
|
||||
}
|
||||
encryption_key->key_id = key_id;
|
||||
encryption_key->key = key;
|
||||
encryption_key->iv = iv;
|
||||
|
||||
if (!ProtectionSystemSpecificInfo::ParseBoxes(
|
||||
pssh_boxes.data(), pssh_boxes.size(),
|
||||
|
|
|
@ -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<FixedKeySource> 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<FixedKeySource> Create(
|
||||
const std::vector<uint8_t>& key_id,
|
||||
const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& pssh_boxes,
|
||||
const std::vector<uint8_t>& iv);
|
||||
|
||||
protected:
|
||||
// Allow default constructor for mock key sources.
|
||||
|
|
|
@ -43,13 +43,19 @@ const char kDefaultPsshBoxHex[] =
|
|||
"00000001"
|
||||
"0101020305080d1522375990e9000000"
|
||||
"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::unique_ptr<FixedKeySource> key_source =
|
||||
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, pssh_boxes,
|
||||
kIvHex);
|
||||
std::unique_ptr<FixedKeySource> 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<FixedKeySource> key_source =
|
||||
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", kIvHex);
|
||||
TEST(FixedKeySourceTest, EmptyPssh) {
|
||||
std::unique_ptr<FixedKeySource> key_source = FixedKeySource::Create(
|
||||
HexStringToVector(kKeyIdHex), HexStringToVector(kKeyHex),
|
||||
std::vector<uint8_t>(), 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<FixedKeySource> 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<FixedKeySource> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -182,17 +182,11 @@ PlayReadyKeySource::PlayReadyKeySource(
|
|||
PlayReadyKeySource::~PlayReadyKeySource() {}
|
||||
|
||||
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);
|
||||
if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) {
|
||||
LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex;
|
||||
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>();
|
||||
}
|
||||
encryption_key->key_id = key_id;
|
||||
encryption_key->key = key;
|
||||
std::vector<uint8_t> pssh_data;
|
||||
Status status = GeneratePlayReadyPsshData(
|
||||
encryption_key->key_id, encryption_key->key, &pssh_data);
|
||||
|
|
|
@ -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<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.
|
||||
void SetCaFile(const std::string& ca_file) {
|
||||
ca_file_ = ca_file;
|
||||
|
|
|
@ -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<uint8_t> 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<uint8_t> 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<uint8_t>& aes_key,
|
||||
const std::vector<uint8_t>& iv) {
|
||||
std::unique_ptr<AesCbcEncryptor> encryptor(
|
||||
new AesCbcEncryptor(kPkcs5Padding, AesCryptor::kUseConstantIv));
|
||||
if (!encryptor->InitializeWithIv(aes_key, iv))
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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<uint8_t>& aes_key,
|
||||
const std::vector<uint8_t>& iv);
|
||||
|
||||
/// RequestSigner implementation override.
|
||||
bool GenerateSignature(const std::string& message,
|
||||
|
|
|
@ -8,13 +8,9 @@
|
|||
|
||||
#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/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 {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -150,9 +150,9 @@ struct WidevineSigner {
|
|||
SigningKeyType signing_key_type = SigningKeyType::kNone;
|
||||
struct {
|
||||
/// AES signing key.
|
||||
std::string key;
|
||||
std::vector<uint8_t> key;
|
||||
/// AES signing IV.
|
||||
std::string iv;
|
||||
std::vector<uint8_t> 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<uint8_t> key_id;
|
||||
/// Provides a raw Playready Key.
|
||||
std::string key;
|
||||
std::vector<uint8_t> 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<uint8_t> iv;
|
||||
/// Inject a custom `pssh` or multiple concatenated `psshs`. If not provided,
|
||||
/// a common system pssh will be generated.
|
||||
std::string pssh;
|
||||
std::vector<uint8_t> pssh;
|
||||
|
||||
using StreamLabel = std::string;
|
||||
struct KeyPair {
|
||||
std::string key_id;
|
||||
std::string key;
|
||||
std::vector<uint8_t> key_id;
|
||||
std::vector<uint8_t> 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<uint8_t> key_id;
|
||||
std::vector<uint8_t> key;
|
||||
};
|
||||
/// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the
|
||||
/// default `KeyPair`, which applies to all the `StreamLabels` not present in
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue