Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1298)

Unified Diff: media/mp4/box_definitions.cc

Issue 10534172: Implement ISO BMFF support in Media Source (try 2). (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..e59d050afe460981932a60742b04a2672f9736e6
--- /dev/null
+++ b/media/mp4/box_definitions.cc
@@ -0,0 +1,638 @@
+// 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(&timescale) &&
+ reader->Read8(&duration));
+ } else {
+ RCHECK(reader->Read4Into8(&creation_time) &&
+ reader->Read4Into8(&modification_time) &&
+ reader->Read4(&timescale) &&
+ 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 (std::vector<EditListEntry>::iterator 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() {}
+AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
+FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
+
+bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
+ RCHECK(reader->Read1(&version) && version == 1 &&
+ reader->Read1(&profile_indication) &&
+ reader->Read1(&profile_compatibility) &&
+ reader->Read1(&avc_level));
+
+ uint8 length_size_minus_one;
+ RCHECK(reader->Read1(&length_size_minus_one) &&
+ (length_size_minus_one & 0xfc) == 0xfc);
+ length_size = (length_size_minus_one & 0x3) + 1;
+
+ uint8 num_sps;
+ RCHECK(reader->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(reader->Read2(&sps_length) &&
+ reader->ReadVec(&sps_list[i], sps_length));
+ }
+
+ uint8 num_pps;
+ RCHECK(reader->Read1(&num_pps));
+
+ pps_list.resize(num_pps);
+ for (int i = 0; i < num_pps; i++) {
+ uint16 pps_length;
+ RCHECK(reader->Read2(&pps_length) &&
+ reader->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): finalize format signaling for encrypted media
+ // (http://crbug.com/132351)
+ //
+ // 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;
+
+ 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(&timescale) &&
+ reader->Read8(&duration));
+ } else {
+ RCHECK(reader->Read4Into8(&creation_time) &&
+ reader->Read4Into8(&modification_time) &&
+ reader->Read4(&timescale) &&
+ 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) &&
+ reader->ReadChildren(&tracks);
+}
+
+Movie::Movie() {}
+Movie::~Movie() {}
+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: reject tracks that set 'base-data-offset-present'.
+ // Although the Media Source requires that 'default-base-is-moof' (14496-12
+ // Amendment 2) be set, we omit this check as many otherwise-valid files in
+ // the wild don't set it.
+ //
+ // 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) != 0;
+ bool first_sample_flags_present = (flags & 0x4) != 0;
+ bool sample_duration_present = (flags & 0x100) != 0;
+ bool sample_size_present = (flags & 0x200) != 0;
+ bool sample_flags_present = (flags & 0x400) != 0;
+ bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
+
+ 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

Powered by Google App Engine
This is Rietveld 408576698