| 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;
|
| }
|
|
|