Chromium Code Reviews| Index: media/mp4/box_definitions.cc |
| diff --git a/media/mp4/box_definitions.cc b/media/mp4/box_definitions.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d127dc05d8b8ba5a3d132194df3b0cd137752566 |
| --- /dev/null |
| +++ b/media/mp4/box_definitions.cc |
| @@ -0,0 +1,640 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "media/mp4/box_definitions.h" |
| + |
| +#include "base/logging.h" |
| +#include "media/mp4/box_reader.h" |
| +#include "media/mp4/fourccs.h" |
| +#include "media/mp4/rcheck.h" |
| + |
| +namespace media { |
| +namespace mp4 { |
| + |
| +bool FileType::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFourCC(&major_brand) && reader->Read4(&minor_version)); |
| + size_t num_brands = (reader->size() - reader->pos()) / sizeof(FourCC); |
| + return reader->SkipBytes(sizeof(FourCC) * num_brands); // compatible_brands |
| +} |
| + |
| +ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {} |
| +ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {} |
| +FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; } |
| + |
| +bool ProtectionSystemSpecificHeader::Parse(BoxReader* reader) { |
| + uint32 size; |
| + return reader->SkipBytes(4) && |
| + reader->ReadVec(&system_id, 16) && |
| + reader->Read4(&size) && |
| + reader->ReadVec(&data, size); |
| +} |
| + |
| +SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {} |
| +SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {} |
| +FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; } |
| + |
| +bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader()); |
| + if (reader->flags() & 1) |
| + RCHECK(reader->SkipBytes(8)); |
| + |
| + uint32 count; |
| + RCHECK(reader->Read4(&count) && |
| + reader->HasBytes(count * (reader->version() == 1 ? 8 : 4))); |
| + offsets.resize(count); |
| + |
| + for (uint32 i = 0; i < count; i++) { |
| + if (reader->version() == 1) { |
| + RCHECK(reader->Read8(&offsets[i])); |
| + } else { |
| + RCHECK(reader->Read4Into8(&offsets[i])); |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize() |
| + : default_sample_info_size(0), sample_count(0) { |
| +} |
| +SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {} |
| +FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; } |
| + |
| +bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader()); |
| + if (reader->flags() & 1) |
| + RCHECK(reader->SkipBytes(8)); |
| + |
| + RCHECK(reader->Read1(&default_sample_info_size) && |
| + reader->Read4(&sample_count)); |
| + if (default_sample_info_size == 0) |
| + return reader->ReadVec(&sample_info_sizes, sample_count); |
| + return true; |
| +} |
| + |
| +OriginalFormat::OriginalFormat() {} |
| +OriginalFormat::~OriginalFormat() {} |
| +FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; } |
| + |
| +bool OriginalFormat::Parse(BoxReader* reader) { |
| + return reader->ReadFourCC(&format); |
| +} |
| + |
| +SchemeType::SchemeType() {} |
| +SchemeType::~SchemeType() {} |
| +FourCC SchemeType::BoxType() const { return FOURCC_SCHM; } |
| + |
| +bool SchemeType::Parse(BoxReader* reader) { |
| + RCHECK(reader->SkipBytes(4) && |
| + reader->ReadFourCC(&type) && |
| + reader->Read4(&version)); |
| + RCHECK(type == FOURCC_CENC); |
| + return true; |
| +} |
| + |
| +TrackEncryption::TrackEncryption() |
| + : is_encrypted(false), default_iv_size(0) { |
| +} |
| +TrackEncryption::~TrackEncryption() {} |
| +FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; } |
| + |
| +bool TrackEncryption::Parse(BoxReader* reader) { |
| + uint8 flag; |
| + RCHECK(reader->SkipBytes(2) && |
| + reader->Read1(&flag) && |
| + reader->Read1(&default_iv_size) && |
| + reader->ReadVec(&default_kid, 16)); |
| + is_encrypted = (flag != 0); |
| + if (is_encrypted) { |
| + RCHECK(default_iv_size == 8 || default_iv_size == 16); |
| + } else { |
| + RCHECK(default_iv_size == 0); |
| + } |
| + return true; |
| +} |
| + |
| +SchemeInfo::SchemeInfo() {} |
| +SchemeInfo::~SchemeInfo() {} |
| +FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; } |
| + |
| +bool SchemeInfo::Parse(BoxReader* reader) { |
| + return reader->ScanChildren() && reader->ReadChild(&track_encryption); |
| +} |
| + |
| +ProtectionSchemeInfo::ProtectionSchemeInfo() {} |
| +ProtectionSchemeInfo::~ProtectionSchemeInfo() {} |
| +FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; } |
| + |
| +bool ProtectionSchemeInfo::Parse(BoxReader* reader) { |
| + return reader->ScanChildren() && |
| + reader->ReadChild(&type) && |
| + reader->ReadChild(&info); |
| +} |
| + |
| +MovieHeader::MovieHeader() {} |
| +MovieHeader::~MovieHeader() {} |
| +FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; } |
| + |
| +bool MovieHeader::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader()); |
| + |
| + if (reader->version() == 1) { |
| + RCHECK(reader->Read8(&creation_time) && |
| + reader->Read8(&modification_time) && |
| + reader->Read4(×cale) && |
| + reader->Read8(&duration)); |
| + } else { |
| + RCHECK(reader->Read4Into8(&creation_time) && |
| + reader->Read4Into8(&modification_time) && |
| + reader->Read4(×cale) && |
| + reader->Read4Into8(&duration)); |
| + } |
| + |
| + RCHECK(reader->Read4s(&rate) && |
| + reader->Read2s(&volume) && |
| + reader->SkipBytes(10) && // reserved |
| + reader->SkipBytes(36) && // matrix |
| + reader->SkipBytes(24) && // predefined zero |
| + reader->Read4(&next_track_id)); |
| + return true; |
| +} |
| + |
| +TrackHeader::TrackHeader() {} |
| +TrackHeader::~TrackHeader() {} |
| +FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; } |
| + |
| +bool TrackHeader::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader()); |
| + if (reader->version() == 1) { |
| + RCHECK(reader->Read8(&creation_time) && |
| + reader->Read8(&modification_time) && |
| + reader->Read4(&track_id) && |
| + reader->SkipBytes(4) && // reserved |
| + reader->Read8(&duration)); |
| + } else { |
| + RCHECK(reader->Read4Into8(&creation_time) && |
| + reader->Read4Into8(&modification_time) && |
| + reader->Read4(&track_id) && |
| + reader->SkipBytes(4) && // reserved |
| + reader->Read4Into8(&duration)); |
| + } |
| + |
| + RCHECK(reader->SkipBytes(8) && // reserved |
| + reader->Read2s(&layer) && |
| + reader->Read2s(&alternate_group) && |
| + reader->Read2s(&volume) && |
| + reader->SkipBytes(2) && // reserved |
| + reader->SkipBytes(36) && // matrix |
| + reader->Read4(&width) && |
| + reader->Read4(&height)); |
| + width >>= 16; |
| + height >>= 16; |
| + return true; |
| +} |
| + |
| +SampleDescription::SampleDescription() {} |
| +SampleDescription::~SampleDescription() {} |
| +FourCC SampleDescription::BoxType() const { return FOURCC_STSD; } |
| + |
| +bool SampleDescription::Parse(BoxReader* reader) { |
| + uint32 count; |
| + RCHECK(reader->SkipBytes(4) && |
| + reader->Read4(&count) && |
| + reader->ScanChildren()); |
| + video_entries.clear(); |
| + audio_entries.clear(); |
| + |
| + // Note: this value is preset before scanning begins. See comments in the |
| + // Parse(Media*) function. |
| + if (type == kVideo) { |
| + RCHECK(reader->ReadAllChildren(&video_entries)); |
| + } else if (type == kAudio) { |
| + RCHECK(reader->ReadAllChildren(&audio_entries)); |
| + } |
| + return true; |
| +} |
| + |
| +SampleTable::SampleTable() {} |
| +SampleTable::~SampleTable() {} |
| +FourCC SampleTable::BoxType() const { return FOURCC_STBL; } |
| + |
| +bool SampleTable::Parse(BoxReader* reader) { |
| + return reader->ScanChildren() && |
| + reader->ReadChild(&description); |
| +} |
| + |
| +EditList::EditList() {} |
| +EditList::~EditList() {} |
| +FourCC EditList::BoxType() const { return FOURCC_ELST; } |
| + |
| +bool EditList::Parse(BoxReader* reader) { |
| + uint32 count; |
| + RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count)); |
| + |
| + if (reader->version() == 1) { |
| + RCHECK(reader->HasBytes(count * 20)); |
| + } else { |
| + RCHECK(reader->HasBytes(count * 12)); |
| + } |
| + edits.resize(count); |
| + |
| + for (auto edit = edits.begin(); edit != edits.end(); ++edit) { |
| + if (reader->version() == 1) { |
| + RCHECK(reader->Read8(&edit->segment_duration) && |
| + reader->Read8s(&edit->media_time)); |
| + } else { |
| + RCHECK(reader->Read4Into8(&edit->segment_duration) && |
| + reader->Read4sInto8s(&edit->media_time)); |
| + } |
| + RCHECK(reader->Read2s(&edit->media_rate_integer) && |
| + reader->Read2s(&edit->media_rate_fraction)); |
| + } |
| + return true; |
| +} |
| + |
| +Edit::Edit() {} |
| +Edit::~Edit() {} |
| +FourCC Edit::BoxType() const { return FOURCC_EDTS; } |
| + |
| +bool Edit::Parse(BoxReader* reader) { |
| + return reader->ScanChildren() && reader->ReadChild(&list); |
| +} |
| + |
| +HandlerReference::HandlerReference() {} |
| +HandlerReference::~HandlerReference() {} |
| +FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; } |
| + |
| +bool HandlerReference::Parse(BoxReader* reader) { |
| + FourCC hdlr_type; |
| + RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type)); |
| + // Note: remaining fields in box ignored |
| + if (hdlr_type == FOURCC_VIDE) { |
| + type = kVideo; |
| + } else if (hdlr_type == FOURCC_SOUN) { |
| + type = kAudio; |
| + } else { |
| + type = kInvalid; |
| + } |
| + return true; |
| +} |
| + |
| +AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord() {}; |
|
acolwell GONE FROM CHROMIUM
2012/06/08 16:10:38
lint nit: remove ;
strobe_
2012/06/11 18:44:21
Done.
|
| +AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}; |
|
acolwell GONE FROM CHROMIUM
2012/06/08 16:10:38
lint nit: remove ;
strobe_
2012/06/11 18:44:21
Done.
|
| +FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; } |
| + |
| +bool AVCDecoderConfigurationRecord::Parse(BoxReader* readereader) { |
| + RCHECK(readereader->Read1(&version) && version == 1 && |
|
acolwell GONE FROM CHROMIUM
2012/06/08 16:10:38
Oops :) readereader -> reader
strobe_
2012/06/11 18:44:21
Heh. Done.
|
| + readereader->Read1(&profile_indication) && |
| + readereader->Read1(&profile_compatibility) && |
| + readereader->Read1(&avc_level)); |
| + |
| + uint8 length_size_minus_one; |
| + RCHECK(readereader->Read1(&length_size_minus_one) && |
| + (length_size_minus_one & 0xfc) == 0xfc); |
| + length_size = (length_size_minus_one & 0x3) + 1; |
| + |
| + uint8 num_sps; |
| + RCHECK(readereader->Read1(&num_sps) && (num_sps & 0xe0) == 0xe0); |
| + num_sps &= 0x1f; |
| + |
| + sps_list.resize(num_sps); |
| + for (int i = 0; i < num_sps; i++) { |
| + uint16 sps_length; |
| + RCHECK(readereader->Read2(&sps_length) && |
| + readereader->ReadVec(&sps_list[i], sps_length)); |
| + } |
| + |
| + uint8 num_pps; |
| + RCHECK(readereader->Read1(&num_pps)); |
| + |
| + pps_list.resize(num_pps); |
| + for (int i = 0; i < num_pps; i++) { |
| + uint16 pps_length; |
| + RCHECK(readereader->Read2(&pps_length) && |
| + readereader->ReadVec(&pps_list[i], pps_length)); |
| + } |
| + |
| + return true; |
| +} |
| + |
| +VideoSampleEntry::VideoSampleEntry() {} |
| +VideoSampleEntry::~VideoSampleEntry() {} |
| +FourCC VideoSampleEntry::BoxType() const { |
| + DCHECK(false) << "VideoSampleEntry should be parsed according to the " |
| + << "handler type recovered in its Media ancestor."; |
| + return FOURCC_NULL; |
| +} |
| + |
| +bool VideoSampleEntry::Parse(BoxReader* reader) { |
| + format = reader->type(); |
| + RCHECK(reader->SkipBytes(6) && |
| + reader->Read2(&data_reference_index) && |
| + reader->SkipBytes(16) && |
| + reader->Read2(&width) && |
| + reader->Read2(&height) && |
| + reader->SkipBytes(50)); |
| + |
| + RCHECK(reader->ScanChildren()); |
| + if (format == FOURCC_ENCV) { |
| + RCHECK(reader->ReadChild(&sinf)); |
| + } |
| + |
| + // TODO(strobe): Widevine test files do not follow spec here; check disabled |
|
acolwell GONE FROM CHROMIUM
2012/06/08 16:10:38
lint nit: 2 spaces after // here and below
strobe_
2012/06/11 18:44:21
Done.
|
| + //if (format == FOURCC_AVC1 || |
| + // (format == FOURCC_ENCV && |
| + // sinf.format.format == FOURCC_AVC1)) { |
| + RCHECK(reader->ReadChild(&avcc)); |
| + //} |
| + return true; |
| +} |
| + |
| +AudioSampleEntry::AudioSampleEntry() {} |
| +AudioSampleEntry::~AudioSampleEntry() {} |
| +FourCC AudioSampleEntry::BoxType() const { |
| + DCHECK(false) << "AudioSampleEntry should be parsed according to the " |
| + << "handler type recovered in its Media ancestor."; |
| + return FOURCC_NULL; |
| +} |
| + |
| +bool AudioSampleEntry::Parse(BoxReader* reader) { |
| + format = reader->type(); |
| + RCHECK(reader->SkipBytes(6) && |
| + reader->Read2(&data_reference_index) && |
| + reader->SkipBytes(8) && |
| + reader->Read2(&channelcount) && |
| + reader->Read2(&samplesize) && |
| + reader->SkipBytes(4) && |
| + reader->Read4(&samplerate)); |
| + // Convert from 16.16 fixed point to integer |
| + samplerate >>= 16; |
|
acolwell GONE FROM CHROMIUM
2012/06/08 16:10:38
How does mp4 handle 96kHz audio?
strobe_
2012/06/11 18:44:21
Poorly. ;)
BMFF supports a lot of crazy things, b
acolwell GONE FROM CHROMIUM
2012/06/13 14:16:06
Ok. I'm fine with leaving this code as is for now.
|
| + |
| + RCHECK(reader->ScanChildren()); |
| + if (format == FOURCC_ENCA) { |
| + RCHECK(reader->ReadChild(&sinf)); |
| + } |
| + return true; |
| +} |
| + |
| +MediaHeader::MediaHeader() {} |
| +MediaHeader::~MediaHeader() {} |
| +FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; } |
| + |
| +bool MediaHeader::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader()); |
| + |
| + if (reader->version() == 1) { |
| + RCHECK(reader->Read8(&creation_time) && |
| + reader->Read8(&modification_time) && |
| + reader->Read4(×cale) && |
| + reader->Read8(&duration)); |
| + } else { |
| + RCHECK(reader->Read4Into8(&creation_time) && |
| + reader->Read4Into8(&modification_time) && |
| + reader->Read4(×cale) && |
| + reader->Read4Into8(&duration)); |
| + } |
| + // Skip language information |
| + return reader->SkipBytes(4); |
| +} |
| + |
| +MediaInformation::MediaInformation() {} |
| +MediaInformation::~MediaInformation() {} |
| +FourCC MediaInformation::BoxType() const { return FOURCC_MINF; } |
| + |
| +bool MediaInformation::Parse(BoxReader* reader) { |
| + return reader->ScanChildren() && |
| + reader->ReadChild(&sample_table); |
| +} |
| + |
| +Media::Media() {} |
| +Media::~Media() {} |
| +FourCC Media::BoxType() const { return FOURCC_MDIA; } |
| + |
| +bool Media::Parse(BoxReader* reader) { |
| + RCHECK(reader->ScanChildren() && |
| + reader->ReadChild(&header) && |
| + reader->ReadChild(&handler)); |
| + |
| + // Maddeningly, the HandlerReference box specifies how to parse the |
| + // SampleDescription box, making the latter the only box (of those that we |
| + // support) which cannot be parsed correctly on its own (or even with |
| + // information from its strict ancestor tree). We thus copy the handler type |
| + // to the sample description box *before* parsing it to provide this |
| + // information while parsing. |
| + information.sample_table.description.type = handler.type; |
| + RCHECK(reader->ReadChild(&information)); |
| + return true; |
| +} |
| + |
| +Track::Track() {} |
| +Track::~Track() {} |
| +FourCC Track::BoxType() const { return FOURCC_TRAK; } |
| + |
| +bool Track::Parse(BoxReader* reader) { |
| + RCHECK(reader->ScanChildren() && |
| + reader->ReadChild(&header) && |
| + reader->ReadChild(&media) && |
| + reader->MaybeReadChild(&edit)); |
| + return true; |
| +} |
| + |
| +MovieExtendsHeader::MovieExtendsHeader() {} |
| +MovieExtendsHeader::~MovieExtendsHeader() {} |
| +FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; } |
| + |
| +bool MovieExtendsHeader::Parse(BoxReader* reader) { |
| + RCHECK(reader->Read8(&fragment_duration)); |
| + return true; |
| +} |
| + |
| +TrackExtends::TrackExtends() {} |
| +TrackExtends::~TrackExtends() {} |
| +FourCC TrackExtends::BoxType() const { return FOURCC_TREX; } |
| + |
| +bool TrackExtends::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader() && |
| + reader->Read4(&track_id) && |
| + reader->Read4(&default_sample_description_index) && |
| + reader->Read4(&default_sample_duration) && |
| + reader->Read4(&default_sample_size) && |
| + reader->Read4(&default_sample_flags)); |
| + return true; |
| +} |
| + |
| +MovieExtends::MovieExtends() {} |
| +MovieExtends::~MovieExtends() {} |
| +FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; } |
| + |
| +bool MovieExtends::Parse(BoxReader* reader) { |
| + header.fragment_duration = 0; |
| + return reader->ScanChildren() && |
| + reader->MaybeReadChild(&header) && |
| + // TODO(strobe): does not detect correspondence rule (trex must match |
| + // one-to-one with trak) |
| + reader->ReadChildren(&tracks); |
| +} |
| + |
| +Movie::Movie() {}; |
|
acolwell GONE FROM CHROMIUM
2012/06/08 16:10:38
lint nit: remove ;
strobe_
2012/06/11 18:44:21
Done.
|
| +Movie::~Movie() {}; |
|
acolwell GONE FROM CHROMIUM
2012/06/08 16:10:38
lint nit: remove ;
strobe_
2012/06/11 18:44:21
Done.
|
| +FourCC Movie::BoxType() const { return FOURCC_MOOV; } |
| + |
| +bool Movie::Parse(BoxReader* reader) { |
| + return reader->ScanChildren() && |
| + reader->ReadChild(&header) && |
| + reader->ReadChildren(&tracks) && |
| + // Media Source specific: 'mvex' required |
| + reader->ReadChild(&extends) && |
| + reader->MaybeReadChildren(&pssh); |
| +} |
| + |
| +TrackFragmentDecodeTime::TrackFragmentDecodeTime() {} |
| +TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {} |
| +FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; } |
| + |
| +bool TrackFragmentDecodeTime::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader()); |
| + if (reader->version() == 1) |
| + return reader->Read8(&decode_time); |
| + else |
| + return reader->Read4Into8(&decode_time); |
| +} |
| + |
| +MovieFragmentHeader::MovieFragmentHeader() {} |
| +MovieFragmentHeader::~MovieFragmentHeader() {} |
| +FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; } |
| + |
| +bool MovieFragmentHeader::Parse(BoxReader* reader) { |
| + return reader->SkipBytes(4) && reader->Read4(&sequence_number); |
| +} |
| + |
| +TrackFragmentHeader::TrackFragmentHeader() {} |
| +TrackFragmentHeader::~TrackFragmentHeader() {} |
| +FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; } |
| + |
| +bool TrackFragmentHeader::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id)); |
| + |
| + // Media Source specific: we require that 'default-base-is-moof' (14496-12 |
| + // Amendment 2) be set, and reject tracks that set 'base-data-offset-present'. |
| + // |
| + // TODO(strobe): Test files do not have 'default-base-is-moof' set explicitly |
| + // (although they are structured as if it is set). Because this flag is hidden |
| + // in Amendment 2, it might not be set by all implementors. Should we reject |
| + // such files, or try them anyway? |
| + // |
| + // RCHECK((flags & 0x020000) && !(flags & 0x1)); |
| + RCHECK(!(reader->flags() & 0x1)); |
| + |
| + if (reader->flags() & 0x2) |
| + RCHECK(reader->SkipBytes(4)); // sample_description_index |
| + |
| + if (reader->flags() & 0x8) { |
| + RCHECK(reader->Read4(&default_sample_duration)); |
| + } else { |
| + default_sample_duration = 0; |
| + } |
| + |
| + if (reader->flags() & 0x10) { |
| + RCHECK(reader->Read4(&default_sample_size)); |
| + } else { |
| + default_sample_size = 0; |
| + } |
| + |
| + if (reader->flags() & 0x20) { |
| + RCHECK(reader->Read4(&default_sample_flags)); |
| + has_default_sample_flags = true; |
| + } else { |
| + has_default_sample_flags = false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +TrackFragmentRun::TrackFragmentRun() {} |
| +TrackFragmentRun::~TrackFragmentRun() {} |
| +FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; } |
| + |
| +bool TrackFragmentRun::Parse(BoxReader* reader) { |
| + RCHECK(reader->ReadFullBoxHeader() && |
| + reader->Read4(&sample_count)); |
| + const uint32 flags = reader->flags(); |
| + |
| + bool data_offset_present = flags & 0x1; |
| + bool first_sample_flags_present = flags & 0x4; |
| + bool sample_duration_present = flags & 0x100; |
| + bool sample_size_present = flags & 0x200; |
| + bool sample_flags_present = flags & 0x400; |
| + bool sample_composition_time_offsets_present = flags & 0x800; |
| + |
| + if (data_offset_present) { |
| + RCHECK(reader->Read4(&data_offset)); |
| + } else { |
| + data_offset = 0; |
| + } |
| + |
| + uint32 first_sample_flags; |
| + if (first_sample_flags_present) |
| + RCHECK(reader->Read4(&first_sample_flags)); |
| + |
| + int fields = sample_duration_present + sample_size_present + |
| + sample_flags_present + sample_composition_time_offsets_present; |
| + RCHECK(reader->HasBytes(fields * sample_count)); |
| + |
| + if (sample_duration_present) |
| + sample_durations.resize(sample_count); |
| + if (sample_size_present) |
| + sample_sizes.resize(sample_count); |
| + if (sample_flags_present) |
| + sample_flags.resize(sample_count); |
| + if (sample_composition_time_offsets_present) |
| + sample_composition_time_offsets.resize(sample_count); |
| + |
| + for (uint32 i = 0; i < sample_count; ++i) { |
| + if (sample_duration_present) |
| + RCHECK(reader->Read4(&sample_durations[i])); |
| + if (sample_size_present) |
| + RCHECK(reader->Read4(&sample_sizes[i])); |
| + if (sample_flags_present) |
| + RCHECK(reader->Read4(&sample_flags[i])); |
| + if (sample_composition_time_offsets_present) |
| + RCHECK(reader->Read4(&sample_composition_time_offsets[i])); |
| + } |
| + |
| + if (first_sample_flags_present) { |
| + if (sample_flags.size() == 0) { |
| + sample_flags.push_back(first_sample_flags); |
| + } else { |
| + sample_flags[0] = first_sample_flags; |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +TrackFragment::TrackFragment() {} |
| +TrackFragment::~TrackFragment() {} |
| +FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; } |
| + |
| +bool TrackFragment::Parse(BoxReader* reader) { |
| + return reader->ScanChildren() && |
| + reader->ReadChild(&header) && |
| + // Media Source specific: 'tfdt' required |
| + reader->ReadChild(&decode_time) && |
| + reader->MaybeReadChildren(&runs) && |
| + reader->MaybeReadChild(&auxiliary_offset) && |
| + reader->MaybeReadChild(&auxiliary_size); |
| +} |
| + |
| +MovieFragment::MovieFragment() {} |
| +MovieFragment::~MovieFragment() {} |
| +FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; } |
| + |
| +bool MovieFragment::Parse(BoxReader* reader) { |
| + RCHECK(reader->ScanChildren() && |
| + reader->ReadChild(&header) && |
| + reader->ReadChildren(&tracks) && |
| + reader->MaybeReadChildren(&pssh)); |
| + return true; |
| +} |
| + |
| +} // namespace mp4 |
| +} // namespace media |