Index: media/formats/mp4/track_run_iterator_unittest.cc |
diff --git a/media/formats/mp4/track_run_iterator_unittest.cc b/media/formats/mp4/track_run_iterator_unittest.cc |
index d1b3129d3f426b6e6f295df18f23f854a0d3adc1..7c2043bf3411807e8bf64098217869259ec607f1 100644 |
--- a/media/formats/mp4/track_run_iterator_unittest.cc |
+++ b/media/formats/mp4/track_run_iterator_unittest.cc |
@@ -97,6 +97,48 @@ const uint8_t kFragmentCencSampleGroupKeyId[] = { |
0x74, 0x43, 0x65, 0x6e, 0x63, 0x53, 0x61, 0x6d, |
}; |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+// Sample encryption data for two samples, using constant IV (defined by 'tenc' |
+// or sample group entry). |
+const uint8_t kSampleEncryptionDataWithSubsamplesAndConstantIv[] = { |
+ // Sample count. |
+ 0x00, 0x00, 0x00, 0x05, |
+ // Sample 1: Subsample count. |
+ 0x00, 0x01, |
+ // Sample 1: Subsample 1. |
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, |
+ // Sample 2: Subsample count. |
+ 0x00, 0x02, |
+ // Sample 2: Subsample 1. |
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, |
+ // Sample 2: Subsample 2. |
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, |
+ // Sample 3: Subsample count. |
+ 0x00, 0x01, |
+ // Sample 3: Subsample 1. |
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, |
+ // Sample 4: Subsample count. |
+ 0x00, 0x01, |
+ // Sample 4: Subsample 1. |
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, |
+ // Sample 5: Subsample count. |
+ 0x00, 0x01, |
+ // Sample 5: Subsample 1. |
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, |
+}; |
+ |
+// Size of these IVs are 16 bytes. |
+const char kIv4[] = { |
+ 0x41, 0x54, 0x65, 0x73, 0x74, 0x49, 0x76, 0x34, |
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
+}; |
+ |
+const char kIv5[] = { |
+ 0x41, 0x54, 0x65, 0x73, 0x74, 0x49, 0x76, 0x35, |
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
+}; |
+#endif |
+ |
} // namespace |
namespace media { |
@@ -258,8 +300,7 @@ class TrackRunIteratorTest : public testing::Test { |
return moof; |
} |
- // Update the first sample description of a Track to indicate encryption |
- void AddEncryption(Track* track) { |
+ ProtectionSchemeInfo* GetProtectionSchemeInfoForTrack(Track* track) { |
SampleDescription* stsd = |
&track->media.information.sample_table.description; |
ProtectionSchemeInfo* sinf; |
@@ -268,7 +309,12 @@ class TrackRunIteratorTest : public testing::Test { |
} else { |
sinf = &stsd->audio_entries[0].sinf; |
} |
+ return sinf; |
+ } |
+ // Update the first sample description of a Track to indicate CENC encryption |
+ void AddEncryption(Track* track) { |
+ ProtectionSchemeInfo* sinf = GetProtectionSchemeInfoForTrack(track); |
sinf->type.type = FOURCC_CENC; |
sinf->info.track_encryption.is_encrypted = true; |
sinf->info.track_encryption.default_iv_size = 8; |
@@ -354,6 +400,70 @@ class TrackRunIteratorTest : public testing::Test { |
} |
} |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ // Update the first sample description of a Track to indicate CBCS encryption |
+ // with a constant IV and pattern. |
+ void AddEncryptionCbcs(Track* track) { |
+ ProtectionSchemeInfo* sinf = GetProtectionSchemeInfoForTrack(track); |
+ sinf->type.type = FOURCC_CBCS; |
+ sinf->info.track_encryption.is_encrypted = true; |
+ sinf->info.track_encryption.default_iv_size = 0; |
+ sinf->info.track_encryption.default_crypt_byte_block = 1; |
+ sinf->info.track_encryption.default_skip_byte_block = 9; |
+ sinf->info.track_encryption.default_constant_iv_size = 16; |
+ memcpy(sinf->info.track_encryption.default_constant_iv, kIv3, 16); |
+ sinf->info.track_encryption.default_kid.assign(kKeyId, |
+ kKeyId + arraysize(kKeyId)); |
+ } |
+ |
+ void AddConstantIvsToCencSampleGroup(Track* track, TrackFragment* frag) { |
+ auto& track_cenc_group = |
+ track->media.information.sample_table.sample_group_description; |
+ track_cenc_group.entries[0].iv_size = 0; |
+ track_cenc_group.entries[0].crypt_byte_block = 1; |
+ track_cenc_group.entries[0].skip_byte_block = 9; |
+ track_cenc_group.entries[0].constant_iv_size = 16; |
+ memcpy(track_cenc_group.entries[0].constant_iv, kIv4, 16); |
+ |
+ frag->sample_group_description.entries[1].iv_size = 0; |
+ frag->sample_group_description.entries[1].crypt_byte_block = 1; |
+ frag->sample_group_description.entries[1].skip_byte_block = 9; |
+ frag->sample_group_description.entries[1].constant_iv_size = 16; |
+ memcpy(frag->sample_group_description.entries[1].constant_iv, kIv5, 16); |
+ frag->sample_group_description.entries[2].iv_size = 0; |
+ frag->sample_group_description.entries[2].crypt_byte_block = 1; |
+ frag->sample_group_description.entries[2].skip_byte_block = 9; |
+ frag->sample_group_description.entries[2].constant_iv_size = 16; |
+ memcpy(frag->sample_group_description.entries[2].constant_iv, kIv5, 16); |
+ } |
+ |
+ void AddSampleEncryptionCbcs(TrackFragment* frag) { |
+ frag->sample_encryption.use_subsample_encryption = true; |
+ frag->sample_encryption.sample_encryption_data.assign( |
+ kSampleEncryptionDataWithSubsamplesAndConstantIv, |
+ kSampleEncryptionDataWithSubsamplesAndConstantIv + |
+ arraysize(kSampleEncryptionDataWithSubsamplesAndConstantIv)); |
+ |
+ // Update sample sizes and aux info header. |
+ frag->runs.resize(1); |
+ frag->runs[0].sample_count = 5; |
+ frag->auxiliary_offset.offsets.push_back(0); |
+ frag->auxiliary_size.sample_count = 5; |
+ // Update sample sizes to match with subsample entries above. |
+ frag->runs[0].sample_sizes[0] = 3; |
+ frag->runs[0].sample_sizes[1] = 10; |
+ frag->runs[0].sample_sizes[2] = 3; |
+ frag->runs[0].sample_sizes[3] = 3; |
+ frag->runs[0].sample_sizes[4] = 3; |
+ // Set aux info header. |
+ frag->auxiliary_size.sample_info_sizes.push_back(16); |
+ frag->auxiliary_size.sample_info_sizes.push_back(30); |
+ frag->auxiliary_size.sample_info_sizes.push_back(16); |
+ frag->auxiliary_size.sample_info_sizes.push_back(16); |
+ frag->auxiliary_size.sample_info_sizes.push_back(16); |
+ } |
+#endif |
+ |
bool InitMoofWithArbitraryAuxInfo(MovieFragment* moof) { |
// Add aux info header (equal sized aux info for every sample). |
for (uint32_t i = 0; i < moof->tracks.size(); ++i) { |
@@ -879,5 +989,97 @@ TEST_F(TrackRunIteratorTest, KeyFrameFlagCombinations) { |
EXPECT_EQ("2 K P P P K P", KeyframeAndRAPInfo(iter_.get())); |
} |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+TEST_F(TrackRunIteratorTest, DecryptConfigTestWithConstantIvNoAuxInfo) { |
+ AddEncryptionCbcs(&moov_.tracks[1]); |
+ iter_.reset(new TrackRunIterator(&moov_, media_log_)); |
+ |
+ MovieFragment moof = CreateFragment(); |
+ |
+ ASSERT_TRUE(iter_->Init(moof)); |
+ |
+ // The run for track 2 will be the second. |
+ iter_->AdvanceRun(); |
+ EXPECT_EQ(iter_->track_id(), 2u); |
+ EXPECT_TRUE(iter_->is_encrypted()); |
+ ASSERT_FALSE(iter_->AuxInfoNeedsToBeCached()); |
+ EXPECT_EQ(iter_->sample_offset(), 200); |
+ std::unique_ptr<DecryptConfig> config = iter_->GetDecryptConfig(); |
+ EXPECT_EQ( |
+ std::string(reinterpret_cast<const char*>(kKeyId), arraysize(kKeyId)), |
+ config->key_id()); |
+ EXPECT_EQ(std::string(reinterpret_cast<const char*>(kIv3), arraysize(kIv3)), |
+ config->iv()); |
+ EXPECT_TRUE(config->subsamples().empty()); |
+ iter_->AdvanceSample(); |
+ config = iter_->GetDecryptConfig(); |
+ EXPECT_EQ( |
+ std::string(reinterpret_cast<const char*>(kKeyId), arraysize(kKeyId)), |
+ config->key_id()); |
+ EXPECT_EQ(std::string(reinterpret_cast<const char*>(kIv3), arraysize(kIv3)), |
+ config->iv()); |
+ EXPECT_TRUE(config->subsamples().empty()); |
+} |
+ |
+TEST_F(TrackRunIteratorTest, DecryptConfigTestWithSampleGroupsAndConstantIv) { |
+ // Add TrackEncryption Box. |
+ AddEncryptionCbcs(&moov_.tracks[1]); |
+ |
+ MovieFragment moof = CreateFragment(); |
+ AddSampleEncryptionCbcs(&moof.tracks[1]); |
+ |
+ const SampleToGroupEntry kSampleToGroupTable[] = { |
+ // Associated with the 2nd entry in fragment SampleGroupDescription Box. |
+ {1, SampleToGroupEntry::kFragmentGroupDescriptionIndexBase + 2}, |
+ // Associated with the default values specified in TrackEncryption Box. |
+ {1, 0}, |
+ // Associated with the 1st entry in fragment SampleGroupDescription Box. |
+ {1, SampleToGroupEntry::kFragmentGroupDescriptionIndexBase + 1}, |
+ // Associated with the 1st entry in track SampleGroupDescription Box. |
+ {1, 1}}; |
+ AddCencSampleGroup(&moov_.tracks[1], &moof.tracks[1], kSampleToGroupTable, |
+ arraysize(kSampleToGroupTable)); |
+ AddConstantIvsToCencSampleGroup(&moov_.tracks[1], &moof.tracks[1]); |
+ iter_.reset(new TrackRunIterator(&moov_, media_log_)); |
+ ASSERT_TRUE(iter_->Init(moof)); |
+ |
+ // The run for track 2 will be the second. |
+ iter_->AdvanceRun(); |
+ |
+ std::string track_encryption_iv(kIv3, kIv3 + arraysize(kIv3)); |
+ std::string track_cenc_sample_group_iv(kIv4, kIv4 + arraysize(kIv4)); |
+ std::string fragment_cenc_sample_group_iv(kIv5, kIv5 + arraysize(kIv5)); |
+ |
+ for (size_t i = 0; i < kSampleToGroupTable[0].sample_count; ++i) { |
+ EXPECT_TRUE(iter_->is_encrypted()); |
+ EXPECT_EQ(fragment_cenc_sample_group_iv, iter_->GetDecryptConfig()->iv()); |
+ iter_->AdvanceSample(); |
+ } |
+ |
+ for (size_t i = 0; i < kSampleToGroupTable[1].sample_count; ++i) { |
+ EXPECT_TRUE(iter_->is_encrypted()); |
+ EXPECT_EQ(track_encryption_iv, iter_->GetDecryptConfig()->iv()); |
+ iter_->AdvanceSample(); |
+ } |
+ |
+ for (size_t i = 0; i < kSampleToGroupTable[2].sample_count; ++i) { |
+ EXPECT_FALSE(iter_->is_encrypted()); |
+ iter_->AdvanceSample(); |
+ } |
+ |
+ for (size_t i = 0; i < kSampleToGroupTable[3].sample_count; ++i) { |
+ EXPECT_TRUE(iter_->is_encrypted()); |
+ EXPECT_EQ(track_cenc_sample_group_iv, iter_->GetDecryptConfig()->iv()); |
+ iter_->AdvanceSample(); |
+ } |
+ |
+ // The remaining samples should be associated with the default values |
+ // specified in TrackEncryption Box. |
+ EXPECT_TRUE(iter_->is_encrypted()); |
+ EXPECT_EQ(track_encryption_iv, iter_->GetDecryptConfig()->iv()); |
+} |
+ |
+#endif |
+ |
} // namespace mp4 |
} // namespace media |