Consolidate EncryptionParam and EncryptionOptions

Change-Id: I8a5b5c329d4731341a3184d50bed061aa00cdeda
This commit is contained in:
KongQun Yang 2017-07-05 16:47:55 -07:00
parent e605203fa7
commit c7c201b00c
9 changed files with 352 additions and 360 deletions

View File

@ -134,6 +134,27 @@ bool GetHlsPlaylistType(const std::string& playlist_type,
return true;
}
bool GetProtectionScheme(uint32_t* protection_scheme) {
if (FLAGS_protection_scheme == "cenc") {
*protection_scheme = EncryptionParams::kProtectionSchemeCenc;
return true;
}
if (FLAGS_protection_scheme == "cbc1") {
*protection_scheme = EncryptionParams::kProtectionSchemeCbc1;
return true;
}
if (FLAGS_protection_scheme == "cbcs") {
*protection_scheme = EncryptionParams::kProtectionSchemeCbcs;
return true;
}
if (FLAGS_protection_scheme == "cens") {
*protection_scheme = EncryptionParams::kProtectionSchemeCens;
return true;
}
LOG(ERROR) << "Unrecognized protection_scheme " << FLAGS_protection_scheme;
return false;
}
base::Optional<PackagingParams> GetPackagingParams() {
PackagingParams packaging_params;
@ -166,12 +187,13 @@ base::Optional<PackagingParams> GetPackagingParams() {
if (encryption_params.key_provider != KeyProvider::kNone) {
encryption_params.clear_lead_in_seconds = FLAGS_clear_lead;
encryption_params.protection_scheme = FLAGS_protection_scheme;
if (!GetProtectionScheme(&encryption_params.protection_scheme))
return base::nullopt;
encryption_params.crypto_period_duration_in_seconds =
FLAGS_crypto_period_duration;
encryption_params.vp9_subsample_encryption = FLAGS_vp9_subsample_encryption;
encryption_params.stream_label_func = std::bind(
&EncryptionParams::DefaultStreamLabelFunction, FLAGS_max_sd_pixels,
&Packager::DefaultStreamLabelFunction, FLAGS_max_sd_pixels,
FLAGS_max_hd_pixels, FLAGS_max_uhd1_pixels, std::placeholders::_1);
}
switch (encryption_params.key_provider) {

View File

@ -26,21 +26,6 @@ namespace shaka {
namespace media {
namespace {
FourCC GetProtectionScheme(const std::string& protection_scheme) {
if (protection_scheme == "cenc") {
return FOURCC_cenc;
} else if (protection_scheme == "cens") {
return FOURCC_cens;
} else if (protection_scheme == "cbc1") {
return FOURCC_cbc1;
} else if (protection_scheme == "cbcs") {
return FOURCC_cbcs;
} else {
LOG(ERROR) << "Unknown protection scheme: " << protection_scheme;
return FOURCC_NULL;
}
}
} // namespace
std::unique_ptr<RequestSigner> CreateSigner(const WidevineSigner& signer) {
@ -198,21 +183,6 @@ ChunkingOptions GetChunkingOptions(const ChunkingParams& chunking_params) {
return chunking_options;
}
EncryptionOptions GetEncryptionOptions(
const EncryptionParams& encryption_params) {
EncryptionOptions encryption_options;
encryption_options.clear_lead_in_seconds =
encryption_params.clear_lead_in_seconds;
encryption_options.protection_scheme =
GetProtectionScheme(encryption_params.protection_scheme);
encryption_options.crypto_period_duration_in_seconds =
encryption_params.crypto_period_duration_in_seconds;
encryption_options.vp9_subsample_encryption =
encryption_params.vp9_subsample_encryption;
encryption_options.stream_label_func = encryption_params.stream_label_func;
return encryption_options;
}
MuxerOptions GetMuxerOptions(const std::string& temp_dir,
const Mp4OutputParams& mp4_params) {
MuxerOptions muxer_options;

View File

@ -53,10 +53,6 @@ std::unique_ptr<KeySource> CreateDecryptionKeySource(
/// @return ChunkingOptions from provided command line options.
ChunkingOptions GetChunkingOptions(const ChunkingParams& chunking_params);
/// @return EncryptionOptions from provided command line options.
EncryptionOptions GetEncryptionOptions(
const EncryptionParams& encryption_params);
/// @return MuxerOptions from provided command line options.
MuxerOptions GetMuxerOptions(const std::string& temp_dir,
const Mp4OutputParams& mp4_params);

View File

@ -31,7 +31,7 @@ const uint8_t kKeyRotationDefaultKeyId[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
// Adds one or more subsamples to |*subsamples|. This may add more than one
// Adds one or more subsamples to |*decrypt_config|. This may add more than one
// if one of the values overflows the integer in the subsample.
void AddSubsample(uint64_t clear_bytes,
uint64_t cipher_bytes,
@ -77,15 +77,17 @@ std::string GetStreamLabelForEncryption(
}
} // namespace
EncryptionHandler::EncryptionHandler(
const EncryptionOptions& encryption_options,
KeySource* key_source)
: encryption_options_(encryption_options), key_source_(key_source) {}
EncryptionHandler::EncryptionHandler(const EncryptionParams& encryption_params,
KeySource* key_source)
: encryption_params_(encryption_params),
protection_scheme_(
static_cast<FourCC>(encryption_params.protection_scheme)),
key_source_(key_source) {}
EncryptionHandler::~EncryptionHandler() {}
Status EncryptionHandler::InitializeInternal() {
if (!encryption_options_.stream_label_func) {
if (!encryption_params_.stream_label_func) {
return Status(error::INVALID_ARGUMENT, "Stream label function not set.");
}
if (num_input_streams() != 1 || next_output_stream_index() != 1) {
@ -134,17 +136,17 @@ Status EncryptionHandler::ProcessStreamInfo(StreamInfo* stream_info) {
}
remaining_clear_lead_ =
encryption_options_.clear_lead_in_seconds * stream_info->time_scale();
encryption_params_.clear_lead_in_seconds * stream_info->time_scale();
crypto_period_duration_ =
encryption_options_.crypto_period_duration_in_seconds *
encryption_params_.crypto_period_duration_in_seconds *
stream_info->time_scale();
codec_ = stream_info->codec();
nalu_length_size_ = GetNaluLengthSize(*stream_info);
stream_label_ = GetStreamLabelForEncryption(
*stream_info, encryption_options_.stream_label_func);
*stream_info, encryption_params_.stream_label_func);
switch (codec_) {
case kCodecVP9:
if (encryption_options_.vp9_subsample_encryption)
if (encryption_params_.vp9_subsample_encryption)
vpx_parser_.reset(new VP9Parser);
break;
case kCodecH264:
@ -192,8 +194,7 @@ Status EncryptionHandler::ProcessStreamInfo(StreamInfo* stream_info) {
return Status(error::ENCRYPTION_FAILURE, "Failed to create encryptor");
stream_info->set_is_encrypted(true);
stream_info->set_has_clear_lead(encryption_options_.clear_lead_in_seconds >
0);
stream_info->set_has_clear_lead(encryption_params_.clear_lead_in_seconds > 0);
stream_info->set_encryption_config(*encryption_config_);
return Status::OK;
}
@ -230,10 +231,10 @@ Status EncryptionHandler::ProcessMediaSample(MediaSample* sample) {
if (remaining_clear_lead_ > 0)
return Status::OK;
std::unique_ptr<DecryptConfig> decrypt_config(new DecryptConfig(
encryption_config_->key_id, encryptor_->iv(),
std::vector<SubsampleEntry>(), encryption_options_.protection_scheme,
crypt_byte_block_, skip_byte_block_));
std::unique_ptr<DecryptConfig> decrypt_config(
new DecryptConfig(encryption_config_->key_id, encryptor_->iv(),
std::vector<SubsampleEntry>(), protection_scheme_,
crypt_byte_block_, skip_byte_block_));
bool result = true;
if (vpx_parser_) {
result = EncryptVpxFrame(vpx_frames, sample, decrypt_config.get());
@ -262,7 +263,7 @@ Status EncryptionHandler::ProcessMediaSample(MediaSample* sample) {
}
Status EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
switch (encryption_options_.protection_scheme) {
switch (protection_scheme_) {
case kAppleSampleAesProtectionScheme: {
const size_t kH264LeadingClearBytesSize = 32u;
const size_t kSmallNalUnitSize = 32u + 16u;
@ -323,7 +324,7 @@ Status EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
bool EncryptionHandler::CreateEncryptor(const EncryptionKey& encryption_key) {
std::unique_ptr<AesCryptor> encryptor;
switch (encryption_options_.protection_scheme) {
switch (protection_scheme_) {
case FOURCC_cenc:
encryptor.reset(new AesCtrEncryptor);
break;
@ -363,8 +364,7 @@ bool EncryptionHandler::CreateEncryptor(const EncryptionKey& encryption_key) {
std::vector<uint8_t> iv = encryption_key.iv;
if (iv.empty()) {
if (!AesCryptor::GenerateRandomIv(encryption_options_.protection_scheme,
&iv)) {
if (!AesCryptor::GenerateRandomIv(protection_scheme_, &iv)) {
LOG(ERROR) << "Failed to generate random iv.";
return false;
}
@ -374,7 +374,7 @@ bool EncryptionHandler::CreateEncryptor(const EncryptionKey& encryption_key) {
encryptor_ = std::move(encryptor);
encryption_config_.reset(new EncryptionConfig);
encryption_config_->protection_scheme = encryption_options_.protection_scheme;
encryption_config_->protection_scheme = protection_scheme_;
encryption_config_->crypt_byte_block = crypt_byte_block_;
encryption_config_->skip_byte_block = skip_byte_block_;
if (encryptor_->use_constant_iv()) {
@ -467,9 +467,9 @@ bool EncryptionHandler::EncryptNalFrame(MediaSample* sample,
// CMAF requires 'cenc' scheme BytesOfProtectedData SHALL be a multiple
// of 16 bytes; while 'cbcs' scheme BytesOfProtectedData SHALL start on
// the first byte of video data following the slice header.
if (encryption_options_.protection_scheme == FOURCC_cbc1 ||
encryption_options_.protection_scheme == FOURCC_cens ||
encryption_options_.protection_scheme == FOURCC_cenc) {
if (protection_scheme_ == FOURCC_cbc1 ||
protection_scheme_ == FOURCC_cens ||
protection_scheme_ == FOURCC_cenc) {
const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
current_clear_bytes += misalign_bytes;
cipher_bytes -= misalign_bytes;

View File

@ -9,7 +9,7 @@
#include "packager/media/base/key_source.h"
#include "packager/media/base/media_handler.h"
#include "packager/packager.h"
#include "packager/media/public/crypto_params.h"
namespace shaka {
namespace media {
@ -20,27 +20,9 @@ class VPxParser;
struct EncryptionKey;
struct VPxFrameInfo;
/// This structure defines encryption options.
struct EncryptionOptions {
/// Clear lead duration in seconds.
double clear_lead_in_seconds = 0;
/// The protection scheme: 'cenc', 'cens', 'cbc1', 'cbcs'.
FourCC protection_scheme = FOURCC_cenc;
/// Crypto period duration in seconds. A positive value means key rotation is
/// enabled, the key source must support key rotation in this case.
double crypto_period_duration_in_seconds = 0;
/// Enable/disable subsample encryption for VP9.
bool vp9_subsample_encryption = true;
/// Stream label function used to get the label of the encrypted stream. Must
/// be set.
std::function<std::string(
const EncryptionParams::EncryptedStreamAttributes& stream_attributes)>
stream_label_func;
};
class EncryptionHandler : public MediaHandler {
public:
EncryptionHandler(const EncryptionOptions& encryption_options,
EncryptionHandler(const EncryptionParams& encryption_params,
KeySource* key_source);
~EncryptionHandler() override;
@ -76,7 +58,8 @@ class EncryptionHandler : public MediaHandler {
void InjectVideoSliceHeaderParserForTesting(
std::unique_ptr<VideoSliceHeaderParser> header_parser);
const EncryptionOptions encryption_options_;
const EncryptionParams encryption_params_;
const FourCC protection_scheme_ = FOURCC_NULL;
KeySource* key_source_ = nullptr;
std::string stream_label_;
// Current encryption config and encryptor.

View File

@ -83,13 +83,13 @@ class MockVideoSliceHeaderParser : public VideoSliceHeaderParser {
class EncryptionHandlerTest : public MediaHandlerTestBase {
public:
void SetUp() override { SetUpEncryptionHandler(EncryptionOptions()); }
void SetUp() override { SetUpEncryptionHandler(EncryptionParams()); }
void SetUpEncryptionHandler(const EncryptionOptions& encryption_options) {
EncryptionOptions new_encryption_options = encryption_options;
if (!encryption_options.stream_label_func) {
void SetUpEncryptionHandler(const EncryptionParams& encryption_params) {
EncryptionParams new_encryption_params = encryption_params;
if (!encryption_params.stream_label_func) {
// Setup default stream label function.
new_encryption_options.stream_label_func =
new_encryption_params.stream_label_func =
[](const EncryptionParams::EncryptedStreamAttributes&
stream_attributes) {
if (stream_attributes.stream_type ==
@ -100,7 +100,7 @@ class EncryptionHandlerTest : public MediaHandlerTestBase {
};
}
encryption_handler_.reset(
new EncryptionHandler(new_encryption_options, &mock_key_source_));
new EncryptionHandler(new_encryption_params, &mock_key_source_));
SetUpGraph(1 /* one input */, 1 /* one output */, encryption_handler_);
}
@ -470,11 +470,11 @@ class EncryptionHandlerEncryptionTest
TEST_P(EncryptionHandlerEncryptionTest, ClearLeadWithNoKeyRotation) {
const double kClearLeadInSeconds = 1.5 * kSegmentDuration / kTimeScale;
EncryptionOptions encryption_options;
encryption_options.protection_scheme = protection_scheme_;
encryption_options.clear_lead_in_seconds = kClearLeadInSeconds;
encryption_options.vp9_subsample_encryption = vp9_subsample_encryption_;
SetUpEncryptionHandler(encryption_options);
EncryptionParams encryption_params;
encryption_params.protection_scheme = protection_scheme_;
encryption_params.clear_lead_in_seconds = kClearLeadInSeconds;
encryption_params.vp9_subsample_encryption = vp9_subsample_encryption_;
SetUpEncryptionHandler(encryption_params);
const EncryptionKey mock_encryption_key = GetMockEncryptionKey();
EXPECT_CALL(mock_key_source_, GetKey(_, _))
@ -523,13 +523,13 @@ TEST_P(EncryptionHandlerEncryptionTest, ClearLeadWithKeyRotation) {
const int kSegmentsPerCryptoPeriod = 2; // 2 segments.
const double kCryptoPeriodDurationInSeconds =
kSegmentsPerCryptoPeriod * kSegmentDuration / kTimeScale;
EncryptionOptions encryption_options;
encryption_options.protection_scheme = protection_scheme_;
encryption_options.clear_lead_in_seconds = kClearLeadInSeconds;
encryption_options.crypto_period_duration_in_seconds =
EncryptionParams encryption_params;
encryption_params.protection_scheme = protection_scheme_;
encryption_params.clear_lead_in_seconds = kClearLeadInSeconds;
encryption_params.crypto_period_duration_in_seconds =
kCryptoPeriodDurationInSeconds;
encryption_options.vp9_subsample_encryption = vp9_subsample_encryption_;
SetUpEncryptionHandler(encryption_options);
encryption_params.vp9_subsample_encryption = vp9_subsample_encryption_;
SetUpEncryptionHandler(encryption_params);
ASSERT_OK(Process(GetStreamInfoStreamData(kStreamIndex, codec_, kTimeScale)));
EXPECT_THAT(GetOutputStreamDataVector(),
@ -582,10 +582,10 @@ TEST_P(EncryptionHandlerEncryptionTest, ClearLeadWithKeyRotation) {
}
TEST_P(EncryptionHandlerEncryptionTest, Encrypt) {
EncryptionOptions encryption_options;
encryption_options.protection_scheme = protection_scheme_;
encryption_options.vp9_subsample_encryption = vp9_subsample_encryption_;
SetUpEncryptionHandler(encryption_options);
EncryptionParams encryption_params;
encryption_params.protection_scheme = protection_scheme_;
encryption_params.vp9_subsample_encryption = vp9_subsample_encryption_;
SetUpEncryptionHandler(encryption_params);
const EncryptionKey mock_encryption_key = GetMockEncryptionKey();
EXPECT_CALL(mock_key_source_, GetKey(_, _))
@ -653,15 +653,15 @@ class EncryptionHandlerTrackTypeTest : public EncryptionHandlerTest {
TEST_F(EncryptionHandlerTrackTypeTest, AudioTrackType) {
EncryptionParams::EncryptedStreamAttributes captured_stream_attributes;
EncryptionOptions encryption_options;
encryption_options.stream_label_func =
EncryptionParams encryption_params;
encryption_params.stream_label_func =
[&captured_stream_attributes](
const EncryptionParams::EncryptedStreamAttributes&
stream_attributes) {
captured_stream_attributes = stream_attributes;
return kAudioStreamLabel;
};
SetUpEncryptionHandler(encryption_options);
SetUpEncryptionHandler(encryption_params);
EXPECT_CALL(mock_key_source_, GetKey(kAudioStreamLabel, _))
.WillOnce(
DoAll(SetArgPointee<1>(GetMockEncryptionKey()), Return(Status::OK)));
@ -672,15 +672,15 @@ TEST_F(EncryptionHandlerTrackTypeTest, AudioTrackType) {
TEST_F(EncryptionHandlerTrackTypeTest, VideoTrackType) {
EncryptionParams::EncryptedStreamAttributes captured_stream_attributes;
EncryptionOptions encryption_options;
encryption_options.stream_label_func =
EncryptionParams encryption_params;
encryption_params.stream_label_func =
[&captured_stream_attributes](
const EncryptionParams::EncryptedStreamAttributes&
stream_attributes) {
captured_stream_attributes = stream_attributes;
return kSdVideoStreamLabel;
};
SetUpEncryptionHandler(encryption_options);
SetUpEncryptionHandler(encryption_params);
EXPECT_CALL(mock_key_source_, GetKey(kSdVideoStreamLabel, _))
.WillOnce(
DoAll(SetArgPointee<1>(GetMockEncryptionKey()), Return(Status::OK)));

View File

@ -0,0 +1,211 @@
// 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
#ifndef PACKAGER_MEDIA_PUBLIC_CRYPTO_PARAMS_H_
#define PACKAGER_MEDIA_PUBLIC_CRYPTO_PARAMS_H_
#include <functional>
#include <map>
#include <string>
#include <vector>
namespace shaka {
/// Encryption / decryption key providers.
enum class KeyProvider {
kNone = 0,
kWidevine = 1,
kPlayready = 2,
kRawKey = 3,
};
/// Signer credential for Widevine license server.
struct WidevineSigner {
/// Name of the signer / content provider.
std::string signer_name;
enum class SigningKeyType {
kNone,
kAes,
kRsa,
};
/// Specifies the signing key type, which determines whether AES or RSA key
/// are used to authenticate the signer. A type of 'kNone' is invalid.
SigningKeyType signing_key_type = SigningKeyType::kNone;
struct {
/// AES signing key.
std::vector<uint8_t> key;
/// AES signing IV.
std::vector<uint8_t> iv;
} aes;
struct {
/// RSA signing private key.
std::string key;
} rsa;
};
/// Widevine encryption parameters.
struct WidevineEncryptionParams {
/// Widevine license / key server URL.
std::string key_server_url;
/// Generates and includes an additional v1 PSSH box for the common system ID.
/// See: https://goo.gl/s8RIhr.
// TODO(kqyang): Move to EncryptionParams and support common PSSH generation
// in all key providers.
bool include_common_pssh = false;
/// Content identifier.
std::vector<uint8_t> content_id;
/// The name of a stored policy, which specifies DRM content rights.
std::string policy;
/// Signer credential for Widevine license / key server.
WidevineSigner signer;
/// Group identifier, if present licenses will belong to this group.
std::vector<uint8_t> group_id;
};
/// Playready encryption parameters.
/// Two different modes of playready key acquisition is supported:
/// (1) Fetch from a key server. `key_server_url` and `program_identifier` are
/// required. The presence of other parameters may be necessary depends
/// on server configuration.
/// (2) Provide the raw key directly. Both `key_id` and `key` are required.
/// We are planning to merge this mode with `RawKeyEncryptionParams`.
struct PlayreadyEncryptionParams {
/// Playready license / key server URL.
std::string key_server_url;
/// Playready program identifier.
std::string program_identifier;
/// Absolute path to the Certificate Authority file for the server cert in PEM
/// format.
std::string ca_file;
/// Absolute path to client certificate file.
std::string client_cert_file;
/// Absolute path to the private key file.
std::string client_cert_private_key_file;
/// Password to the private key file.
std::string client_cert_private_key_password;
// TODO(kqyang): move raw playready key generation to RawKey.
/// Provides a raw Playready KeyId.
std::vector<uint8_t> key_id;
/// Provides a raw Playready Key.
std::vector<uint8_t> key;
};
/// Raw key encryption parameters, i.e. with key parameters provided.
struct RawKeyEncryptionParams {
/// An optional initialization vector. If not provided, a random `iv` will be
/// generated. Note that this parameter should only be used during testing.
std::vector<uint8_t> iv;
/// Inject a custom `pssh` or multiple concatenated `psshs`. If not provided,
/// a common system pssh will be generated.
std::vector<uint8_t> pssh;
using StreamLabel = std::string;
struct KeyPair {
std::vector<uint8_t> key_id;
std::vector<uint8_t> key;
};
/// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the
/// default `KeyPair`, which applies to all the `StreamLabels` not present in
/// `key_map`.
std::map<StreamLabel, KeyPair> key_map;
};
/// Encryption parameters.
struct EncryptionParams {
/// Specifies the key provider, which determines which key provider is used
/// and which encryption params is valid. 'kNone' means not to encrypt the
/// streams.
KeyProvider key_provider = KeyProvider::kNone;
// Only one of the three fields is valid.
WidevineEncryptionParams widevine;
PlayreadyEncryptionParams playready;
RawKeyEncryptionParams raw_key;
/// Clear lead duration in seconds.
double clear_lead_in_seconds = 0;
/// The protection scheme: "cenc", "cens", "cbc1", "cbcs".
static constexpr uint32_t kProtectionSchemeCenc = 0x63656E63;
static constexpr uint32_t kProtectionSchemeCbc1 = 0x63626331;
static constexpr uint32_t kProtectionSchemeCens = 0x63656E73;
static constexpr uint32_t kProtectionSchemeCbcs = 0x63626373;
uint32_t protection_scheme = kProtectionSchemeCenc;
/// Crypto period duration in seconds. A positive value means key rotation is
/// enabled, the key provider must support key rotation in this case.
static constexpr double kNoKeyRotation = 0;
double crypto_period_duration_in_seconds = kNoKeyRotation;
/// Enable/disable subsample encryption for VP9.
bool vp9_subsample_encryption = true;
/// Encrypted stream information that is used to determine stream label.
struct EncryptedStreamAttributes {
enum StreamType {
kUnknown,
kVideo,
kAudio,
};
StreamType stream_type = kUnknown;
union OneOf {
OneOf() {}
struct {
int width = 0;
int height = 0;
float frame_rate = 0;
int bit_depth = 0;
} video;
struct {
int number_of_channels = 0;
} audio;
} oneof;
};
/// Stream label function assigns a stream label to the stream to be
/// encrypted. Stream label is used to associate KeyPair with streams. Streams
/// with the same stream label always uses the same keyPair; Streams with
/// different stream label could use the same or different KeyPairs.
/// A default stream label function will be generated if not set.
std::function<std::string(const EncryptedStreamAttributes& stream_attributes)>
stream_label_func;
};
/// Widevine decryption parameters.
struct WidevineDecryptionParams {
/// Widevine license / key server URL.
std::string key_server_url;
/// Signer credential for Widevine license / key server.
WidevineSigner signer;
};
/// Raw key decryption parameters, i.e. with key parameters provided.
struct RawKeyDecryptionParams {
using StreamLabel = std::string;
struct KeyPair {
std::vector<uint8_t> key_id;
std::vector<uint8_t> key;
};
/// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the
/// default `KeyPair`, which applies to all the `StreamLabels` not present in
/// `key_map`.
std::map<StreamLabel, KeyPair> key_map;
};
/// Decryption parameters.
struct DecryptionParams {
/// Specifies the key provider, which determines which key provider is used
/// and which encryption params is valid. 'kNone' means not to decrypt the
/// streams.
KeyProvider key_provider = KeyProvider::kNone;
// Only one of the two fields is valid.
WidevineDecryptionParams widevine;
RawKeyDecryptionParams raw_key;
};
} // namespace shaka
#endif // PACKAGER_MEDIA_PUBLIC_CRYPTO_PARAMS_H_

View File

@ -316,7 +316,6 @@ std::shared_ptr<Muxer> CreateOutputMuxer(const MuxerOptions& options,
bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
const PackagingParams& packaging_params,
const ChunkingOptions& chunking_options,
const EncryptionOptions& encryption_options,
const MuxerOptions& muxer_options,
FakeClock* fake_clock,
KeySource* encryption_key_source,
@ -472,17 +471,25 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
Status status;
if (encryption_key_source && !stream_iter->skip_encryption) {
auto new_encryption_options = encryption_options;
auto encryption_params = packaging_params.encryption_params;
// Use Sample AES in MPEG2TS.
// TODO(kqyang): Consider adding a new flag to enable Sample AES as we
// will support CENC in TS in the future.
if (output_format == CONTAINER_MPEG2TS) {
VLOG(1) << "Use Apple Sample AES encryption for MPEG2TS.";
new_encryption_options.protection_scheme =
encryption_params.protection_scheme =
kAppleSampleAesProtectionScheme;
}
if (!encryption_params.stream_label_func) {
const int kDefaultMaxSdPixels = 768 * 576;
const int kDefaultMaxHdPixels = 1920 * 1080;
const int kDefaultMaxUhd1Pixels = 4096 * 2160;
encryption_params.stream_label_func = std::bind(
&Packager::DefaultStreamLabelFunction, kDefaultMaxSdPixels,
kDefaultMaxHdPixels, kDefaultMaxUhd1Pixels, std::placeholders::_1);
}
handlers.emplace_back(
new EncryptionHandler(new_encryption_options, encryption_key_source));
new EncryptionHandler(encryption_params, encryption_key_source));
}
// If trick_play_handler is available, muxer should already be connected to
@ -544,24 +551,6 @@ Status RunRemuxJobs(const std::vector<std::unique_ptr<Job>>& jobs) {
} // namespace
} // namespace media
std::string EncryptionParams::DefaultStreamLabelFunction(
int max_sd_pixels,
int max_hd_pixels,
int max_uhd1_pixels,
const EncryptedStreamAttributes& stream_attributes) {
if (stream_attributes.stream_type == EncryptedStreamAttributes::kAudio)
return "AUDIO";
if (stream_attributes.stream_type == EncryptedStreamAttributes::kVideo) {
const int pixels = stream_attributes.oneof.video.width *
stream_attributes.oneof.video.height;
if (pixels <= max_sd_pixels) return "SD";
if (pixels <= max_hd_pixels) return "HD";
if (pixels <= max_uhd1_pixels) return "UHD1";
return "UHD2";
}
return "";
}
struct Packager::PackagerInternal {
media::FakeClock fake_clock;
std::unique_ptr<KeySource> encryption_key_source;
@ -596,8 +585,6 @@ Status Packager::Initialize(
ChunkingOptions chunking_options =
media::GetChunkingOptions(packaging_params.chunking_params);
EncryptionOptions encryption_options =
media::GetEncryptionOptions(packaging_params.encryption_params);
MuxerOptions muxer_options = media::GetMuxerOptions(
packaging_params.temp_dir, packaging_params.mp4_output_params);
@ -608,11 +595,10 @@ Status Packager::Initialize(
// Create encryption key source if needed.
if (packaging_params.encryption_params.key_provider != KeyProvider::kNone) {
if (encryption_options.protection_scheme == media::FOURCC_NULL)
return Status(error::INVALID_ARGUMENT, "Invalid protection scheme.");
internal->encryption_key_source =
CreateEncryptionKeySource(encryption_options.protection_scheme,
packaging_params.encryption_params);
internal->encryption_key_source = CreateEncryptionKeySource(
static_cast<media::FourCC>(
packaging_params.encryption_params.protection_scheme),
packaging_params.encryption_params);
if (!internal->encryption_key_source)
return Status(error::INVALID_ARGUMENT, "Failed to create key source.");
}
@ -651,7 +637,7 @@ Status Packager::Initialize(
stream_descriptor_list.insert(descriptor);
if (!media::CreateRemuxJobs(
stream_descriptor_list, packaging_params, chunking_options,
encryption_options, muxer_options, &internal->fake_clock,
muxer_options, &internal->fake_clock,
internal->encryption_key_source.get(), internal->mpd_notifier.get(),
internal->hls_notifier.get(), &internal->jobs)) {
return Status(error::INVALID_ARGUMENT, "Failed to create remux jobs.");
@ -691,4 +677,24 @@ std::string Packager::GetLibraryVersion() {
return GetPackagerVersion();
}
std::string Packager::DefaultStreamLabelFunction(
int max_sd_pixels,
int max_hd_pixels,
int max_uhd1_pixels,
const EncryptionParams::EncryptedStreamAttributes& stream_attributes) {
if (stream_attributes.stream_type ==
EncryptionParams::EncryptedStreamAttributes::kAudio)
return "AUDIO";
if (stream_attributes.stream_type ==
EncryptionParams::EncryptedStreamAttributes::kVideo) {
const int pixels = stream_attributes.oneof.video.width *
stream_attributes.oneof.video.height;
if (pixels <= max_sd_pixels) return "SD";
if (pixels <= max_hd_pixels) return "HD";
if (pixels <= max_uhd1_pixels) return "UHD1";
return "UHD2";
}
return "";
}
} // namespace shaka

View File

@ -7,14 +7,12 @@
#ifndef PACKAGER_PACKAGER_H_
#define PACKAGER_PACKAGER_H_
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "packager/hls/public/hls_playlist_type.h"
#include "packager/media/public/crypto_params.h"
#include "packager/status.h"
namespace shaka {
@ -109,225 +107,6 @@ struct HlsParams {
double time_shift_buffer_depth = 0;
};
/// Encryption / decryption key providers.
enum class KeyProvider {
kNone = 0,
kWidevine = 1,
kPlayready = 2,
kRawKey = 3,
};
/// Signer credential for Widevine license server.
struct WidevineSigner {
/// Name of the signer / content provider.
std::string signer_name;
enum class SigningKeyType {
kNone,
kAes,
kRsa,
};
/// Specifies the signing key type, which determines whether AES or RSA key
/// are used to authenticate the signer. A type of 'kNone' is invalid.
SigningKeyType signing_key_type = SigningKeyType::kNone;
struct {
/// AES signing key.
std::vector<uint8_t> key;
/// AES signing IV.
std::vector<uint8_t> iv;
} aes;
struct {
/// RSA signing private key.
std::string key;
} rsa;
};
/// Widevine encryption parameters.
struct WidevineEncryptionParams {
/// Widevine license / key server URL.
std::string key_server_url;
/// Generates and includes an additional v1 PSSH box for the common system ID.
/// See: https://goo.gl/s8RIhr.
// TODO(kqyang): Move to EncryptionParams and support common PSSH generation
// in all key providers.
bool include_common_pssh = false;
/// Content identifier.
std::vector<uint8_t> content_id;
/// The name of a stored policy, which specifies DRM content rights.
std::string policy;
/// Signer credential for Widevine license / key server.
WidevineSigner signer;
/// Group identifier, if present licenses will belong to this group.
std::vector<uint8_t> group_id;
};
/// Playready encryption parameters.
/// Two different modes of playready key acquisition is supported:
/// (1) Fetch from a key server. `key_server_url` and `program_identifier` are
/// required. The presence of other parameters may be necessary depends
/// on server configuration.
/// (2) Provide the raw key directly. Both `key_id` and `key` are required.
/// We are planning to merge this mode with `RawKeyEncryptionParams`.
struct PlayreadyEncryptionParams {
/// Playready license / key server URL.
std::string key_server_url;
/// Playready program identifier.
std::string program_identifier;
/// Absolute path to the Certificate Authority file for the server cert in PEM
/// format.
std::string ca_file;
/// Absolute path to client certificate file.
std::string client_cert_file;
/// Absolute path to the private key file.
std::string client_cert_private_key_file;
/// Password to the private key file.
std::string client_cert_private_key_password;
// TODO(kqyang): move raw playready key generation to RawKey.
/// Provides a raw Playready KeyId.
std::vector<uint8_t> key_id;
/// Provides a raw Playready Key.
std::vector<uint8_t> key;
};
/// Raw key encryption parameters, i.e. with key parameters provided.
struct RawKeyEncryptionParams {
/// An optional initialization vector. If not provided, a random `iv` will be
/// generated. Note that this parameter should only be used during testing.
std::vector<uint8_t> iv;
/// Inject a custom `pssh` or multiple concatenated `psshs`. If not provided,
/// a common system pssh will be generated.
std::vector<uint8_t> pssh;
using StreamLabel = std::string;
struct KeyPair {
std::vector<uint8_t> key_id;
std::vector<uint8_t> key;
};
/// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the
/// default `KeyPair`, which applies to all the `StreamLabels` not present in
/// `key_map`.
std::map<StreamLabel, KeyPair> key_map;
};
/// Encryption parameters.
struct EncryptionParams {
/// Specifies the key provider, which determines which key provider is used
/// and which encryption params is valid. 'kNone' means not to encrypt the
/// streams.
KeyProvider key_provider = KeyProvider::kNone;
// Only one of the three fields is valid.
WidevineEncryptionParams widevine;
PlayreadyEncryptionParams playready;
RawKeyEncryptionParams raw_key;
/// Clear lead duration in seconds.
double clear_lead_in_seconds = 0;
/// The protection scheme: "cenc", "cens", "cbc1", "cbcs".
std::string protection_scheme = "cenc";
/// Crypto period duration in seconds. A positive value means key rotation is
/// enabled, the key provider must support key rotation in this case.
const double kNoKeyRotation = 0;
double crypto_period_duration_in_seconds = 0;
/// Enable/disable subsample encryption for VP9.
bool vp9_subsample_encryption = true;
/// Encrypted stream information that is used to determine stream label.
struct EncryptedStreamAttributes {
enum StreamType {
kUnknown,
kVideo,
kAudio,
};
StreamType stream_type = kUnknown;
union OneOf {
OneOf() {}
struct {
int width = 0;
int height = 0;
float frame_rate = 0;
int bit_depth = 0;
} video;
struct {
int number_of_channels = 0;
} audio;
} oneof;
};
/// Default stream label function implementation.
/// @param max_sd_pixels The threshold to determine whether a video track
/// should be considered as SD. If the max pixels per
/// frame is no higher than max_sd_pixels, i.e. [0,
/// max_sd_pixels], it is SD.
/// @param max_hd_pixels: The threshold to determine whether a video track
/// should be considered as HD. If the max pixels per
/// frame is higher than max_sd_pixels, but no higher
/// than max_hd_pixels, i.e. (max_sd_pixels,
/// max_hd_pixels], it is HD.
/// @param max_uhd1_pixels: The threshold to determine whether a video track
/// should be considered as UHD1. If the max pixels
/// per frame is higher than max_hd_pixels, but no
/// higher than max_uhd1_pixels, i.e. (max_hd_pixels,
/// max_uhd1_pixels], it is UHD1. Otherwise it is
/// UHD2.
/// @param stream_info Encrypted stream info.
/// @return the stream label associated with `stream_info`. Can be "AUDIO",
/// "SD", "HD", "UHD1" or "UHD2".
static SHAKA_EXPORT std::string DefaultStreamLabelFunction(
int max_sd_pixels,
int max_hd_pixels,
int max_uhd1_pixels,
const EncryptedStreamAttributes& stream_attributes);
const int kDefaultMaxSdPixels = 768 * 576;
const int kDefaultMaxHdPixels = 1920 * 1080;
const int kDefaultMaxUhd1Pixels = 4096 * 2160;
/// Stream label function assigns a stream label to the stream to be
/// encrypted. Stream label is used to associate KeyPair with streams. Streams
/// with the same stream label always uses the same keyPair; Streams with
/// different stream label could use the same or different KeyPairs.
std::function<std::string(const EncryptedStreamAttributes& stream_attributes)>
stream_label_func =
std::bind(&EncryptionParams::DefaultStreamLabelFunction,
kDefaultMaxSdPixels,
kDefaultMaxHdPixels,
kDefaultMaxUhd1Pixels,
std::placeholders::_1);
};
/// Widevine decryption parameters.
struct WidevineDecryptionParams {
/// Widevine license / key server URL.
std::string key_server_url;
/// Signer credential for Widevine license / key server.
WidevineSigner signer;
};
/// Raw key decryption parameters, i.e. with key parameters provided.
struct RawKeyDecryptionParams {
using StreamLabel = std::string;
struct KeyPair {
std::vector<uint8_t> key_id;
std::vector<uint8_t> key;
};
/// Defines the KeyPair for the streams. An empty `StreamLabel` indicates the
/// default `KeyPair`, which applies to all the `StreamLabels` not present in
/// `key_map`.
std::map<StreamLabel, KeyPair> key_map;
};
/// Decryption parameters.
struct DecryptionParams {
/// Specifies the key provider, which determines which key provider is used
/// and which encryption params is valid. 'kNone' means not to decrypt the
/// streams.
KeyProvider key_provider = KeyProvider::kNone;
// Only one of the two fields is valid.
WidevineDecryptionParams widevine;
RawKeyDecryptionParams raw_key;
};
/// Parameters used for testing.
struct TestParams {
/// Whether to dump input stream info.
@ -440,6 +219,31 @@ class SHAKA_EXPORT Packager {
/// @return The version of the library.
static std::string GetLibraryVersion();
/// Default stream label function implementation.
/// @param max_sd_pixels The threshold to determine whether a video track
/// should be considered as SD. If the max pixels per
/// frame is no higher than max_sd_pixels, i.e. [0,
/// max_sd_pixels], it is SD.
/// @param max_hd_pixels The threshold to determine whether a video track
/// should be considered as HD. If the max pixels per
/// frame is higher than max_sd_pixels, but no higher
/// than max_hd_pixels, i.e. (max_sd_pixels,
/// max_hd_pixels], it is HD.
/// @param max_uhd1_pixels The threshold to determine whether a video track
/// should be considered as UHD1. If the max pixels
/// per frame is higher than max_hd_pixels, but no
/// higher than max_uhd1_pixels, i.e. (max_hd_pixels,
/// max_uhd1_pixels], it is UHD1. Otherwise it is
/// UHD2.
/// @param stream_info Encrypted stream info.
/// @return the stream label associated with `stream_info`. Can be "AUDIO",
/// "SD", "HD", "UHD1" or "UHD2".
static std::string DefaultStreamLabelFunction(
int max_sd_pixels,
int max_hd_pixels,
int max_uhd1_pixels,
const EncryptionParams::EncryptedStreamAttributes& stream_attributes);
private:
Packager(const Packager&) = delete;
Packager& operator=(const Packager&) = delete;