diff --git a/packager/app/test/packager_test.py b/packager/app/test/packager_test.py
index 08e4754c90..1f1cae2546 100755
--- a/packager/app/test/packager_test.py
+++ b/packager/app/test/packager_test.py
@@ -171,7 +171,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True,
protection_scheme='cens'))
- self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4')
+ self._DiffGold(self.output[0], 'bear-640x360-a-cens-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-cens-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-av-cens-golden.mpd')
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
@@ -182,7 +182,7 @@ class PackagerAppTest(unittest.TestCase):
self._GetStreams(['audio', 'video']),
self._GetFlags(encryption=True,
protection_scheme='cbcs'))
- self._DiffGold(self.output[0], 'bear-640x360-a-cbc1-golden.mp4')
+ self._DiffGold(self.output[0], 'bear-640x360-a-cbcs-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-cbcs-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-av-cbcs-golden.mpd')
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
diff --git a/packager/app/test/testdata/bear-640x360-a-cbcs-golden.mp4 b/packager/app/test/testdata/bear-640x360-a-cbcs-golden.mp4
new file mode 100644
index 0000000000..313271ea58
Binary files /dev/null and b/packager/app/test/testdata/bear-640x360-a-cbcs-golden.mp4 differ
diff --git a/packager/app/test/testdata/bear-640x360-a-cens-golden.mp4 b/packager/app/test/testdata/bear-640x360-a-cens-golden.mp4
new file mode 100644
index 0000000000..fe06b5ac9d
Binary files /dev/null and b/packager/app/test/testdata/bear-640x360-a-cens-golden.mp4 differ
diff --git a/packager/app/test/testdata/bear-640x360-av-cbcs-golden.mpd b/packager/app/test/testdata/bear-640x360-av-cbcs-golden.mpd
index 972d28a625..119988cfc5 100644
--- a/packager/app/test/testdata/bear-640x360-av-cbcs-golden.mpd
+++ b/packager/app/test/testdata/bear-640x360-av-cbcs-golden.mpd
@@ -15,15 +15,15 @@
-
+
-
+
AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2
output_audio.mp4
-
-
+
+
diff --git a/packager/app/test/testdata/bear-640x360-av-cens-golden.mpd b/packager/app/test/testdata/bear-640x360-av-cens-golden.mpd
index 627ef222cb..cbd0e46067 100644
--- a/packager/app/test/testdata/bear-640x360-av-cens-golden.mpd
+++ b/packager/app/test/testdata/bear-640x360-av-cens-golden.mpd
@@ -17,7 +17,7 @@
-
+
AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2
diff --git a/packager/app/widevine_encryption_flags.cc b/packager/app/widevine_encryption_flags.cc
index 7c34a62baf..09ef9f0955 100644
--- a/packager/app/widevine_encryption_flags.cc
+++ b/packager/app/widevine_encryption_flags.cc
@@ -58,11 +58,7 @@ DEFINE_int32(crypto_period_duration,
DEFINE_string(protection_scheme,
"cenc",
"Choose protection scheme, 'cenc' or 'cbc1' or pattern-based "
- "protection schemes 'cens' or 'cbcs'. Note that if a "
- "pattern-based protection scheme only applies to video stream; "
- "audio stream will be encrypted using the corresponding "
- "non-pattern-based protection schemes, i.e. 'cenc' for 'cens', "
- "'cbc1' for 'cbcs'.");
+ "protection schemes 'cens' or 'cbcs'.");
namespace shaka {
diff --git a/packager/media/base/aes_cryptor.h b/packager/media/base/aes_cryptor.h
index 2c4997f232..1ca85c1369 100644
--- a/packager/media/base/aes_cryptor.h
+++ b/packager/media/base/aes_cryptor.h
@@ -80,6 +80,9 @@ class AesCryptor {
/// @return The current iv.
const std::vector& iv() const { return iv_; }
+ /// @return true if constant iv is used, false otherwise.
+ bool use_constant_iv() const { return constant_iv_flag_ == kUseConstantIv; }
+
/// @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.
diff --git a/packager/media/base/aes_pattern_cryptor.cc b/packager/media/base/aes_pattern_cryptor.cc
index 8de98ede90..55a3be6b81 100644
--- a/packager/media/base/aes_pattern_cryptor.cc
+++ b/packager/media/base/aes_pattern_cryptor.cc
@@ -23,7 +23,13 @@ AesPatternCryptor::AesPatternCryptor(uint8_t crypt_byte_block,
skip_byte_block_(skip_byte_block),
encryption_mode_(encryption_mode),
cryptor_(cryptor.Pass()) {
+ // |crypt_byte_block_| should never be 0. |skip_byte_block_| can be 0 to allow
+ // a special pattern of 1:0, which is the pattern for the case of pattern
+ // encryption when applied to non video tracks.
+ DCHECK_NE(crypt_byte_block_, 0u);
+ DCHECK(skip_byte_block_ != 0 || crypt_byte_block_ == 1);
DCHECK(cryptor_);
+ DCHECK(!cryptor_->use_constant_iv());
}
AesPatternCryptor::~AesPatternCryptor() {}
@@ -45,6 +51,17 @@ bool AesPatternCryptor::CryptInternal(const uint8_t* text,
}
*crypt_text_size = text_size;
+ // Handle the special pattern 1:0.
+ if (skip_byte_block_ == 0) {
+ DCHECK_EQ(crypt_byte_block_, 1u);
+ const size_t crypt_byte_size = text_size / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
+ if (!cryptor_->Crypt(text, crypt_byte_size, crypt_text))
+ return false;
+ memcpy(crypt_text + crypt_byte_size, text + crypt_byte_size,
+ text_size - crypt_byte_size);
+ return true;
+ }
+
while (text_size > 0) {
const size_t crypt_byte_size = crypt_byte_block_ * AES_BLOCK_SIZE;
if (NeedEncrypt(text_size, crypt_byte_size)) {
diff --git a/packager/media/base/aes_pattern_cryptor.h b/packager/media/base/aes_pattern_cryptor.h
index 7c4d364a38..ba351304a6 100644
--- a/packager/media/base/aes_pattern_cryptor.h
+++ b/packager/media/base/aes_pattern_cryptor.h
@@ -47,7 +47,8 @@ class AesPatternCryptor : public AesCryptor {
/// internally inside Crypt call, i.e. iv will be updated across Crypt
/// calls.
/// @param cryptor points to an AesCryptor instance which performs the actual
- /// encryption/decryption.
+ /// encryption/decryption. Note that @a cryptor shall not use constant
+ /// iv.
AesPatternCryptor(uint8_t crypt_byte_block,
uint8_t skip_byte_block,
PatternEncryptionMode encryption_mode,
diff --git a/packager/media/base/aes_pattern_cryptor_unittest.cc b/packager/media/base/aes_pattern_cryptor_unittest.cc
index dc6dbfb423..f7f311be04 100644
--- a/packager/media/base/aes_pattern_cryptor_unittest.cc
+++ b/packager/media/base/aes_pattern_cryptor_unittest.cc
@@ -219,5 +219,35 @@ TEST(SampleAesPatternCryptor, MoreThan16Bytes) {
ASSERT_TRUE(pattern_cryptor.Crypt("0123456789abcdef012", &crypt_text));
}
+TEST(FullSampleSpecialPatternTest, Test) {
+ MockAesCryptor* mock_cryptor = new MockAesCryptor();
+ EXPECT_CALL(*mock_cryptor, CryptInternal(_, 96u, _, _))
+ .WillOnce(Invoke([](const uint8_t* text, size_t text_size,
+ uint8_t* crypt_text, size_t* crypt_text_size) {
+ *crypt_text_size = text_size;
+ for (size_t i = 0; i < text_size; ++i)
+ *crypt_text++ = 'e';
+ return true;
+ }));
+
+ const uint8_t kFulLSampleCryptBlock = 1;
+ const uint8_t kFullSampleSkipBlock = 0;
+ AesPatternCryptor pattern_cryptor(
+ kFulLSampleCryptBlock, kFullSampleSkipBlock,
+ AesPatternCryptor::kSkipIfCryptByteBlockRemaining,
+ AesPatternCryptor::kUseConstantIv,
+ scoped_ptr(mock_cryptor));
+
+ std::vector iv(8, 'i');
+ // SetIv will be called only once by AesPatternCryptor::SetIv.
+ EXPECT_TRUE(pattern_cryptor.SetIv(iv));
+
+ std::string input_text(100, 'c');
+ std::string crypt_text;
+ // More than 16 bytes so mock's CryptInternal should be called.
+ ASSERT_TRUE(pattern_cryptor.Crypt(input_text, &crypt_text));
+ EXPECT_EQ(std::string(96, 'e') + std::string(4, 'c'), crypt_text);
+}
+
} // namespace media
} // namespace shaka
diff --git a/packager/media/formats/mp4/box_definitions.cc b/packager/media/formats/mp4/box_definitions.cc
index 253820c922..55b45cc226 100644
--- a/packager/media/formats/mp4/box_definitions.cc
+++ b/packager/media/formats/mp4/box_definitions.cc
@@ -126,6 +126,11 @@ FourCC TrackTypeToFourCC(TrackType track_type) {
}
}
+bool IsProtectionSchemeSupported(FourCC scheme) {
+ return scheme == FOURCC_cenc || scheme == FOURCC_cens ||
+ scheme == FOURCC_cbc1 || scheme == FOURCC_cbcs;
+}
+
} // namespace
FileType::FileType() : major_brand(FOURCC_NULL), minor_version(0) {}
@@ -483,9 +488,12 @@ bool ProtectionSchemeInfo::ReadWriteInternal(BoxBuffer* buffer) {
buffer->PrepareChildren() &&
buffer->ReadWriteChild(&format) &&
buffer->ReadWriteChild(&type));
- RCHECK(type.type == FOURCC_cenc || type.type == FOURCC_cbc1 ||
- type.type == FOURCC_cens || type.type == FOURCC_cbcs);
- RCHECK(buffer->ReadWriteChild(&info));
+ if (IsProtectionSchemeSupported(type.type)) {
+ RCHECK(buffer->ReadWriteChild(&info));
+ } else {
+ DLOG(WARNING) << "Ignore unsupported protection scheme: "
+ << FourCCToString(type.type);
+ }
// Other protection schemes are silently ignored. Since the protection scheme
// type can't be determined until this box is opened, we return 'true' for
// non-CENC protection scheme types. It is the parent box's responsibility to
@@ -1001,8 +1009,8 @@ bool SampleGroupDescription::ReadWriteInternal(BoxBuffer* buffer) {
return ReadWriteEntries(buffer, &audio_roll_recovery_entries);
default:
DCHECK(buffer->Reading());
- DLOG(WARNING) << "Sample group '" << grouping_type
- << "' is not supported.";
+ DLOG(WARNING) << "Ignore unsupported sample group: "
+ << FourCCToString(static_cast(grouping_type));
return true;
}
}
@@ -1077,9 +1085,8 @@ bool SampleToGroup::ReadWriteInternal(BoxBuffer* buffer) {
if (grouping_type != FOURCC_seig && grouping_type != FOURCC_roll) {
DCHECK(buffer->Reading());
- DLOG(WARNING) << "Sample group "
- << FourCCToString(static_cast(grouping_type))
- << " is not supported.";
+ DLOG(WARNING) << "Ignore unsupported sample group: "
+ << FourCCToString(static_cast(grouping_type));
return true;
}
@@ -1538,8 +1545,17 @@ bool VideoSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
RCHECK(buffer->PrepareChildren());
- if (format == FOURCC_encv)
- RCHECK(buffer->ReadWriteChild(&sinf));
+ if (format == FOURCC_encv) {
+ if (buffer->Reading()) {
+ // Continue scanning until a supported protection scheme is found, or
+ // until we run out of protection schemes.
+ while (!IsProtectionSchemeSupported(sinf.type.type))
+ RCHECK(buffer->ReadWriteChild(&sinf));
+ } else {
+ DCHECK(IsProtectionSchemeSupported(sinf.type.type));
+ RCHECK(buffer->ReadWriteChild(&sinf));
+ }
+ }
const FourCC actual_format = GetActualFormat();
if (buffer->Reading()) {
@@ -1777,8 +1793,17 @@ bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
samplerate >>= 16;
RCHECK(buffer->PrepareChildren());
- if (format == FOURCC_enca)
- RCHECK(buffer->ReadWriteChild(&sinf));
+ if (format == FOURCC_enca) {
+ if (buffer->Reading()) {
+ // Continue scanning until a supported protection scheme is found, or
+ // until we run out of protection schemes.
+ while (!IsProtectionSchemeSupported(sinf.type.type))
+ RCHECK(buffer->ReadWriteChild(&sinf));
+ } else {
+ DCHECK(IsProtectionSchemeSupported(sinf.type.type));
+ RCHECK(buffer->ReadWriteChild(&sinf));
+ }
+ }
RCHECK(buffer->TryReadWriteChild(&esds));
RCHECK(buffer->TryReadWriteChild(&ddts));
diff --git a/packager/media/formats/mp4/encrypting_fragmenter.cc b/packager/media/formats/mp4/encrypting_fragmenter.cc
index 8e69aac10c..d54dcced06 100644
--- a/packager/media/formats/mp4/encrypting_fragmenter.cc
+++ b/packager/media/formats/mp4/encrypting_fragmenter.cc
@@ -186,9 +186,18 @@ void EncryptingFragmenter::FinalizeFragmentForEncryption() {
DCHECK(!IsSubsampleEncryptionRequired());
saiz.default_sample_info_size = per_sample_iv_size;
}
- // It should only happen with full sample encryption + constant iv, which is
- // not a legal combination.
- CHECK(!saiz.sample_info_sizes.empty() || saiz.default_sample_info_size != 0);
+
+ // It should only happen with full sample encryption + constant iv, i.e.
+ // 'cbcs' applying to audio.
+ if (saiz.default_sample_info_size == 0 && saiz.sample_info_sizes.empty()) {
+ DCHECK_EQ(protection_scheme_, FOURCC_cbcs);
+ DCHECK(!IsSubsampleEncryptionRequired());
+ // ISO/IEC 23001-7:2016(E) The sample auxiliary information would then be
+ // empty and should be emitted. Clear saiz and saio boxes so they are not
+ // written.
+ saiz.sample_count = 0;
+ traf()->auxiliary_offset.offsets.clear();
+ }
}
Status EncryptingFragmenter::CreateEncryptor() {
@@ -337,6 +346,8 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr sample) {
traf()->auxiliary_size.sample_info_sizes.push_back(
sample_encryption_entry.ComputeSize());
} else {
+ DCHECK_LE(crypt_byte_block(), 1u);
+ DCHECK_EQ(skip_byte_block(), 0u);
EncryptBytes(data, sample->data_size());
}
diff --git a/packager/media/formats/mp4/segmenter.cc b/packager/media/formats/mp4/segmenter.cc
index fbb7a32516..5b35794e00 100644
--- a/packager/media/formats/mp4/segmenter.cc
+++ b/packager/media/formats/mp4/segmenter.cc
@@ -28,10 +28,6 @@ namespace media {
namespace mp4 {
namespace {
-// For pattern-based encryption.
-const uint8_t kCryptByteBlock = 1u;
-const uint8_t kSkipByteBlock = 9u;
-
const size_t kCencKeyIdSize = 16u;
// The version of cenc implemented here. CENC 4.
@@ -43,6 +39,12 @@ const uint8_t kKeyRotationDefaultKeyId[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
+// Defines protection pattern for pattern-based encryption.
+struct ProtectionPattern {
+ uint8_t crypt_byte_block;
+ uint8_t skip_byte_block;
+};
+
COMPILE_ASSERT(arraysize(kKeyRotationDefaultKeyId) == kCencKeyIdSize,
cenc_key_id_must_be_size_16);
@@ -52,21 +54,37 @@ uint64_t Rescale(uint64_t time_in_old_scale,
return static_cast(time_in_old_scale) / old_scale * new_scale;
}
-uint8_t GetCryptByteBlock(FourCC protection_scheme) {
- return (protection_scheme == FOURCC_cbcs || protection_scheme == FOURCC_cens)
- ? kCryptByteBlock
- : 0;
-}
-
-uint8_t GetSkipByteBlock(FourCC protection_scheme) {
- return (protection_scheme == FOURCC_cbcs || protection_scheme == FOURCC_cens)
- ? kSkipByteBlock
- : 0;
+ProtectionPattern GetProtectionPattern(FourCC protection_scheme,
+ TrackType track_type) {
+ ProtectionPattern pattern;
+ if (protection_scheme != FOURCC_cbcs && protection_scheme != FOURCC_cens) {
+ // Not using pattern encryption.
+ pattern.crypt_byte_block = 0u;
+ pattern.skip_byte_block = 0u;
+ } else if (track_type != kVideo) {
+ // Tracks other than video are protected using whole-block full-sample
+ // encryption, which is essentially a pattern of 1:0. Note that this may not
+ // be the same as the non-pattern based encryption counterparts, e.g. in
+ // 'cens' for full sample encryption, the whole sample is encrypted up to
+ // the last 16-byte boundary, see 23001-7:2016(E) 9.7; while in 'cenc' for
+ // full sample encryption, the last partial 16-byte block is also encrypted,
+ // see 23001-7:2016(E) 9.4.2. Another difference is the use of constant iv.
+ pattern.crypt_byte_block = 1u;
+ pattern.skip_byte_block = 0u;
+ } else {
+ // Use 1:9 pattern for video.
+ const uint8_t kCryptByteBlock = 1u;
+ const uint8_t kSkipByteBlock = 9u;
+ pattern.crypt_byte_block = kCryptByteBlock;
+ pattern.skip_byte_block = kSkipByteBlock;
+ }
+ return pattern;
}
void GenerateSinf(const EncryptionKey& encryption_key,
FourCC old_type,
FourCC protection_scheme,
+ ProtectionPattern pattern,
ProtectionSchemeInfo* sinf) {
sinf->format.format = old_type;
@@ -85,16 +103,15 @@ void GenerateSinf(const EncryptionKey& encryption_key,
} else {
track_encryption.default_per_sample_iv_size = encryption_key.iv.size();
}
- track_encryption.default_crypt_byte_block =
- GetCryptByteBlock(protection_scheme);
- track_encryption.default_skip_byte_block =
- GetSkipByteBlock(protection_scheme);
+ track_encryption.default_crypt_byte_block = pattern.crypt_byte_block;
+ track_encryption.default_skip_byte_block = pattern.skip_byte_block;
track_encryption.default_kid = encryption_key.key_id;
}
void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
double clear_lead_in_seconds,
FourCC protection_scheme,
+ ProtectionPattern pattern,
SampleDescription* description) {
DCHECK(description);
if (description->type == kVideo) {
@@ -106,7 +123,8 @@ void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
// Convert the first entry to an encrypted entry.
VideoSampleEntry& entry = description->video_entries[0];
- GenerateSinf(encryption_key, entry.format, protection_scheme, &entry.sinf);
+ GenerateSinf(encryption_key, entry.format, protection_scheme, pattern,
+ &entry.sinf);
entry.format = FOURCC_encv;
} else {
DCHECK_EQ(kAudio, description->type);
@@ -118,7 +136,8 @@ void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
// Convert the first entry to an encrypted entry.
AudioSampleEntry& entry = description->audio_entries[0];
- GenerateSinf(encryption_key, entry.format, protection_scheme, &entry.sinf);
+ GenerateSinf(encryption_key, entry.format, protection_scheme, pattern,
+ &entry.sinf);
entry.format = FOURCC_enca;
}
}
@@ -174,20 +193,12 @@ Status Segmenter::Initialize(const std::vector& streams,
continue;
}
- FourCC local_protection_scheme = protection_scheme;
- if (streams[i]->info()->stream_type() != kStreamVideo) {
- // Pattern encryption should only be used with video. Replaces with the
- // corresponding non-pattern encryption scheme.
- if (protection_scheme == FOURCC_cbcs)
- local_protection_scheme = FOURCC_cbc1;
- else if (protection_scheme == FOURCC_cens)
- local_protection_scheme = FOURCC_cenc;
- }
-
KeySource::TrackType track_type =
GetTrackTypeForEncryption(*streams[i]->info(), max_sd_pixels);
SampleDescription& description =
moov_->tracks[i].media.information.sample_table.description;
+ ProtectionPattern pattern =
+ GetProtectionPattern(protection_scheme, description.type);
if (key_rotation_enabled) {
// Fill encrypted sample entry with default key.
@@ -195,17 +206,16 @@ Status Segmenter::Initialize(const std::vector& streams,
encryption_key.key_id.assign(
kKeyRotationDefaultKeyId,
kKeyRotationDefaultKeyId + arraysize(kKeyRotationDefaultKeyId));
- if (!AesCryptor::GenerateRandomIv(local_protection_scheme,
+ 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,
- local_protection_scheme, &description);
+ protection_scheme, pattern, &description);
if (muxer_listener_) {
muxer_listener_->OnEncryptionInfoReady(
- kInitialEncryptionInfo, local_protection_scheme,
- encryption_key.key_id, encryption_key.iv,
- encryption_key.key_system_info);
+ kInitialEncryptionInfo, protection_scheme, encryption_key.key_id,
+ encryption_key.iv, encryption_key.key_system_info);
}
fragmenters_[i] = new KeyRotationFragmenter(
@@ -213,8 +223,8 @@ Status Segmenter::Initialize(const std::vector& streams,
encryption_key_source, track_type,
crypto_period_duration_in_seconds * streams[i]->info()->time_scale(),
clear_lead_in_seconds * streams[i]->info()->time_scale(),
- local_protection_scheme, GetCryptByteBlock(local_protection_scheme),
- GetSkipByteBlock(local_protection_scheme), muxer_listener_);
+ protection_scheme, pattern.crypt_byte_block, pattern.skip_byte_block,
+ muxer_listener_);
continue;
}
@@ -224,14 +234,14 @@ Status Segmenter::Initialize(const std::vector& streams,
if (!status.ok())
return status;
if (encryption_key->iv.empty()) {
- if (!AesCryptor::GenerateRandomIv(local_protection_scheme,
+ 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,
- local_protection_scheme, &description);
+ protection_scheme, pattern, &description);
if (moov_->pssh.empty()) {
moov_->pssh.resize(encryption_key->key_system_info.size());
@@ -241,17 +251,15 @@ Status Segmenter::Initialize(const std::vector& streams,
if (muxer_listener_) {
muxer_listener_->OnEncryptionInfoReady(
- kInitialEncryptionInfo, local_protection_scheme,
- encryption_key->key_id, encryption_key->iv,
- encryption_key->key_system_info);
+ kInitialEncryptionInfo, protection_scheme, encryption_key->key_id,
+ encryption_key->iv, encryption_key->key_system_info);
}
}
fragmenters_[i] = new EncryptingFragmenter(
streams[i]->info(), &moof_->tracks[i], encryption_key.Pass(),
clear_lead_in_seconds * streams[i]->info()->time_scale(),
- local_protection_scheme, GetCryptByteBlock(local_protection_scheme),
- GetSkipByteBlock(local_protection_scheme));
+ protection_scheme, pattern.crypt_byte_block, pattern.skip_byte_block);
}
// Choose the first stream if there is no VIDEO.