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,
|
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 "
|
"IV in hex string format. If not specified, a random IV will be "
|
||||||
"generated. This flag should only be used for testing.");
|
"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, "
|
"One or more PSSH boxes in hex string format. If not specified, "
|
||||||
"will generate a v1 common PSSH box as specified in "
|
"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";
|
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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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,
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 "
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 += [
|
||||||
|
'--enable_widevine_encryption',
|
||||||
'--key_server_url=' + widevine_server_url,
|
'--key_server_url=' + widevine_server_url,
|
||||||
'--content_id=3031323334353637', '--signer=widevine_test']
|
'--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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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.");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue