| Index: media/formats/mp4/track_run_iterator.cc
|
| diff --git a/media/formats/mp4/track_run_iterator.cc b/media/formats/mp4/track_run_iterator.cc
|
| index bdd4e07dd9a3cd6d2ff6d1847d8df517d9778301..b2f6e7399f9cfb633164203dadec2685a5ff4476 100644
|
| --- a/media/formats/mp4/track_run_iterator.cc
|
| +++ b/media/formats/mp4/track_run_iterator.cc
|
| @@ -12,6 +12,7 @@
|
| #include "base/macros.h"
|
| #include "media/formats/mp4/rcheck.h"
|
| #include "media/formats/mp4/sample_to_group_iterator.h"
|
| +#include "media/media_features.h"
|
|
|
| namespace media {
|
| namespace mp4 {
|
| @@ -323,24 +324,21 @@ bool TrackRunIterator::Init(const MovieFragment& moof) {
|
| tri.fragment_sample_encryption_info =
|
| traf.sample_group_description.entries;
|
|
|
| - uint8_t default_iv_size = 0;
|
| + const TrackEncryption* track_encryption;
|
| tri.is_audio = (stsd.type == kAudio);
|
| if (tri.is_audio) {
|
| RCHECK(!stsd.audio_entries.empty());
|
| if (desc_idx > stsd.audio_entries.size())
|
| desc_idx = 0;
|
| tri.audio_description = &stsd.audio_entries[desc_idx];
|
| - default_iv_size =
|
| - tri.audio_description->sinf.info.track_encryption.default_iv_size;
|
| + track_encryption = &tri.audio_description->sinf.info.track_encryption;
|
| } else {
|
| RCHECK(!stsd.video_entries.empty());
|
| if (desc_idx > stsd.video_entries.size())
|
| desc_idx = 0;
|
| tri.video_description = &stsd.video_entries[desc_idx];
|
| - default_iv_size =
|
| - tri.video_description->sinf.info.track_encryption.default_iv_size;
|
| + track_encryption = &tri.video_description->sinf.info.track_encryption;
|
| }
|
| -
|
| // Initialize aux_info variables only if no sample encryption entries.
|
| if (sample_encryption_entries_count == 0 &&
|
| traf.auxiliary_offset.offsets.size() > j) {
|
| @@ -408,12 +406,46 @@ bool TrackRunIterator::Init(const MovieFragment& moof) {
|
| tri.sample_encryption_entries.resize(trun.sample_count);
|
| for (size_t k = 0; k < trun.sample_count; k++) {
|
| uint32_t index = tri.samples[k].cenc_group_description_index;
|
| - const uint8_t iv_size =
|
| - index == 0 ? default_iv_size
|
| - : GetSampleEncryptionInfoEntry(tri, index)->iv_size;
|
| - RCHECK(tri.sample_encryption_entries[k].Parse(
|
| - sample_encryption_reader.get(), iv_size,
|
| - traf.sample_encryption.use_subsample_encryption));
|
| + const CencSampleEncryptionInfoEntry* info_entry =
|
| + index == 0 ? nullptr : GetSampleEncryptionInfoEntry(tri, index);
|
| + const uint8_t iv_size = index == 0 ? track_encryption->default_iv_size
|
| + : info_entry->iv_size;
|
| + SampleEncryptionEntry& entry = tri.sample_encryption_entries[k];
|
| + RCHECK(entry.Parse(sample_encryption_reader.get(), iv_size,
|
| + traf.sample_encryption.use_subsample_encryption));
|
| +#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
|
| + // If we don't have a per-sample IV, get the constant IV.
|
| + bool is_encrypted = index == 0 ? track_encryption->is_encrypted
|
| + : info_entry->is_encrypted;
|
| + // We only support setting the pattern values in the 'tenc' box for
|
| + // the track (not varying on per sample group basis).
|
| + // Thus we need to verify that the settings in the sample group match
|
| + // those in the 'tenc'.
|
| + if (is_encrypted && index != 0) {
|
| + RCHECK_MEDIA_LOGGED(info_entry->crypt_byte_block ==
|
| + track_encryption->default_crypt_byte_block,
|
| + media_log_,
|
| + "Pattern value (crypt byte block) for the "
|
| + "sample group does not match that in the tenc "
|
| + "box . This is not currently supported.");
|
| + RCHECK_MEDIA_LOGGED(info_entry->skip_byte_block ==
|
| + track_encryption->default_skip_byte_block,
|
| + media_log_,
|
| + "Pattern value (skip byte block) for the "
|
| + "sample group does not match that in the tenc "
|
| + "box . This is not currently supported.");
|
| + }
|
| + if (is_encrypted && !iv_size) {
|
| + const uint8_t constant_iv_size =
|
| + index == 0 ? track_encryption->default_constant_iv_size
|
| + : info_entry->constant_iv_size;
|
| + RCHECK(constant_iv_size != 0);
|
| + const uint8_t* constant_iv =
|
| + index == 0 ? track_encryption->default_constant_iv
|
| + : info_entry->constant_iv;
|
| + memcpy(entry.initialization_vector, constant_iv, constant_iv_size);
|
| + }
|
| +#endif
|
| }
|
| }
|
| runs_.push_back(tri);
|
| @@ -474,8 +506,14 @@ bool TrackRunIterator::CacheAuxInfo(const uint8_t* buf, int buf_size) {
|
| BufferReader reader(buf + pos, info_size);
|
| const uint8_t iv_size = GetIvSize(i);
|
| const bool has_subsamples = info_size > iv_size;
|
| - RCHECK(
|
| - sample_encryption_entries[i].Parse(&reader, iv_size, has_subsamples));
|
| + SampleEncryptionEntry& entry = sample_encryption_entries[i];
|
| + RCHECK(entry.Parse(&reader, iv_size, has_subsamples));
|
| +#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
|
| + // if we don't have a per-sample IV, get the constant IV.
|
| + if (!iv_size) {
|
| + RCHECK(ApplyConstantIv(i, &entry));
|
| + }
|
| +#endif
|
| }
|
| pos += info_size;
|
| }
|
| @@ -592,14 +630,28 @@ const TrackEncryption& TrackRunIterator::track_encryption() const {
|
|
|
| std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
| DCHECK(is_encrypted());
|
| + size_t sample_idx = sample_itr_ - run_itr_->samples.begin();
|
| + const std::vector<uint8_t>& kid = GetKeyId(sample_idx);
|
|
|
| if (run_itr_->sample_encryption_entries.empty()) {
|
| DCHECK_EQ(0, aux_info_size());
|
| +#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
|
| + // The 'cbcs' scheme allows empty aux info when a constant IV is in use
|
| + // with full sample encryption. That case will fall through to here.
|
| + SampleEncryptionEntry sample_encryption_entry;
|
| + if (ApplyConstantIv(sample_idx, &sample_encryption_entry)) {
|
| + return std::unique_ptr<DecryptConfig>(new DecryptConfig(
|
| + std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()),
|
| + std::string(reinterpret_cast<const char*>(
|
| + sample_encryption_entry.initialization_vector),
|
| + arraysize(sample_encryption_entry.initialization_vector)),
|
| + sample_encryption_entry.subsamples));
|
| + }
|
| +#endif
|
| MEDIA_LOG(ERROR, media_log_) << "Sample encryption info is not available.";
|
| return std::unique_ptr<DecryptConfig>();
|
| }
|
|
|
| - size_t sample_idx = sample_itr_ - run_itr_->samples.begin();
|
| DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size());
|
| const SampleEncryptionEntry& sample_encryption_entry =
|
| run_itr_->sample_encryption_entries[sample_idx];
|
| @@ -612,7 +664,6 @@ std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
|
| return std::unique_ptr<DecryptConfig>();
|
| }
|
|
|
| - const std::vector<uint8_t>& kid = GetKeyId(sample_idx);
|
| return std::unique_ptr<DecryptConfig>(new DecryptConfig(
|
| std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()),
|
| std::string(reinterpret_cast<const char*>(
|
| @@ -648,5 +699,24 @@ uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const {
|
| : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size;
|
| }
|
|
|
| +#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
|
| +bool TrackRunIterator::ApplyConstantIv(size_t sample_index,
|
| + SampleEncryptionEntry* entry) const {
|
| + DCHECK(IsSampleEncrypted(sample_index));
|
| + uint32_t index = GetGroupDescriptionIndex(sample_index);
|
| + const uint8_t constant_iv_size =
|
| + index == 0
|
| + ? track_encryption().default_constant_iv_size
|
| + : GetSampleEncryptionInfoEntry(*run_itr_, index)->constant_iv_size;
|
| + RCHECK(constant_iv_size != 0);
|
| + const uint8_t* constant_iv =
|
| + index == 0 ? track_encryption().default_constant_iv
|
| + : GetSampleEncryptionInfoEntry(*run_itr_, index)->constant_iv;
|
| + RCHECK(constant_iv != nullptr);
|
| + memcpy(entry->initialization_vector, constant_iv, kInitializationVectorSize);
|
| + return true;
|
| +}
|
| +#endif
|
| +
|
| } // namespace mp4
|
| } // namespace media
|
|
|