Index: media/formats/mp4/box_definitions.cc |
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc |
index 773b4a2ecd271e9cc0029fcdadbdf4581b08440a..6743605a66b425e18300b5be2c92f58ae22d5fe6 100644 |
--- a/media/formats/mp4/box_definitions.cc |
+++ b/media/formats/mp4/box_definitions.cc |
@@ -26,6 +26,12 @@ |
namespace media { |
namespace mp4 { |
+namespace { |
+ |
+const size_t kKeyIdSize = 16; |
+ |
+} // namespace |
+ |
FileType::FileType() {} |
FileType::FileType(const FileType& other) = default; |
FileType::~FileType() {} |
@@ -160,8 +166,10 @@ bool SampleEncryptionEntry::Parse(BufferReader* reader, |
uint8_t iv_size, |
bool has_subsamples) { |
// According to ISO/IEC FDIS 23001-7: CENC spec, IV should be either |
- // 64-bit (8-byte) or 128-bit (16-byte). |
- RCHECK(iv_size == 8 || iv_size == 16); |
+ // 64-bit (8-byte) or 128-bit (16-byte). The 3rd Edition allows |iv_size| |
+ // to be 0, for the case of a "constant IV". In this case, the existence of |
+ // the constant IV must be ensured by the caller. |
+ RCHECK(iv_size == 0 || iv_size == 8 || iv_size == 16); |
memset(initialization_vector, 0, sizeof(initialization_vector)); |
for (uint8_t i = 0; i < iv_size; i++) |
@@ -235,7 +243,15 @@ bool SchemeType::Parse(BoxReader* reader) { |
} |
TrackEncryption::TrackEncryption() |
- : is_encrypted(false), default_iv_size(0) { |
+ : is_encrypted(false), |
+ default_iv_size(0) |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ , |
+ default_crypt_byte_block(0), |
+ default_skip_byte_block(0), |
+ default_constant_iv_size(0) |
+#endif |
+{ |
} |
TrackEncryption::TrackEncryption(const TrackEncryption& other) = default; |
TrackEncryption::~TrackEncryption() {} |
@@ -243,14 +259,31 @@ FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; } |
bool TrackEncryption::Parse(BoxReader* reader) { |
uint8_t flag; |
+ uint8_t possible_pattern_info; |
RCHECK(reader->ReadFullBoxHeader() && |
- reader->SkipBytes(2) && |
- reader->Read1(&flag) && |
+ reader->SkipBytes(1) && // skip reserved byte |
+ reader->Read1(&possible_pattern_info) && reader->Read1(&flag) && |
reader->Read1(&default_iv_size) && |
- reader->ReadVec(&default_kid, 16)); |
+ reader->ReadVec(&default_kid, kKeyIdSize)); |
is_encrypted = (flag != 0); |
if (is_encrypted) { |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ if (reader->version() > 0) { |
+ default_crypt_byte_block = (possible_pattern_info >> 4) & 0x0f; |
+ default_skip_byte_block = possible_pattern_info & 0x0f; |
+ } |
+ if (default_iv_size == 0) { |
+ RCHECK(reader->Read1(&default_constant_iv_size)); |
+ RCHECK(default_constant_iv_size == 8 || default_constant_iv_size == 16); |
+ memset(default_constant_iv, 0, sizeof(default_constant_iv)); |
+ for (uint8_t i = 0; i < default_constant_iv_size; i++) |
+ RCHECK(reader->Read1(default_constant_iv + i)); |
+ } else { |
+ RCHECK(default_iv_size == 8 || default_iv_size == 16); |
+ } |
+#else |
RCHECK(default_iv_size == 8 || default_iv_size == 16); |
+#endif |
} else { |
RCHECK(default_iv_size == 0); |
} |
@@ -276,15 +309,26 @@ bool ProtectionSchemeInfo::Parse(BoxReader* reader) { |
RCHECK(reader->ScanChildren() && |
reader->ReadChild(&format) && |
reader->ReadChild(&type)); |
- if (type.type == FOURCC_CENC) |
+ if (HasSupportedScheme()) |
RCHECK(reader->ReadChild(&info)); |
// 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 |
+ // unsupported protection schemes. It is the parent box's responsibility to |
// ensure that this scheme type is a supported one. |
return true; |
} |
+bool ProtectionSchemeInfo::HasSupportedScheme() const { |
+ FourCC fourCC = type.type; |
+ if (fourCC == FOURCC_CENC) |
+ return true; |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ if (fourCC == FOURCC_CBCS) |
+ return true; |
+#endif |
+ return false; |
+} |
+ |
MovieHeader::MovieHeader() |
: version(0), |
creation_time(0), |
@@ -652,7 +696,7 @@ bool VideoSampleEntry::Parse(BoxReader* reader) { |
if (format == FOURCC_ENCV) { |
// Continue scanning until a recognized protection scheme is found, or until |
// we run out of protection schemes. |
- while (sinf.type.type != FOURCC_CENC) { |
+ while (!sinf.HasSupportedScheme()) { |
if (!reader->ReadChild(&sinf)) |
return false; |
} |
@@ -802,7 +846,7 @@ bool AudioSampleEntry::Parse(BoxReader* reader) { |
if (format == FOURCC_ENCA) { |
// Continue scanning until a recognized protection scheme is found, or until |
// we run out of protection schemes. |
- while (sinf.type.type != FOURCC_CENC) { |
+ while (!sinf.HasSupportedScheme()) { |
if (!reader->ReadChild(&sinf)) |
return false; |
} |
@@ -1142,11 +1186,50 @@ bool SampleToGroup::Parse(BoxReader* reader) { |
} |
CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry() |
- : is_encrypted(false), iv_size(0) {} |
+ : is_encrypted(false), |
+ iv_size(0) |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ , |
+ crypt_byte_block(0), |
+ skip_byte_block(0), |
+ constant_iv_size(0) |
+#endif |
+{ |
+} |
CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry( |
const CencSampleEncryptionInfoEntry& other) = default; |
CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {} |
+bool CencSampleEncryptionInfoEntry::Parse(BoxReader* reader) { |
+ uint8_t flag; |
+ uint8_t possible_pattern_info; |
+ RCHECK(reader->SkipBytes(1) && // reserved. |
+ reader->Read1(&possible_pattern_info) && reader->Read1(&flag) && |
+ reader->Read1(&iv_size) && reader->ReadVec(&key_id, kKeyIdSize)); |
+ |
+ is_encrypted = (flag != 0); |
+ if (is_encrypted) { |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ crypt_byte_block = (possible_pattern_info >> 4) & 0x0f; |
+ skip_byte_block = possible_pattern_info & 0x0f; |
+ if (iv_size == 0) { |
+ RCHECK(reader->Read1(&constant_iv_size)); |
+ RCHECK(constant_iv_size == 8 || constant_iv_size == 16); |
+ memset(constant_iv, 0, sizeof(constant_iv)); |
+ for (uint8_t i = 0; i < constant_iv_size; i++) |
+ RCHECK(reader->Read1(constant_iv + i)); |
+ } else { |
+ RCHECK(iv_size == 8 || iv_size == 16); |
+ } |
+#else |
+ RCHECK(iv_size == 8 || iv_size == 16); |
+#endif |
+ } else { |
+ RCHECK(iv_size == 0); |
+ } |
+ return true; |
+} |
+ |
SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {} |
SampleGroupDescription::SampleGroupDescription( |
const SampleGroupDescription& other) = default; |
@@ -1165,7 +1248,6 @@ bool SampleGroupDescription::Parse(BoxReader* reader) { |
const uint8_t version = reader->version(); |
- const size_t kKeyIdSize = 16; |
const size_t kEntrySize = sizeof(uint32_t) + kKeyIdSize; |
uint32_t default_length = 0; |
if (version == 1) { |
@@ -1184,19 +1266,7 @@ bool SampleGroupDescription::Parse(BoxReader* reader) { |
RCHECK(description_length >= kEntrySize); |
} |
} |
- |
- uint8_t flag; |
- RCHECK(reader->SkipBytes(2) && // reserved. |
- reader->Read1(&flag) && |
- reader->Read1(&entries[i].iv_size) && |
- reader->ReadVec(&entries[i].key_id, kKeyIdSize)); |
- |
- entries[i].is_encrypted = (flag != 0); |
- if (entries[i].is_encrypted) { |
- RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16); |
- } else { |
- RCHECK(entries[i].iv_size == 0); |
- } |
+ RCHECK(entries[i].Parse(reader)); |
} |
return true; |
} |