Use FOURCC as protection scheme parameter
- Remove EncryptionMode enums - Remove AesEncryptor::InitializeWithRandomIv, replaced with a static function AesCryptor::GenerateRandomIv, which should be called to generate the iv if the iv is empty. This change is to prepare support for CBCS and CENS pattern-based protection schemes. Issue #77 Change-Id: Icba35089d6e451cbea7ebbf5dd5674079f206390
This commit is contained in:
parent
0218d9c690
commit
2ac57bf9b9
|
@ -25,7 +25,7 @@
|
||||||
#include "packager/base/time/clock.h"
|
#include "packager/base/time/clock.h"
|
||||||
#include "packager/media/base/container_names.h"
|
#include "packager/media/base/container_names.h"
|
||||||
#include "packager/media/base/demuxer.h"
|
#include "packager/media/base/demuxer.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/key_source.h"
|
#include "packager/media/base/key_source.h"
|
||||||
#include "packager/media/base/muxer_options.h"
|
#include "packager/media/base/muxer_options.h"
|
||||||
#include "packager/media/base/muxer_util.h"
|
#include "packager/media/base/muxer_util.h"
|
||||||
|
@ -105,15 +105,19 @@ std::string DetermineTextFileFormat(const std::string& file) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
edash_packager::media::EncryptionMode GetEncryptionMode(
|
edash_packager::media::FourCC GetProtectionScheme(
|
||||||
const std::string& protection_scheme) {
|
const std::string& protection_scheme) {
|
||||||
if (protection_scheme == "cenc") {
|
if (protection_scheme == "cenc") {
|
||||||
return edash_packager::media::kEncryptionModeAesCtr;
|
return edash_packager::media::FOURCC_cenc;
|
||||||
|
} else if (protection_scheme == "cens") {
|
||||||
|
return edash_packager::media::FOURCC_cens;
|
||||||
} else if (protection_scheme == "cbc1") {
|
} else if (protection_scheme == "cbc1") {
|
||||||
return edash_packager::media::kEncryptionModeAesCbc;
|
return edash_packager::media::FOURCC_cbc1;
|
||||||
|
} else if (protection_scheme == "cbcs") {
|
||||||
|
return edash_packager::media::FOURCC_cbcs;
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Unknown protection scheme: " << protection_scheme;
|
LOG(ERROR) << "Unknown protection scheme: " << protection_scheme;
|
||||||
return edash_packager::media::kEncryptionModeUnknown;
|
return edash_packager::media::FOURCC_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +314,7 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
||||||
FLAGS_max_sd_pixels,
|
FLAGS_max_sd_pixels,
|
||||||
FLAGS_clear_lead,
|
FLAGS_clear_lead,
|
||||||
FLAGS_crypto_period_duration,
|
FLAGS_crypto_period_duration,
|
||||||
GetEncryptionMode(FLAGS_protection_scheme));
|
GetProtectionScheme(FLAGS_protection_scheme));
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_ptr<MuxerListener> muxer_listener;
|
scoped_ptr<MuxerListener> muxer_listener;
|
||||||
|
@ -374,11 +378,11 @@ Status RunRemuxJobs(const std::vector<RemuxJob*>& remux_jobs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunPackager(const StreamDescriptorList& stream_descriptors) {
|
bool RunPackager(const StreamDescriptorList& stream_descriptors) {
|
||||||
EncryptionMode encryption_mode = GetEncryptionMode(FLAGS_protection_scheme);
|
const FourCC protection_scheme = GetProtectionScheme(FLAGS_protection_scheme);
|
||||||
if (encryption_mode == kEncryptionModeUnknown)
|
if (protection_scheme == FOURCC_NULL)
|
||||||
return false;
|
return false;
|
||||||
if (encryption_mode == kEncryptionModeAesCbc && !FLAGS_iv.empty()) {
|
if (protection_scheme == FOURCC_cbc1 || protection_scheme == FOURCC_cbcs) {
|
||||||
if (FLAGS_iv.size() != 16) {
|
if (!FLAGS_iv.empty() && FLAGS_iv.size() != 16) {
|
||||||
LOG(ERROR) << "Iv size should be 16 bytes for CBC encryption mode.";
|
LOG(ERROR) << "Iv size should be 16 bytes for CBC encryption mode.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "packager/media/base/aes_cryptor.h"
|
#include "packager/media/base/aes_cryptor.h"
|
||||||
|
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/stl_util.h"
|
#include "packager/base/stl_util.h"
|
||||||
|
@ -53,6 +55,25 @@ size_t AesCryptor::NumPaddingBytes(size_t size) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AesCryptor::GenerateRandomIv(FourCC protection_scheme,
|
||||||
|
std::vector<uint8_t>* iv) {
|
||||||
|
// ISO/IEC 23001-7:2016 10.1 and 10.3 For 'cenc' and 'cens'
|
||||||
|
// default_Per_Sample_IV_Size and Per_Sample_IV_Size SHOULD be 8-bytes.
|
||||||
|
// There is no official guideline on the iv size for 'cbc1' and 'cbcs',
|
||||||
|
// but 16-byte provides better security.
|
||||||
|
const size_t iv_size =
|
||||||
|
(protection_scheme == FOURCC_cenc || protection_scheme == FOURCC_cens)
|
||||||
|
? 8
|
||||||
|
: 16;
|
||||||
|
iv->resize(iv_size);
|
||||||
|
if (RAND_bytes(iv->data(), iv_size) != 1) {
|
||||||
|
LOG(ERROR) << "RAND_bytes failed with error: "
|
||||||
|
<< ERR_error_string(ERR_get_error(), NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
} // namespace edash_packager
|
} // namespace edash_packager
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "packager/base/macros.h"
|
#include "packager/base/macros.h"
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
|
#include "packager/media/base/fourccs.h"
|
||||||
|
|
||||||
struct aes_key_st;
|
struct aes_key_st;
|
||||||
typedef struct aes_key_st AES_KEY;
|
typedef struct aes_key_st AES_KEY;
|
||||||
|
@ -58,6 +59,13 @@ class AesCryptor {
|
||||||
/// @return The current iv.
|
/// @return The current iv.
|
||||||
const std::vector<uint8_t>& iv() const { return iv_; }
|
const std::vector<uint8_t>& iv() const { return iv_; }
|
||||||
|
|
||||||
|
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
|
||||||
|
/// 'cbc1', 'cbcs', which is useful to determine the random iv size.
|
||||||
|
/// @param iv points to generated initialization vector.
|
||||||
|
/// @return true on success, false otherwise.
|
||||||
|
static bool GenerateRandomIv(FourCC protection_scheme,
|
||||||
|
std::vector<uint8_t>* iv);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_iv(const std::vector<uint8_t>& iv) { iv_ = iv; }
|
void set_iv(const std::vector<uint8_t>& iv) { iv_ = iv; }
|
||||||
const AES_KEY* aes_key() const { return aes_key_.get(); }
|
const AES_KEY* aes_key() const { return aes_key_.get(); }
|
||||||
|
|
|
@ -220,12 +220,12 @@ TEST_F(AesCtrEncryptorTest, 128BitIVBoundaryCaseEncryption) {
|
||||||
EXPECT_EQ(encrypted, encrypted_verify);
|
EXPECT_EQ(encrypted, encrypted_verify);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AesCtrEncryptorTest, InitWithRandomIv) {
|
TEST_F(AesCtrEncryptorTest, GenerateRandomIv) {
|
||||||
const uint8_t kIvSize = 8;
|
const uint8_t kCencIvSize = 8;
|
||||||
ASSERT_TRUE(encryptor_.InitializeWithRandomIv(key_, kIvSize));
|
std::vector<uint8_t> iv;
|
||||||
ASSERT_EQ(kIvSize, encryptor_.iv().size());
|
ASSERT_TRUE(AesCryptor::GenerateRandomIv(FOURCC_cenc, &iv));
|
||||||
LOG(INFO) << "Random IV: "
|
ASSERT_EQ(kCencIvSize, iv.size());
|
||||||
<< base::HexEncode(&encryptor_.iv()[0], encryptor_.iv().size());
|
LOG(INFO) << "Random IV: " << base::HexEncode(iv.data(), iv.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AesCtrEncryptorTest, UnsupportedKeySize) {
|
TEST_F(AesCtrEncryptorTest, UnsupportedKeySize) {
|
||||||
|
@ -238,10 +238,6 @@ TEST_F(AesCtrEncryptorTest, UnsupportedIV) {
|
||||||
ASSERT_FALSE(encryptor_.InitializeWithIv(key_, iv));
|
ASSERT_FALSE(encryptor_.InitializeWithIv(key_, iv));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AesCtrEncryptorTest, IncorrectIvSize) {
|
|
||||||
ASSERT_FALSE(encryptor_.InitializeWithRandomIv(key_, 15));
|
|
||||||
}
|
|
||||||
|
|
||||||
class AesCtrEncryptorSubsampleTest
|
class AesCtrEncryptorSubsampleTest
|
||||||
: public AesCtrEncryptorTest,
|
: public AesCtrEncryptorTest,
|
||||||
public ::testing::WithParamInterface<SubsampleTestCase> {};
|
public ::testing::WithParamInterface<SubsampleTestCase> {};
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
#include "packager/media/base/aes_encryptor.h"
|
#include "packager/media/base/aes_encryptor.h"
|
||||||
|
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/err.h>
|
|
||||||
#include <openssl/rand.h>
|
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
|
|
||||||
|
@ -40,17 +38,6 @@ namespace media {
|
||||||
AesEncryptor::AesEncryptor() {}
|
AesEncryptor::AesEncryptor() {}
|
||||||
AesEncryptor::~AesEncryptor() {}
|
AesEncryptor::~AesEncryptor() {}
|
||||||
|
|
||||||
bool AesEncryptor::InitializeWithRandomIv(const std::vector<uint8_t>& key,
|
|
||||||
uint8_t iv_size) {
|
|
||||||
std::vector<uint8_t> iv(iv_size, 0);
|
|
||||||
if (RAND_bytes(iv.data(), iv_size) != 1) {
|
|
||||||
LOG(ERROR) << "RAND_bytes failed with error: "
|
|
||||||
<< ERR_error_string(ERR_get_error(), NULL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return InitializeWithIv(key, iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AesEncryptor::InitializeWithIv(const std::vector<uint8_t>& key,
|
bool AesEncryptor::InitializeWithIv(const std::vector<uint8_t>& key,
|
||||||
const std::vector<uint8_t>& iv) {
|
const std::vector<uint8_t>& iv) {
|
||||||
if (!IsKeySizeValidForAes(key.size())) {
|
if (!IsKeySizeValidForAes(key.size())) {
|
||||||
|
|
|
@ -24,11 +24,6 @@ class AesEncryptor : public AesCryptor {
|
||||||
AesEncryptor();
|
AesEncryptor();
|
||||||
~AesEncryptor() override;
|
~AesEncryptor() override;
|
||||||
|
|
||||||
/// Initialize the encryptor with specified key and a random generated IV
|
|
||||||
/// of the specified size.
|
|
||||||
/// @return true on successful initialization, false otherwise.
|
|
||||||
bool InitializeWithRandomIv(const std::vector<uint8_t>& key, uint8_t iv_size);
|
|
||||||
|
|
||||||
/// Initialize the encryptor with specified key and IV.
|
/// Initialize the encryptor with specified key and IV.
|
||||||
/// @return true on successful initialization, false otherwise.
|
/// @return true on successful initialization, false otherwise.
|
||||||
bool InitializeWithIv(const std::vector<uint8_t>& key,
|
bool InitializeWithIv(const std::vector<uint8_t>& key,
|
||||||
|
|
|
@ -9,14 +9,19 @@
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
DecryptConfig::DecryptConfig(const std::vector<uint8_t>& key_id,
|
||||||
|
const std::vector<uint8_t>& iv,
|
||||||
|
const std::vector<SubsampleEntry>& subsamples)
|
||||||
|
: DecryptConfig(key_id, iv, subsamples, FOURCC_cenc) {}
|
||||||
|
|
||||||
DecryptConfig::DecryptConfig(const std::vector<uint8_t>& key_id,
|
DecryptConfig::DecryptConfig(const std::vector<uint8_t>& key_id,
|
||||||
const std::vector<uint8_t>& iv,
|
const std::vector<uint8_t>& iv,
|
||||||
const std::vector<SubsampleEntry>& subsamples,
|
const std::vector<SubsampleEntry>& subsamples,
|
||||||
EncryptionMode decryption_mode)
|
FourCC protection_scheme)
|
||||||
: key_id_(key_id),
|
: key_id_(key_id),
|
||||||
iv_(iv),
|
iv_(iv),
|
||||||
subsamples_(subsamples),
|
subsamples_(subsamples),
|
||||||
decryption_mode_(decryption_mode) {
|
protection_scheme_(protection_scheme) {
|
||||||
CHECK_GT(key_id.size(), 0u);
|
CHECK_GT(key_id.size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
@ -42,23 +42,35 @@ class DecryptConfig {
|
||||||
/// Keys are always 128 bits.
|
/// Keys are always 128 bits.
|
||||||
static const size_t kDecryptionKeySize = 16;
|
static const size_t kDecryptionKeySize = 16;
|
||||||
|
|
||||||
|
/// Create a 'cenc' decrypt config.
|
||||||
/// @param key_id is the ID that references the decryption key.
|
/// @param key_id is the ID that references the decryption key.
|
||||||
/// @param iv is the initialization vector defined by the encryptor.
|
/// @param iv is the initialization vector defined by the encryptor.
|
||||||
/// @param subsamples defines the clear and encrypted portions of the sample
|
/// @param subsamples defines the clear and encrypted portions of the sample
|
||||||
/// as described in SubsampleEntry. A decrypted buffer will be equal
|
/// as described in SubsampleEntry. A decrypted buffer will be equal
|
||||||
/// in size to the sum of the subsample sizes.
|
/// in size to the sum of the subsample sizes.
|
||||||
/// @param decryption_mode decryption_mode is to determine which decryptor to
|
DecryptConfig(const std::vector<uint8_t>& key_id,
|
||||||
/// use.
|
const std::vector<uint8_t>& iv,
|
||||||
|
const std::vector<SubsampleEntry>& subsamples);
|
||||||
|
|
||||||
|
/// Create a general decrypt config with possible pattern-based encryption.
|
||||||
|
/// @param key_id is the ID that references the decryption key.
|
||||||
|
/// @param iv is the initialization vector defined by the encryptor.
|
||||||
|
/// @param subsamples defines the clear and encrypted portions of the sample
|
||||||
|
/// as described in SubsampleEntry. A decrypted buffer will be equal
|
||||||
|
/// in size to the sum of the subsample sizes.
|
||||||
|
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
|
||||||
|
/// 'cbc1', 'cbcs'.
|
||||||
DecryptConfig(const std::vector<uint8_t>& key_id,
|
DecryptConfig(const std::vector<uint8_t>& key_id,
|
||||||
const std::vector<uint8_t>& iv,
|
const std::vector<uint8_t>& iv,
|
||||||
const std::vector<SubsampleEntry>& subsamples,
|
const std::vector<SubsampleEntry>& subsamples,
|
||||||
EncryptionMode decryption_mode);
|
FourCC protection_scheme);
|
||||||
|
|
||||||
~DecryptConfig();
|
~DecryptConfig();
|
||||||
|
|
||||||
const std::vector<uint8_t>& key_id() const { return key_id_; }
|
const std::vector<uint8_t>& key_id() const { return key_id_; }
|
||||||
const std::vector<uint8_t>& iv() const { return iv_; }
|
const std::vector<uint8_t>& iv() const { return iv_; }
|
||||||
const std::vector<SubsampleEntry>& subsamples() const { return subsamples_; }
|
const std::vector<SubsampleEntry>& subsamples() const { return subsamples_; }
|
||||||
EncryptionMode decryption_mode() const { return decryption_mode_; }
|
FourCC protection_scheme() const { return protection_scheme_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<uint8_t> key_id_;
|
const std::vector<uint8_t> key_id_;
|
||||||
|
@ -70,7 +82,7 @@ class DecryptConfig {
|
||||||
// (less data ignored by data_offset_) is encrypted.
|
// (less data ignored by data_offset_) is encrypted.
|
||||||
const std::vector<SubsampleEntry> subsamples_;
|
const std::vector<SubsampleEntry> subsamples_;
|
||||||
|
|
||||||
EncryptionMode decryption_mode_;
|
const FourCC protection_scheme_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(DecryptConfig);
|
DISALLOW_COPY_AND_ASSIGN(DecryptConfig);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/stl_util.h"
|
#include "packager/base/stl_util.h"
|
||||||
|
#include "packager/media/base/aes_decryptor.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
@ -39,16 +40,16 @@ bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_ptr<AesCryptor> aes_decryptor;
|
scoped_ptr<AesCryptor> aes_decryptor;
|
||||||
switch (decrypt_config->decryption_mode()) {
|
switch (decrypt_config->protection_scheme()) {
|
||||||
case kEncryptionModeAesCtr:
|
case FOURCC_cenc:
|
||||||
aes_decryptor.reset(new AesCtrDecryptor);
|
aes_decryptor.reset(new AesCtrDecryptor);
|
||||||
break;
|
break;
|
||||||
case kEncryptionModeAesCbc:
|
case FOURCC_cbc1:
|
||||||
aes_decryptor.reset(new AesCbcDecryptor(kNoPadding, kChainAcrossCalls));
|
aes_decryptor.reset(new AesCbcDecryptor(kNoPadding, kChainAcrossCalls));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(ERROR) << "Unsupported Decryption Mode: "
|
LOG(ERROR) << "Unsupported protection scheme: "
|
||||||
<< decrypt_config->decryption_mode();
|
<< decrypt_config->protection_scheme();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,10 +81,9 @@ TEST_F(DecryptorSourceTest, FullSampleDecryption) {
|
||||||
|
|
||||||
DecryptConfig decrypt_config(key_id_,
|
DecryptConfig decrypt_config(key_id_,
|
||||||
std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
||||||
std::vector<SubsampleEntry>(),
|
std::vector<SubsampleEntry>());
|
||||||
kEncryptionModeAesCtr);
|
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
|
||||||
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(&decrypt_config, &buffer_[0],
|
&decrypt_config, &buffer_[0], buffer_.size()));
|
||||||
buffer_.size()));
|
|
||||||
EXPECT_EQ(std::vector<uint8_t>(
|
EXPECT_EQ(std::vector<uint8_t>(
|
||||||
kExpectedDecryptedBuffer,
|
kExpectedDecryptedBuffer,
|
||||||
kExpectedDecryptedBuffer + arraysize(kExpectedDecryptedBuffer)),
|
kExpectedDecryptedBuffer + arraysize(kExpectedDecryptedBuffer)),
|
||||||
|
@ -95,7 +94,7 @@ TEST_F(DecryptorSourceTest, FullSampleDecryption) {
|
||||||
buffer_.assign(kBuffer2, kBuffer2 + arraysize(kBuffer2));
|
buffer_.assign(kBuffer2, kBuffer2 + arraysize(kBuffer2));
|
||||||
DecryptConfig decrypt_config2(
|
DecryptConfig decrypt_config2(
|
||||||
key_id_, std::vector<uint8_t>(kIv2, kIv2 + arraysize(kIv2)),
|
key_id_, std::vector<uint8_t>(kIv2, kIv2 + arraysize(kIv2)),
|
||||||
std::vector<SubsampleEntry>(), kEncryptionModeAesCtr);
|
std::vector<SubsampleEntry>());
|
||||||
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
|
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
|
||||||
&decrypt_config2, &buffer_[0], buffer_.size()));
|
&decrypt_config2, &buffer_[0], buffer_.size()));
|
||||||
EXPECT_EQ(std::vector<uint8_t>(kExpectedDecryptedBuffer2,
|
EXPECT_EQ(std::vector<uint8_t>(kExpectedDecryptedBuffer2,
|
||||||
|
@ -130,8 +129,7 @@ TEST_F(DecryptorSourceTest, SubsampleDecryption) {
|
||||||
DecryptConfig decrypt_config(
|
DecryptConfig decrypt_config(
|
||||||
key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
||||||
std::vector<SubsampleEntry>(kSubsamples,
|
std::vector<SubsampleEntry>(kSubsamples,
|
||||||
kSubsamples + arraysize(kSubsamples)),
|
kSubsamples + arraysize(kSubsamples)));
|
||||||
kEncryptionModeAesCtr);
|
|
||||||
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
|
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
|
||||||
&decrypt_config, &buffer_[0], buffer_.size()));
|
&decrypt_config, &buffer_[0], buffer_.size()));
|
||||||
EXPECT_EQ(std::vector<uint8_t>(
|
EXPECT_EQ(std::vector<uint8_t>(
|
||||||
|
@ -155,8 +153,7 @@ TEST_F(DecryptorSourceTest, SubsampleDecryptionSizeValidation) {
|
||||||
DecryptConfig decrypt_config(
|
DecryptConfig decrypt_config(
|
||||||
key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
||||||
std::vector<SubsampleEntry>(kSubsamples,
|
std::vector<SubsampleEntry>(kSubsamples,
|
||||||
kSubsamples + arraysize(kSubsamples)),
|
kSubsamples + arraysize(kSubsamples)));
|
||||||
kEncryptionModeAesCtr);
|
|
||||||
ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer(
|
ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer(
|
||||||
&decrypt_config, &buffer_[0], buffer_.size()));
|
&decrypt_config, &buffer_[0], buffer_.size()));
|
||||||
}
|
}
|
||||||
|
@ -167,8 +164,7 @@ TEST_F(DecryptorSourceTest, DecryptFailedIfGetKeyFailed) {
|
||||||
|
|
||||||
DecryptConfig decrypt_config(key_id_,
|
DecryptConfig decrypt_config(key_id_,
|
||||||
std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
|
||||||
std::vector<SubsampleEntry>(),
|
std::vector<SubsampleEntry>());
|
||||||
kEncryptionModeAesCtr);
|
|
||||||
ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer(
|
ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer(
|
||||||
&decrypt_config, &buffer_[0], buffer_.size()));
|
&decrypt_config, &buffer_[0], buffer_.size()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
// Copyright 2016 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 MEDIA_BASE_ENCRYPTION_MODE_H_
|
|
||||||
#define MEDIA_BASE_ENCRYPTION_MODE_H_
|
|
||||||
|
|
||||||
namespace edash_packager {
|
|
||||||
namespace media {
|
|
||||||
|
|
||||||
/// Supported encryption mode.
|
|
||||||
enum EncryptionMode {
|
|
||||||
kEncryptionModeUnknown,
|
|
||||||
kEncryptionModeAesCtr,
|
|
||||||
kEncryptionModeAesCbc
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace media
|
|
||||||
} // namespace edash_packager
|
|
||||||
|
|
||||||
#endif // MEDIA_BASE_ENCRYPTION_MODE_H_
|
|
|
@ -21,7 +21,9 @@ enum FourCC {
|
||||||
FOURCC_avcC = 0x61766343,
|
FOURCC_avcC = 0x61766343,
|
||||||
FOURCC_bloc = 0x626C6F63,
|
FOURCC_bloc = 0x626C6F63,
|
||||||
FOURCC_cbc1 = 0x63626331,
|
FOURCC_cbc1 = 0x63626331,
|
||||||
|
FOURCC_cbcs = 0x63626373,
|
||||||
FOURCC_cenc = 0x63656e63,
|
FOURCC_cenc = 0x63656e63,
|
||||||
|
FOURCC_cens = 0x63656e73,
|
||||||
FOURCC_co64 = 0x636f3634,
|
FOURCC_co64 = 0x636f3634,
|
||||||
FOURCC_ctim = 0x6374696d,
|
FOURCC_ctim = 0x6374696d,
|
||||||
FOURCC_ctts = 0x63747473,
|
FOURCC_ctts = 0x63747473,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "packager/media/base/muxer.h"
|
#include "packager/media/base/muxer.h"
|
||||||
|
|
||||||
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/media_sample.h"
|
#include "packager/media/base/media_sample.h"
|
||||||
#include "packager/media/base/media_stream.h"
|
#include "packager/media/base/media_stream.h"
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ Muxer::Muxer(const MuxerOptions& options)
|
||||||
max_sd_pixels_(0),
|
max_sd_pixels_(0),
|
||||||
clear_lead_in_seconds_(0),
|
clear_lead_in_seconds_(0),
|
||||||
crypto_period_duration_in_seconds_(0),
|
crypto_period_duration_in_seconds_(0),
|
||||||
encryption_mode_(kEncryptionModeUnknown),
|
protection_scheme_(FOURCC_NULL),
|
||||||
cancelled_(false),
|
cancelled_(false),
|
||||||
clock_(NULL) {}
|
clock_(NULL) {}
|
||||||
|
|
||||||
|
@ -29,13 +30,13 @@ void Muxer::SetKeySource(KeySource* encryption_key_source,
|
||||||
uint32_t max_sd_pixels,
|
uint32_t max_sd_pixels,
|
||||||
double clear_lead_in_seconds,
|
double clear_lead_in_seconds,
|
||||||
double crypto_period_duration_in_seconds,
|
double crypto_period_duration_in_seconds,
|
||||||
EncryptionMode encryption_mode) {
|
FourCC protection_scheme) {
|
||||||
DCHECK(encryption_key_source);
|
DCHECK(encryption_key_source);
|
||||||
encryption_key_source_ = encryption_key_source;
|
encryption_key_source_ = encryption_key_source;
|
||||||
max_sd_pixels_ = max_sd_pixels;
|
max_sd_pixels_ = max_sd_pixels;
|
||||||
clear_lead_in_seconds_ = clear_lead_in_seconds;
|
clear_lead_in_seconds_ = clear_lead_in_seconds;
|
||||||
crypto_period_duration_in_seconds_ = crypto_period_duration_in_seconds;
|
crypto_period_duration_in_seconds_ = crypto_period_duration_in_seconds;
|
||||||
encryption_mode_ = encryption_mode;
|
protection_scheme_ = protection_scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Muxer::AddStream(MediaStream* stream) {
|
void Muxer::AddStream(MediaStream* stream) {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "packager/base/memory/ref_counted.h"
|
#include "packager/base/memory/ref_counted.h"
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "packager/base/time/clock.h"
|
#include "packager/base/time/clock.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/muxer_options.h"
|
#include "packager/media/base/muxer_options.h"
|
||||||
#include "packager/media/base/status.h"
|
#include "packager/media/base/status.h"
|
||||||
#include "packager/media/event/muxer_listener.h"
|
#include "packager/media/event/muxer_listener.h"
|
||||||
|
@ -45,11 +45,13 @@ class Muxer {
|
||||||
/// @param crypto_period_duration_in_seconds specifies crypto period duration
|
/// @param crypto_period_duration_in_seconds specifies crypto period duration
|
||||||
/// in seconds. A positive value means key rotation is enabled, the
|
/// in seconds. A positive value means key rotation is enabled, the
|
||||||
/// key source must support key rotation in this case.
|
/// key source must support key rotation in this case.
|
||||||
|
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
|
||||||
|
/// 'cbc1', 'cbcs'.
|
||||||
void SetKeySource(KeySource* encryption_key_source,
|
void SetKeySource(KeySource* encryption_key_source,
|
||||||
uint32_t max_sd_pixels,
|
uint32_t max_sd_pixels,
|
||||||
double clear_lead_in_seconds,
|
double clear_lead_in_seconds,
|
||||||
double crypto_period_duration_in_seconds,
|
double crypto_period_duration_in_seconds,
|
||||||
EncryptionMode encryption_mode);
|
FourCC protection_scheme);
|
||||||
|
|
||||||
/// Add video/audio stream.
|
/// Add video/audio stream.
|
||||||
void AddStream(MediaStream* stream);
|
void AddStream(MediaStream* stream);
|
||||||
|
@ -94,7 +96,7 @@ class Muxer {
|
||||||
MuxerListener* muxer_listener() { return muxer_listener_.get(); }
|
MuxerListener* muxer_listener() { return muxer_listener_.get(); }
|
||||||
ProgressListener* progress_listener() { return progress_listener_.get(); }
|
ProgressListener* progress_listener() { return progress_listener_.get(); }
|
||||||
base::Clock* clock() { return clock_; }
|
base::Clock* clock() { return clock_; }
|
||||||
EncryptionMode encryption_mode() const { return encryption_mode_; }
|
FourCC protection_scheme() const { return protection_scheme_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MediaStream; // Needed to access AddSample.
|
friend class MediaStream; // Needed to access AddSample.
|
||||||
|
@ -120,7 +122,7 @@ class Muxer {
|
||||||
uint32_t max_sd_pixels_;
|
uint32_t max_sd_pixels_;
|
||||||
double clear_lead_in_seconds_;
|
double clear_lead_in_seconds_;
|
||||||
double crypto_period_duration_in_seconds_;
|
double crypto_period_duration_in_seconds_;
|
||||||
EncryptionMode encryption_mode_;
|
FourCC protection_scheme_;
|
||||||
bool cancelled_;
|
bool cancelled_;
|
||||||
|
|
||||||
scoped_ptr<MuxerListener> muxer_listener_;
|
scoped_ptr<MuxerListener> muxer_listener_;
|
||||||
|
|
|
@ -22,9 +22,6 @@ namespace media {
|
||||||
namespace mp4 {
|
namespace mp4 {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Generate 64bit IV by default.
|
|
||||||
const size_t kDefaultIvSizeForCtr = 8u;
|
|
||||||
const size_t kDefaultIvSizeForCbc = 16u;
|
|
||||||
const size_t kCencBlockSize = 16u;
|
const size_t kCencBlockSize = 16u;
|
||||||
|
|
||||||
// Adds one or more subsamples to |*subsamples|. This may add more than one
|
// Adds one or more subsamples to |*subsamples|. This may add more than one
|
||||||
|
@ -66,14 +63,14 @@ EncryptingFragmenter::EncryptingFragmenter(
|
||||||
TrackFragment* traf,
|
TrackFragment* traf,
|
||||||
scoped_ptr<EncryptionKey> encryption_key,
|
scoped_ptr<EncryptionKey> encryption_key,
|
||||||
int64_t clear_time,
|
int64_t clear_time,
|
||||||
EncryptionMode encryption_mode)
|
FourCC protection_scheme)
|
||||||
: Fragmenter(traf),
|
: Fragmenter(traf),
|
||||||
info_(info),
|
info_(info),
|
||||||
encryption_key_(encryption_key.Pass()),
|
encryption_key_(encryption_key.Pass()),
|
||||||
nalu_length_size_(GetNaluLengthSize(*info)),
|
nalu_length_size_(GetNaluLengthSize(*info)),
|
||||||
video_codec_(GetVideoCodec(*info)),
|
video_codec_(GetVideoCodec(*info)),
|
||||||
clear_time_(clear_time),
|
clear_time_(clear_time),
|
||||||
encryption_mode_(encryption_mode) {
|
protection_scheme_(protection_scheme) {
|
||||||
DCHECK(encryption_key_);
|
DCHECK(encryption_key_);
|
||||||
if (video_codec_ == kCodecVP8) {
|
if (video_codec_ == kCodecVP8) {
|
||||||
vpx_parser_.reset(new VP8Parser);
|
vpx_parser_.reset(new VP8Parser);
|
||||||
|
@ -175,22 +172,21 @@ void EncryptingFragmenter::FinalizeFragmentForEncryption() {
|
||||||
|
|
||||||
Status EncryptingFragmenter::CreateEncryptor() {
|
Status EncryptingFragmenter::CreateEncryptor() {
|
||||||
DCHECK(encryption_key_);
|
DCHECK(encryption_key_);
|
||||||
scoped_ptr<AesEncryptor> encryptor;
|
scoped_ptr<AesCryptor> encryptor;
|
||||||
size_t default_iv_size = 0;
|
switch (protection_scheme_) {
|
||||||
if (encryption_mode_ == kEncryptionModeAesCtr) {
|
case FOURCC_cenc:
|
||||||
encryptor.reset(new AesCtrEncryptor);
|
encryptor.reset(new AesCtrEncryptor);
|
||||||
default_iv_size = kDefaultIvSizeForCtr;
|
break;
|
||||||
} else if (encryption_mode_ == kEncryptionModeAesCbc) {
|
case FOURCC_cbc1:
|
||||||
encryptor.reset(new AesCbcEncryptor(kNoPadding, kChainAcrossCalls));
|
encryptor.reset(new AesCbcEncryptor(kNoPadding, kChainAcrossCalls));
|
||||||
default_iv_size = kDefaultIvSizeForCbc;
|
break;
|
||||||
} else {
|
default:
|
||||||
return Status(error::MUXER_FAILURE, "Unsupported encryption mode.");
|
return Status(error::MUXER_FAILURE, "Unsupported protection scheme.");
|
||||||
}
|
}
|
||||||
const bool initialized = encryption_key_->iv.empty()
|
|
||||||
? encryptor->InitializeWithRandomIv(
|
DCHECK(!encryption_key_->iv.empty());
|
||||||
encryption_key_->key, default_iv_size)
|
const bool initialized =
|
||||||
: encryptor->InitializeWithIv(
|
encryptor->InitializeWithIv(encryption_key_->key, encryption_key_->iv);
|
||||||
encryption_key_->key, encryption_key_->iv);
|
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
return Status(error::MUXER_FAILURE, "Failed to create the encryptor.");
|
return Status(error::MUXER_FAILURE, "Failed to create the encryptor.");
|
||||||
encryptor_ = encryptor.Pass();
|
encryptor_ = encryptor.Pass();
|
||||||
|
@ -229,7 +225,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
|
||||||
// within the superframe.
|
// within the superframe.
|
||||||
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately so
|
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately so
|
||||||
// that the cipher data is block aligned.
|
// that the cipher data is block aligned.
|
||||||
if (is_superframe || encryption_mode_ == kEncryptionModeAesCbc) {
|
if (is_superframe || protection_scheme_ == FOURCC_cbc1) {
|
||||||
const uint16_t misalign_bytes =
|
const uint16_t misalign_bytes =
|
||||||
subsample.cipher_bytes % kCencBlockSize;
|
subsample.cipher_bytes % kCencBlockSize;
|
||||||
subsample.clear_bytes += misalign_bytes;
|
subsample.clear_bytes += misalign_bytes;
|
||||||
|
@ -271,7 +267,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
|
||||||
|
|
||||||
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately
|
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately
|
||||||
// so that the cipher data is block aligned.
|
// so that the cipher data is block aligned.
|
||||||
if (encryption_mode_ == kEncryptionModeAesCbc) {
|
if (protection_scheme_ == FOURCC_cbc1) {
|
||||||
const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
|
const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
|
||||||
current_clear_bytes += misalign_bytes;
|
current_clear_bytes += misalign_bytes;
|
||||||
cipher_bytes -= misalign_bytes;
|
cipher_bytes -= misalign_bytes;
|
||||||
|
@ -303,7 +299,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
|
||||||
uint64_t encryption_data_size = sample->data_size();
|
uint64_t encryption_data_size = sample->data_size();
|
||||||
// AES-CBC mode requires all encrypted cipher blocks to be 16 bytes. The
|
// AES-CBC mode requires all encrypted cipher blocks to be 16 bytes. The
|
||||||
// partial blocks are left unencrypted.
|
// partial blocks are left unencrypted.
|
||||||
if (encryption_mode_ == kEncryptionModeAesCbc)
|
if (protection_scheme_ == FOURCC_cbc1)
|
||||||
encryption_data_size -= encryption_data_size % kCencBlockSize;
|
encryption_data_size -= encryption_data_size % kCencBlockSize;
|
||||||
EncryptBytes(data, encryption_data_size);
|
EncryptBytes(data, encryption_data_size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "packager/base/memory/ref_counted.h"
|
#include "packager/base/memory/ref_counted.h"
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/filters/vpx_parser.h"
|
#include "packager/media/filters/vpx_parser.h"
|
||||||
#include "packager/media/formats/mp4/fragmenter.h"
|
#include "packager/media/formats/mp4/fragmenter.h"
|
||||||
#include "packager/media/formats/mp4/video_slice_header_parser.h"
|
#include "packager/media/formats/mp4/video_slice_header_parser.h"
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class AesEncryptor;
|
class AesCryptor;
|
||||||
class StreamInfo;
|
class StreamInfo;
|
||||||
struct EncryptionKey;
|
struct EncryptionKey;
|
||||||
|
|
||||||
|
@ -30,11 +30,13 @@ class EncryptingFragmenter : public Fragmenter {
|
||||||
/// @param encryption_key contains the encryption parameters.
|
/// @param encryption_key contains the encryption parameters.
|
||||||
/// @param clear_time specifies clear lead duration in units of the current
|
/// @param clear_time specifies clear lead duration in units of the current
|
||||||
/// track's timescale.
|
/// track's timescale.
|
||||||
|
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
|
||||||
|
/// 'cbc1', 'cbcs'.
|
||||||
EncryptingFragmenter(scoped_refptr<StreamInfo> info,
|
EncryptingFragmenter(scoped_refptr<StreamInfo> info,
|
||||||
TrackFragment* traf,
|
TrackFragment* traf,
|
||||||
scoped_ptr<EncryptionKey> encryption_key,
|
scoped_ptr<EncryptionKey> encryption_key,
|
||||||
int64_t clear_time,
|
int64_t clear_time,
|
||||||
EncryptionMode encryption_mode);
|
FourCC protection_scheme);
|
||||||
|
|
||||||
~EncryptingFragmenter() override;
|
~EncryptingFragmenter() override;
|
||||||
|
|
||||||
|
@ -57,8 +59,9 @@ class EncryptingFragmenter : public Fragmenter {
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
Status CreateEncryptor();
|
Status CreateEncryptor();
|
||||||
|
|
||||||
EncryptionKey* encryption_key() { return encryption_key_.get(); }
|
const EncryptionKey* encryption_key() const { return encryption_key_.get(); }
|
||||||
AesEncryptor* encryptor() { return encryptor_.get(); }
|
AesCryptor* encryptor() { return encryptor_.get(); }
|
||||||
|
FourCC protection_scheme() const { return protection_scheme_; }
|
||||||
|
|
||||||
void set_encryption_key(scoped_ptr<EncryptionKey> encryption_key) {
|
void set_encryption_key(scoped_ptr<EncryptionKey> encryption_key) {
|
||||||
encryption_key_ = encryption_key.Pass();
|
encryption_key_ = encryption_key.Pass();
|
||||||
|
@ -73,14 +76,14 @@ class EncryptingFragmenter : public Fragmenter {
|
||||||
|
|
||||||
scoped_refptr<StreamInfo> info_;
|
scoped_refptr<StreamInfo> info_;
|
||||||
scoped_ptr<EncryptionKey> encryption_key_;
|
scoped_ptr<EncryptionKey> encryption_key_;
|
||||||
scoped_ptr<AesEncryptor> encryptor_;
|
scoped_ptr<AesCryptor> encryptor_;
|
||||||
// If this stream contains AVC, subsample encryption specifies that the size
|
// If this stream contains AVC, subsample encryption specifies that the size
|
||||||
// and type of NAL units remain unencrypted. This function returns the size of
|
// and type of NAL units remain unencrypted. This function returns the size of
|
||||||
// the size field in bytes. Can be 1, 2 or 4 bytes.
|
// the size field in bytes. Can be 1, 2 or 4 bytes.
|
||||||
const uint8_t nalu_length_size_;
|
const uint8_t nalu_length_size_;
|
||||||
const VideoCodec video_codec_;
|
const VideoCodec video_codec_;
|
||||||
int64_t clear_time_;
|
int64_t clear_time_;
|
||||||
EncryptionMode encryption_mode_;
|
FourCC protection_scheme_;
|
||||||
|
|
||||||
scoped_ptr<VPxParser> vpx_parser_;
|
scoped_ptr<VPxParser> vpx_parser_;
|
||||||
scoped_ptr<VideoSliceHeaderParser> header_parser_;
|
scoped_ptr<VideoSliceHeaderParser> header_parser_;
|
||||||
|
|
|
@ -24,13 +24,13 @@ KeyRotationFragmenter::KeyRotationFragmenter(MovieFragment* moof,
|
||||||
KeySource::TrackType track_type,
|
KeySource::TrackType track_type,
|
||||||
int64_t crypto_period_duration,
|
int64_t crypto_period_duration,
|
||||||
int64_t clear_time,
|
int64_t clear_time,
|
||||||
MuxerListener* muxer_listener,
|
FourCC protection_scheme,
|
||||||
EncryptionMode encryption_mode)
|
MuxerListener* muxer_listener)
|
||||||
: EncryptingFragmenter(info,
|
: EncryptingFragmenter(info,
|
||||||
traf,
|
traf,
|
||||||
scoped_ptr<EncryptionKey>(new EncryptionKey()),
|
scoped_ptr<EncryptionKey>(new EncryptionKey()),
|
||||||
clear_time,
|
clear_time,
|
||||||
encryption_mode),
|
protection_scheme),
|
||||||
moof_(moof),
|
moof_(moof),
|
||||||
encryption_key_source_(encryption_key_source),
|
encryption_key_source_(encryption_key_source),
|
||||||
track_type_(track_type),
|
track_type_(track_type),
|
||||||
|
@ -55,6 +55,12 @@ Status KeyRotationFragmenter::PrepareFragmentForEncryption(
|
||||||
current_crypto_period_index, track_type_, encryption_key.get());
|
current_crypto_period_index, track_type_, encryption_key.get());
|
||||||
if (!status.ok())
|
if (!status.ok())
|
||||||
return status;
|
return status;
|
||||||
|
if (encryption_key->iv.empty()) {
|
||||||
|
if (!AesCryptor::GenerateRandomIv(protection_scheme(),
|
||||||
|
&encryption_key->iv)) {
|
||||||
|
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
|
||||||
|
}
|
||||||
|
}
|
||||||
set_encryption_key(encryption_key.Pass());
|
set_encryption_key(encryption_key.Pass());
|
||||||
prev_crypto_period_index_ = current_crypto_period_index;
|
prev_crypto_period_index_ = current_crypto_period_index;
|
||||||
need_to_refresh_encryptor = true;
|
need_to_refresh_encryptor = true;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#ifndef MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_
|
#ifndef MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_
|
||||||
#define MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_
|
#define MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_
|
||||||
|
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/key_source.h"
|
#include "packager/media/base/key_source.h"
|
||||||
#include "packager/media/event/muxer_listener.h"
|
#include "packager/media/event/muxer_listener.h"
|
||||||
#include "packager/media/formats/mp4/encrypting_fragmenter.h"
|
#include "packager/media/formats/mp4/encrypting_fragmenter.h"
|
||||||
|
@ -32,6 +32,8 @@ class KeyRotationFragmenter : public EncryptingFragmenter {
|
||||||
/// of the current track's timescale.
|
/// of the current track's timescale.
|
||||||
/// @param clear_time specifies clear lead duration in units of the current
|
/// @param clear_time specifies clear lead duration in units of the current
|
||||||
/// track's timescale.
|
/// track's timescale.
|
||||||
|
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
|
||||||
|
/// 'cbc1', 'cbcs'.
|
||||||
/// @param muxer_listener is a pointer to MuxerListener for notifying
|
/// @param muxer_listener is a pointer to MuxerListener for notifying
|
||||||
/// muxer related events. This may be null.
|
/// muxer related events. This may be null.
|
||||||
KeyRotationFragmenter(MovieFragment* moof,
|
KeyRotationFragmenter(MovieFragment* moof,
|
||||||
|
@ -41,8 +43,8 @@ class KeyRotationFragmenter : public EncryptingFragmenter {
|
||||||
KeySource::TrackType track_type,
|
KeySource::TrackType track_type,
|
||||||
int64_t crypto_period_duration,
|
int64_t crypto_period_duration,
|
||||||
int64_t clear_time,
|
int64_t clear_time,
|
||||||
MuxerListener* muxer_listener,
|
FourCC protection_scheme,
|
||||||
EncryptionMode encryption_mode);
|
MuxerListener* muxer_listener);
|
||||||
~KeyRotationFragmenter() override;
|
~KeyRotationFragmenter() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -147,15 +147,10 @@ Status MP4Muxer::Initialize() {
|
||||||
new MultiSegmentSegmenter(options(), ftyp.Pass(), moov.Pass()));
|
new MultiSegmentSegmenter(options(), ftyp.Pass(), moov.Pass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Status segmenter_initialized =
|
const Status segmenter_initialized = segmenter_->Initialize(
|
||||||
segmenter_->Initialize(streams(),
|
streams(), muxer_listener(), progress_listener(), encryption_key_source(),
|
||||||
muxer_listener(),
|
max_sd_pixels(), clear_lead_in_seconds(),
|
||||||
progress_listener(),
|
crypto_period_duration_in_seconds(), protection_scheme());
|
||||||
encryption_key_source(),
|
|
||||||
max_sd_pixels(),
|
|
||||||
clear_lead_in_seconds(),
|
|
||||||
crypto_period_duration_in_seconds(),
|
|
||||||
encryption_mode());
|
|
||||||
|
|
||||||
if (!segmenter_initialized.ok())
|
if (!segmenter_initialized.ok())
|
||||||
return segmenter_initialized;
|
return segmenter_initialized;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "packager/base/stl_util.h"
|
#include "packager/base/stl_util.h"
|
||||||
|
#include "packager/media/base/aes_cryptor.h"
|
||||||
#include "packager/media/base/buffer_writer.h"
|
#include "packager/media/base/buffer_writer.h"
|
||||||
#include "packager/media/base/key_source.h"
|
#include "packager/media/base/key_source.h"
|
||||||
#include "packager/media/base/media_sample.h"
|
#include "packager/media/base/media_sample.h"
|
||||||
|
@ -26,8 +27,6 @@ namespace mp4 {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Generate 64bit IV by default.
|
|
||||||
const size_t kDefaultIvSize = 8u;
|
|
||||||
const size_t kCencKeyIdSize = 16u;
|
const size_t kCencKeyIdSize = 16u;
|
||||||
|
|
||||||
// The version of cenc implemented here. CENC 4.
|
// The version of cenc implemented here. CENC 4.
|
||||||
|
@ -50,26 +49,24 @@ uint64_t Rescale(uint64_t time_in_old_scale,
|
||||||
|
|
||||||
void GenerateSinf(const EncryptionKey& encryption_key,
|
void GenerateSinf(const EncryptionKey& encryption_key,
|
||||||
FourCC old_type,
|
FourCC old_type,
|
||||||
EncryptionMode encryption_mode,
|
FourCC protection_scheme,
|
||||||
ProtectionSchemeInfo* sinf) {
|
ProtectionSchemeInfo* sinf) {
|
||||||
sinf->format.format = old_type;
|
sinf->format.format = old_type;
|
||||||
|
|
||||||
if (encryption_mode == kEncryptionModeAesCtr){
|
DCHECK_NE(protection_scheme, FOURCC_NULL);
|
||||||
sinf->type.type = FOURCC_cenc;
|
sinf->type.type = protection_scheme;
|
||||||
} else if (encryption_mode == kEncryptionModeAesCbc) {
|
|
||||||
sinf->type.type = FOURCC_cbc1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sinf->type.version = kCencSchemeVersion;
|
sinf->type.version = kCencSchemeVersion;
|
||||||
sinf->info.track_encryption.is_encrypted = true;
|
|
||||||
sinf->info.track_encryption.default_iv_size =
|
auto& track_encryption = sinf->info.track_encryption;
|
||||||
encryption_key.iv.empty() ? kDefaultIvSize : encryption_key.iv.size();
|
track_encryption.is_encrypted = true;
|
||||||
sinf->info.track_encryption.default_kid = encryption_key.key_id;
|
DCHECK(!encryption_key.iv.empty());
|
||||||
|
track_encryption.default_iv_size = encryption_key.iv.size();
|
||||||
|
track_encryption.default_kid = encryption_key.key_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
|
void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
|
||||||
double clear_lead_in_seconds,
|
double clear_lead_in_seconds,
|
||||||
EncryptionMode encryption_mode,
|
FourCC protection_scheme,
|
||||||
SampleDescription* description) {
|
SampleDescription* description) {
|
||||||
DCHECK(description);
|
DCHECK(description);
|
||||||
if (description->type == kVideo) {
|
if (description->type == kVideo) {
|
||||||
|
@ -81,7 +78,7 @@ void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
|
||||||
|
|
||||||
// Convert the first entry to an encrypted entry.
|
// Convert the first entry to an encrypted entry.
|
||||||
VideoSampleEntry& entry = description->video_entries[0];
|
VideoSampleEntry& entry = description->video_entries[0];
|
||||||
GenerateSinf(encryption_key, entry.format, encryption_mode, &entry.sinf);
|
GenerateSinf(encryption_key, entry.format, protection_scheme, &entry.sinf);
|
||||||
entry.format = FOURCC_encv;
|
entry.format = FOURCC_encv;
|
||||||
} else {
|
} else {
|
||||||
DCHECK_EQ(kAudio, description->type);
|
DCHECK_EQ(kAudio, description->type);
|
||||||
|
@ -93,7 +90,7 @@ void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
|
||||||
|
|
||||||
// Convert the first entry to an encrypted entry.
|
// Convert the first entry to an encrypted entry.
|
||||||
AudioSampleEntry& entry = description->audio_entries[0];
|
AudioSampleEntry& entry = description->audio_entries[0];
|
||||||
GenerateSinf(encryption_key, entry.format, encryption_mode, &entry.sinf);
|
GenerateSinf(encryption_key, entry.format, protection_scheme, &entry.sinf);
|
||||||
entry.format = FOURCC_enca;
|
entry.format = FOURCC_enca;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +134,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
|
||||||
uint32_t max_sd_pixels,
|
uint32_t max_sd_pixels,
|
||||||
double clear_lead_in_seconds,
|
double clear_lead_in_seconds,
|
||||||
double crypto_period_duration_in_seconds,
|
double crypto_period_duration_in_seconds,
|
||||||
EncryptionMode encryption_mode) {
|
FourCC protection_scheme) {
|
||||||
DCHECK_LT(0u, streams.size());
|
DCHECK_LT(0u, streams.size());
|
||||||
muxer_listener_ = muxer_listener;
|
muxer_listener_ = muxer_listener;
|
||||||
progress_listener_ = progress_listener;
|
progress_listener_ = progress_listener;
|
||||||
|
@ -173,8 +170,10 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
|
||||||
encryption_key.key_id.assign(
|
encryption_key.key_id.assign(
|
||||||
kKeyRotationDefaultKeyId,
|
kKeyRotationDefaultKeyId,
|
||||||
kKeyRotationDefaultKeyId + arraysize(kKeyRotationDefaultKeyId));
|
kKeyRotationDefaultKeyId + arraysize(kKeyRotationDefaultKeyId));
|
||||||
|
if (!AesCryptor::GenerateRandomIv(protection_scheme, &encryption_key.iv))
|
||||||
|
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
|
||||||
GenerateEncryptedSampleEntry(encryption_key, clear_lead_in_seconds,
|
GenerateEncryptedSampleEntry(encryption_key, clear_lead_in_seconds,
|
||||||
encryption_mode, &description);
|
protection_scheme, &description);
|
||||||
if (muxer_listener_) {
|
if (muxer_listener_) {
|
||||||
muxer_listener_->OnEncryptionInfoReady(
|
muxer_listener_->OnEncryptionInfoReady(
|
||||||
kInitialEncryptionInfo, encryption_key.key_id,
|
kInitialEncryptionInfo, encryption_key.key_id,
|
||||||
|
@ -186,7 +185,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
|
||||||
encryption_key_source, track_type,
|
encryption_key_source, track_type,
|
||||||
crypto_period_duration_in_seconds * streams[i]->info()->time_scale(),
|
crypto_period_duration_in_seconds * streams[i]->info()->time_scale(),
|
||||||
clear_lead_in_seconds * streams[i]->info()->time_scale(),
|
clear_lead_in_seconds * streams[i]->info()->time_scale(),
|
||||||
muxer_listener_, encryption_mode);
|
protection_scheme, muxer_listener_);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,9 +194,13 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
|
||||||
encryption_key_source->GetKey(track_type, encryption_key.get());
|
encryption_key_source->GetKey(track_type, encryption_key.get());
|
||||||
if (!status.ok())
|
if (!status.ok())
|
||||||
return status;
|
return status;
|
||||||
|
if (encryption_key->iv.empty()) {
|
||||||
|
if (!AesCryptor::GenerateRandomIv(protection_scheme, &encryption_key->iv))
|
||||||
|
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
|
||||||
|
}
|
||||||
|
|
||||||
GenerateEncryptedSampleEntry(*encryption_key, clear_lead_in_seconds,
|
GenerateEncryptedSampleEntry(*encryption_key, clear_lead_in_seconds,
|
||||||
encryption_mode, &description);
|
protection_scheme, &description);
|
||||||
|
|
||||||
if (moov_->pssh.empty()) {
|
if (moov_->pssh.empty()) {
|
||||||
moov_->pssh.resize(encryption_key->key_system_info.size());
|
moov_->pssh.resize(encryption_key->key_system_info.size());
|
||||||
|
@ -215,7 +218,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
|
||||||
fragmenters_[i] = new EncryptingFragmenter(
|
fragmenters_[i] = new EncryptingFragmenter(
|
||||||
streams[i]->info(), &moof_->tracks[i], encryption_key.Pass(),
|
streams[i]->info(), &moof_->tracks[i], encryption_key.Pass(),
|
||||||
clear_lead_in_seconds * streams[i]->info()->time_scale(),
|
clear_lead_in_seconds * streams[i]->info()->time_scale(),
|
||||||
encryption_mode);
|
protection_scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose the first stream if there is no VIDEO.
|
// Choose the first stream if there is no VIDEO.
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include "packager/base/memory/ref_counted.h"
|
#include "packager/base/memory/ref_counted.h"
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/status.h"
|
#include "packager/media/base/status.h"
|
||||||
#include "packager/media/formats/mp4/box_definitions.h"
|
#include "packager/media/formats/mp4/box_definitions.h"
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ class Segmenter {
|
||||||
/// pixels per frame than max_sd_pixels, it is HD, SD otherwise.
|
/// pixels per frame than max_sd_pixels, it is HD, SD otherwise.
|
||||||
/// @param clear_time specifies clear lead duration in seconds.
|
/// @param clear_time specifies clear lead duration in seconds.
|
||||||
/// @param crypto_period_duration specifies crypto period duration in seconds.
|
/// @param crypto_period_duration specifies crypto period duration in seconds.
|
||||||
|
/// @param protection_scheme specifies the protection scheme: 'senc', 'sens',
|
||||||
|
/// 'cbc1', 'cbcs'.
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
Status Initialize(const std::vector<MediaStream*>& streams,
|
Status Initialize(const std::vector<MediaStream*>& streams,
|
||||||
MuxerListener* muxer_listener,
|
MuxerListener* muxer_listener,
|
||||||
|
@ -67,7 +69,7 @@ class Segmenter {
|
||||||
uint32_t max_sd_pixels,
|
uint32_t max_sd_pixels,
|
||||||
double clear_lead_in_seconds,
|
double clear_lead_in_seconds,
|
||||||
double crypto_period_duration_in_seconds,
|
double crypto_period_duration_in_seconds,
|
||||||
EncryptionMode encryption_mode);
|
FourCC protection_scheme);
|
||||||
|
|
||||||
/// Finalize the segmenter.
|
/// Finalize the segmenter.
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "packager/media/base/buffer_reader.h"
|
#include "packager/media/base/buffer_reader.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/rcheck.h"
|
#include "packager/media/base/rcheck.h"
|
||||||
#include "packager/media/formats/mp4/chunk_info_iterator.h"
|
#include "packager/media/formats/mp4/chunk_info_iterator.h"
|
||||||
#include "packager/media/formats/mp4/composition_offset_iterator.h"
|
#include "packager/media/formats/mp4/composition_offset_iterator.h"
|
||||||
|
@ -600,24 +600,10 @@ scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
||||||
|
|
||||||
FourCC protection_scheme = is_audio() ? audio_description().sinf.type.type
|
FourCC protection_scheme = is_audio() ? audio_description().sinf.type.type
|
||||||
: video_description().sinf.type.type;
|
: video_description().sinf.type.type;
|
||||||
EncryptionMode decryption_mode;
|
return scoped_ptr<DecryptConfig>(
|
||||||
switch (protection_scheme) {
|
new DecryptConfig(track_encryption().default_kid,
|
||||||
case FOURCC_cenc:
|
sample_encryption_entry.initialization_vector,
|
||||||
decryption_mode = kEncryptionModeAesCtr;
|
sample_encryption_entry.subsamples, protection_scheme));
|
||||||
break;
|
|
||||||
case FOURCC_cbc1:
|
|
||||||
decryption_mode = kEncryptionModeAesCbc;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG(ERROR) << "Unsupported protection scheme.";
|
|
||||||
return scoped_ptr<DecryptConfig>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return scoped_ptr<DecryptConfig>(new DecryptConfig(
|
|
||||||
track_encryption().default_kid,
|
|
||||||
sample_encryption_entry.initialization_vector,
|
|
||||||
sample_encryption_entry.subsamples,
|
|
||||||
decryption_mode));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mp4
|
} // namespace mp4
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "packager/media/formats/webm/encryptor.h"
|
#include "packager/media/formats/webm/encryptor.h"
|
||||||
|
|
||||||
#include "packager/media/base/aes_encryptor.h"
|
#include "packager/media/base/aes_encryptor.h"
|
||||||
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/media_sample.h"
|
#include "packager/media/base/media_sample.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
@ -14,9 +15,6 @@ namespace media {
|
||||||
namespace webm {
|
namespace webm {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Generate 64bit IV by default.
|
|
||||||
const size_t kDefaultIvSize = 8u;
|
|
||||||
|
|
||||||
Status CreateContentEncryption(mkvmuxer::Track* track, EncryptionKey* key) {
|
Status CreateContentEncryption(mkvmuxer::Track* track, EncryptionKey* key) {
|
||||||
if (!track->AddContentEncoding()) {
|
if (!track->AddContentEncoding()) {
|
||||||
return Status(error::INTERNAL_ERROR,
|
return Status(error::INTERNAL_ERROR,
|
||||||
|
@ -107,13 +105,14 @@ Status Encryptor::CreateEncryptor(MuxerListener* muxer_listener,
|
||||||
Status status = key_source->GetKey(track_type, encryption_key.get());
|
Status status = key_source->GetKey(track_type, encryption_key.get());
|
||||||
if (!status.ok())
|
if (!status.ok())
|
||||||
return status;
|
return status;
|
||||||
|
if (encryption_key->iv.empty()) {
|
||||||
|
if (!AesCryptor::GenerateRandomIv(FOURCC_cenc, &encryption_key->iv))
|
||||||
|
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
|
||||||
|
}
|
||||||
|
|
||||||
scoped_ptr<AesCtrEncryptor> encryptor(new AesCtrEncryptor());
|
scoped_ptr<AesCtrEncryptor> encryptor(new AesCtrEncryptor());
|
||||||
const bool initialized = encryption_key->iv.empty()
|
const bool initialized =
|
||||||
? encryptor->InitializeWithRandomIv(
|
encryptor->InitializeWithIv(encryption_key->key, encryption_key->iv);
|
||||||
encryption_key->key, kDefaultIvSize)
|
|
||||||
: encryptor->InitializeWithIv(
|
|
||||||
encryption_key->key, encryption_key->iv);
|
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
return Status(error::INTERNAL_ERROR, "Failed to create the encryptor.");
|
return Status(error::INTERNAL_ERROR, "Failed to create the encryptor.");
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/sys_byteorder.h"
|
#include "packager/base/sys_byteorder.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
@ -56,8 +55,7 @@ bool WebMCreateDecryptConfig(const uint8_t* data,
|
||||||
decrypt_config->reset(new DecryptConfig(
|
decrypt_config->reset(new DecryptConfig(
|
||||||
std::vector<uint8_t>(key_id, key_id + key_id_size),
|
std::vector<uint8_t>(key_id, key_id + key_id_size),
|
||||||
std::vector<uint8_t>(counter_block.begin(), counter_block.end()),
|
std::vector<uint8_t>(counter_block.begin(), counter_block.end()),
|
||||||
std::vector<SubsampleEntry>(),
|
std::vector<SubsampleEntry>()));
|
||||||
kEncryptionModeAesCtr));
|
|
||||||
*data_offset = frame_offset;
|
*data_offset = frame_offset;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "packager/media/formats/webm/webm_muxer.h"
|
#include "packager/media/formats/webm/webm_muxer.h"
|
||||||
|
|
||||||
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/media_sample.h"
|
#include "packager/media/base/media_sample.h"
|
||||||
#include "packager/media/base/media_stream.h"
|
#include "packager/media/base/media_stream.h"
|
||||||
#include "packager/media/base/stream_info.h"
|
#include "packager/media/base/stream_info.h"
|
||||||
|
@ -30,12 +31,11 @@ Status WebMMuxer::Initialize() {
|
||||||
"Key rotation is not implemented for WebM");
|
"Key rotation is not implemented for WebM");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encryption_key_source() && (encryption_mode() != kEncryptionModeAesCtr)) {
|
if (encryption_key_source() && (protection_scheme() != FOURCC_cenc)) {
|
||||||
NOTIMPLEMENTED()
|
NOTIMPLEMENTED()
|
||||||
<< "WebM muxer does not support encryption mode other than AES-CTR.";
|
<< "WebM does not support protection scheme other than 'cenc'.";
|
||||||
return Status(
|
return Status(error::UNIMPLEMENTED,
|
||||||
error::UNIMPLEMENTED,
|
"WebM does not support protection scheme other than 'cenc'.");
|
||||||
"WebM muxer does not support encryption mode other than AES-CTR.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_ptr<MkvWriter> writer(new MkvWriter);
|
scoped_ptr<MkvWriter> writer(new MkvWriter);
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
#include "packager/base/strings/stringprintf.h"
|
#include "packager/base/strings/stringprintf.h"
|
||||||
#include "packager/base/time/clock.h"
|
#include "packager/base/time/clock.h"
|
||||||
#include "packager/media/base/demuxer.h"
|
#include "packager/media/base/demuxer.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
|
||||||
#include "packager/media/base/fixed_key_source.h"
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/media/base/media_stream.h"
|
#include "packager/media/base/media_stream.h"
|
||||||
#include "packager/media/base/muxer.h"
|
#include "packager/media/base/muxer.h"
|
||||||
#include "packager/media/base/stream_info.h"
|
#include "packager/media/base/stream_info.h"
|
||||||
|
@ -174,10 +174,8 @@ void PackagerTestBasic::Remux(const std::string& input,
|
||||||
|
|
||||||
if (enable_encryption) {
|
if (enable_encryption) {
|
||||||
muxer_video->SetKeySource(encryption_key_source.get(),
|
muxer_video->SetKeySource(encryption_key_source.get(),
|
||||||
KeySource::TRACK_TYPE_SD,
|
KeySource::TRACK_TYPE_SD, kClearLeadInSeconds,
|
||||||
kClearLeadInSeconds,
|
kCryptoDurationInSeconds, FOURCC_cenc);
|
||||||
kCryptoDurationInSeconds,
|
|
||||||
kEncryptionModeAesCtr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,10 +194,8 @@ void PackagerTestBasic::Remux(const std::string& input,
|
||||||
|
|
||||||
if (enable_encryption) {
|
if (enable_encryption) {
|
||||||
muxer_audio->SetKeySource(encryption_key_source.get(),
|
muxer_audio->SetKeySource(encryption_key_source.get(),
|
||||||
KeySource::TRACK_TYPE_SD,
|
KeySource::TRACK_TYPE_SD, kClearLeadInSeconds,
|
||||||
kClearLeadInSeconds,
|
kCryptoDurationInSeconds, FOURCC_cenc);
|
||||||
kCryptoDurationInSeconds,
|
|
||||||
kEncryptionModeAesCtr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue