Chromium Code Reviews| Index: media/formats/mp4/box_definitions.cc |
| diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc |
| index 82a94709f73f5572dd0f2dc6b52fe5c41080b9fb..509a8ef46d59c6809a973656fd56bf19b84087e1 100644 |
| --- a/media/formats/mp4/box_definitions.cc |
| +++ b/media/formats/mp4/box_definitions.cc |
| @@ -23,6 +23,12 @@ |
| namespace media { |
| namespace mp4 { |
| +namespace { |
| + |
| +const size_t kKeyIdSize = 16; |
| + |
| +} // namespace |
| + |
| FileType::FileType() {} |
| FileType::FileType(const FileType& other) = default; |
| FileType::~FileType() {} |
| @@ -157,8 +163,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). Subsequent editions allow |iv_size| |
|
ddorwin
2016/06/17 23:32:40
nit: It would be nice to specify which edition add
dougsteed
2016/10/10 18:18:01
Done.
|
| + // 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. |
|
ddorwin
2016/06/17 23:32:40
Do you mean the caller of this function? I assume
dougsteed
2016/10/10 18:18:01
Actually it's in track_run_iterator.cc, line 502.
|
| + 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++) |
| @@ -232,7 +240,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() {} |
| @@ -240,16 +256,28 @@ FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; } |
| bool TrackEncryption::Parse(BoxReader* reader) { |
| uint8_t flag; |
| - RCHECK(reader->ReadFullBoxHeader() && |
| - reader->SkipBytes(2) && |
| - reader->Read1(&flag) && |
| + uint8_t possible_pattern_info; |
| + RCHECK(reader->ReadFullBoxHeader() && reader->SkipBytes(1) && |
|
ddorwin
2016/06/17 23:32:40
What is being skipped? Should we document this?
dougsteed
2016/10/10 18:18:01
A reserved byte.
|
| + reader->Read1(&possible_pattern_info) && reader->Read1(&flag) && |
|
ddorwin
2016/06/17 23:32:40
Did they use reserved bits or something? Why is th
dougsteed
2016/10/10 18:18:01
Yes. There were two reserved bytes. They reassigne
|
| reader->Read1(&default_iv_size) && |
| - reader->ReadVec(&default_kid, 16)); |
| + reader->ReadVec(&default_kid, kKeyIdSize)); |
| is_encrypted = (flag != 0); |
| - if (is_encrypted) { |
| + if (default_iv_size != 0) { |
| RCHECK(default_iv_size == 8 || default_iv_size == 16); |
| +#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
|
ddorwin
2016/06/17 23:32:40
Should this be inside the else if - with a #else t
dougsteed
2016/10/10 18:18:01
I agree. It was unclear. Rearranged it a bit to (h
|
| + } else if (is_encrypted) { |
|
ddorwin
2016/06/17 23:32:40
What is the relationship between this block and de
dougsteed
2016/10/10 18:18:01
see above.
|
| + if (reader->version() > 0) { |
| + default_crypt_byte_block = (possible_pattern_info >> 4) & 0x0f; |
| + default_skip_byte_block = possible_pattern_info & 0x0f; |
| + } |
| + RCHECK(reader->Read1(&default_constant_iv_size) && |
| + (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)); |
| +#endif |
| } else { |
| - RCHECK(default_iv_size == 0); |
| + RCHECK(!is_encrypted); |
| } |
| return true; |
| } |
| @@ -273,7 +301,7 @@ 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 |
| @@ -282,6 +310,17 @@ bool ProtectionSchemeInfo::Parse(BoxReader* reader) { |
| return true; |
| } |
| +bool ProtectionSchemeInfo::HasSupportedScheme() const { |
| + FourCC fourCC = type.type; |
| + if (fourCC == FOURCC_CENC) |
| + return true; |
| +#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
| + return fourCC == FOURCC_CBCS; |
|
ddorwin
2016/06/17 23:32:40
nit: If you follow the style for CENC, you don't n
dougsteed
2016/10/10 18:18:01
Done.
|
| +#else |
| + return false; |
| +#endif |
| +} |
| + |
| MovieHeader::MovieHeader() |
| : creation_time(0), |
| modification_time(0), |
| @@ -609,7 +648,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; |
| } |
| @@ -749,7 +788,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; |
| } |
| @@ -1089,11 +1128,46 @@ 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 (iv_size != 0) { |
|
ddorwin
2016/06/17 23:32:40
ditto on structure
note to self: I skipped this.
dougsteed
2016/10/10 18:18:01
Done.
|
| + RCHECK(iv_size == 8 || iv_size == 16); |
| +#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
| + } else if (is_encrypted) { |
| + crypt_byte_block = (possible_pattern_info >> 4) & 0x0f; |
| + skip_byte_block = possible_pattern_info & 0x0f; |
| + RCHECK(reader->Read1(&constant_iv_size) && |
| + (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)); |
| +#endif |
| + } else { |
| + RCHECK(!is_encrypted); |
| + } |
| + return true; |
| +} |
| + |
| SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {} |
| SampleGroupDescription::SampleGroupDescription( |
| const SampleGroupDescription& other) = default; |
| @@ -1112,7 +1186,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) { |
| @@ -1131,19 +1204,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; |
| } |
| @@ -1154,14 +1215,13 @@ TrackFragment::~TrackFragment() {} |
| FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; } |
| bool TrackFragment::Parse(BoxReader* reader) { |
| - RCHECK(reader->ScanChildren() && |
| - reader->ReadChild(&header) && |
| + RCHECK(reader->ScanChildren() && reader->ReadChild(&header) && |
| // Media Source specific: 'tfdt' required |
| - reader->ReadChild(&decode_time) && |
| - reader->MaybeReadChildren(&runs) && |
| + reader->ReadChild(&decode_time) && reader->MaybeReadChildren(&runs) && |
| reader->MaybeReadChild(&auxiliary_offset) && |
| reader->MaybeReadChild(&auxiliary_size) && |
| - reader->MaybeReadChild(&sdtp)); |
| + reader->MaybeReadChild(&sdtp) && |
| + reader->MaybeReadChild(&sample_encryption)); |
|
ddorwin
2016/06/17 23:32:40
Was this missed in a previous CL?
dougsteed
2016/10/10 18:18:01
It looks like this box was added in the 2nd Editio
|
| // There could be multiple SampleGroupDescription and SampleToGroup boxes with |
| // different grouping types. For common encryption, the relevant grouping type |