1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/formats/mp4/box_definitions.h"
7 #include "base/logging.h"
8 #include "media/formats/mp4/es_descriptor.h"
9 #include "media/formats/mp4/rcheck.h"
14 FileType::FileType() {}
15 FileType::~FileType() {}
16 FourCC FileType::BoxType() const { return FOURCC_FTYP; }
18 bool FileType::Parse(BoxReader* reader) {
19 RCHECK(reader->ReadFourCC(&major_brand) && reader->Read4(&minor_version));
20 size_t num_brands = (reader->size() - reader->pos()) / sizeof(FourCC);
21 return reader->SkipBytes(sizeof(FourCC) * num_brands); // compatible_brands
24 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
25 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
26 FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; }
28 bool ProtectionSystemSpecificHeader::Parse(BoxReader* reader) {
29 // Validate the box's contents and hang on to the system ID.
31 RCHECK(reader->ReadFullBoxHeader() &&
32 reader->ReadVec(&system_id, 16) &&
33 reader->Read4(&size) &&
34 reader->HasBytes(size));
36 // Copy the entire box, including the header, for passing to EME as initData.
37 DCHECK(raw_box.empty());
38 raw_box.assign(reader->data(), reader->data() + reader->size());
42 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
43 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
44 FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; }
46 bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) {
47 RCHECK(reader->ReadFullBoxHeader());
48 if (reader->flags() & 1)
49 RCHECK(reader->SkipBytes(8));
52 RCHECK(reader->Read4(&count) &&
53 reader->HasBytes(count * (reader->version() == 1 ? 8 : 4)));
54 offsets.resize(count);
56 for (uint32 i = 0; i < count; i++) {
57 if (reader->version() == 1) {
58 RCHECK(reader->Read8(&offsets[i]));
60 RCHECK(reader->Read4Into8(&offsets[i]));
66 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
67 : default_sample_info_size(0), sample_count(0) {
69 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
70 FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; }
72 bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) {
73 RCHECK(reader->ReadFullBoxHeader());
74 if (reader->flags() & 1)
75 RCHECK(reader->SkipBytes(8));
77 RCHECK(reader->Read1(&default_sample_info_size) &&
78 reader->Read4(&sample_count));
79 if (default_sample_info_size == 0)
80 return reader->ReadVec(&sample_info_sizes, sample_count);
84 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
85 OriginalFormat::~OriginalFormat() {}
86 FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; }
88 bool OriginalFormat::Parse(BoxReader* reader) {
89 return reader->ReadFourCC(&format);
92 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
93 SchemeType::~SchemeType() {}
94 FourCC SchemeType::BoxType() const { return FOURCC_SCHM; }
96 bool SchemeType::Parse(BoxReader* reader) {
97 RCHECK(reader->ReadFullBoxHeader() &&
98 reader->ReadFourCC(&type) &&
99 reader->Read4(&version));
103 TrackEncryption::TrackEncryption()
104 : is_encrypted(false), default_iv_size(0) {
106 TrackEncryption::~TrackEncryption() {}
107 FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; }
109 bool TrackEncryption::Parse(BoxReader* reader) {
111 RCHECK(reader->ReadFullBoxHeader() &&
112 reader->SkipBytes(2) &&
113 reader->Read1(&flag) &&
114 reader->Read1(&default_iv_size) &&
115 reader->ReadVec(&default_kid, 16));
116 is_encrypted = (flag != 0);
118 RCHECK(default_iv_size == 8 || default_iv_size == 16);
120 RCHECK(default_iv_size == 0);
125 SchemeInfo::SchemeInfo() {}
126 SchemeInfo::~SchemeInfo() {}
127 FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; }
129 bool SchemeInfo::Parse(BoxReader* reader) {
130 return reader->ScanChildren() && reader->ReadChild(&track_encryption);
133 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
134 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
135 FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; }
137 bool ProtectionSchemeInfo::Parse(BoxReader* reader) {
138 RCHECK(reader->ScanChildren() &&
139 reader->ReadChild(&format) &&
140 reader->ReadChild(&type));
141 if (type.type == FOURCC_CENC)
142 RCHECK(reader->ReadChild(&info));
143 // Other protection schemes are silently ignored. Since the protection scheme
144 // type can't be determined until this box is opened, we return 'true' for
145 // non-CENC protection scheme types. It is the parent box's responsibility to
146 // ensure that this scheme type is a supported one.
150 MovieHeader::MovieHeader()
152 modification_time(0),
158 MovieHeader::~MovieHeader() {}
159 FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; }
161 bool MovieHeader::Parse(BoxReader* reader) {
162 RCHECK(reader->ReadFullBoxHeader());
164 if (reader->version() == 1) {
165 RCHECK(reader->Read8(&creation_time) &&
166 reader->Read8(&modification_time) &&
167 reader->Read4(×cale) &&
168 reader->Read8(&duration));
170 RCHECK(reader->Read4Into8(&creation_time) &&
171 reader->Read4Into8(&modification_time) &&
172 reader->Read4(×cale) &&
173 reader->Read4Into8(&duration));
176 RCHECK(reader->Read4s(&rate) &&
177 reader->Read2s(&volume) &&
178 reader->SkipBytes(10) && // reserved
179 reader->SkipBytes(36) && // matrix
180 reader->SkipBytes(24) && // predefined zero
181 reader->Read4(&next_track_id));
185 TrackHeader::TrackHeader()
187 modification_time(0),
195 TrackHeader::~TrackHeader() {}
196 FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; }
198 bool TrackHeader::Parse(BoxReader* reader) {
199 RCHECK(reader->ReadFullBoxHeader());
200 if (reader->version() == 1) {
201 RCHECK(reader->Read8(&creation_time) &&
202 reader->Read8(&modification_time) &&
203 reader->Read4(&track_id) &&
204 reader->SkipBytes(4) && // reserved
205 reader->Read8(&duration));
207 RCHECK(reader->Read4Into8(&creation_time) &&
208 reader->Read4Into8(&modification_time) &&
209 reader->Read4(&track_id) &&
210 reader->SkipBytes(4) && // reserved
211 reader->Read4Into8(&duration));
214 RCHECK(reader->SkipBytes(8) && // reserved
215 reader->Read2s(&layer) &&
216 reader->Read2s(&alternate_group) &&
217 reader->Read2s(&volume) &&
218 reader->SkipBytes(2) && // reserved
219 reader->SkipBytes(36) && // matrix
220 reader->Read4(&width) &&
221 reader->Read4(&height));
227 SampleDescription::SampleDescription() : type(kInvalid) {}
228 SampleDescription::~SampleDescription() {}
229 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
231 bool SampleDescription::Parse(BoxReader* reader) {
233 RCHECK(reader->SkipBytes(4) &&
234 reader->Read4(&count));
235 video_entries.clear();
236 audio_entries.clear();
238 // Note: this value is preset before scanning begins. See comments in the
239 // Parse(Media*) function.
240 if (type == kVideo) {
241 RCHECK(reader->ReadAllChildren(&video_entries));
242 } else if (type == kAudio) {
243 RCHECK(reader->ReadAllChildren(&audio_entries));
248 SyncSample::SyncSample() : is_present(false) {}
249 SyncSample::~SyncSample() {}
250 FourCC SyncSample::BoxType() const { return FOURCC_STSS; }
252 bool SyncSample::Parse(BoxReader* reader) {
254 RCHECK(reader->ReadFullBoxHeader() &&
255 reader->Read4(&entry_count));
259 entries.resize(entry_count);
261 if (entry_count == 0)
264 for (size_t i = 0; i < entry_count; ++i)
265 RCHECK(reader->Read4(&entries[i]));
270 bool SyncSample::IsSyncSample(size_t k) const {
271 // ISO/IEC 14496-12 Section 8.6.2.1 : If the sync sample box is not present,
272 // every sample is a sync sample.
276 // ISO/IEC 14496-12 Section 8.6.2.3 : If entry_count is zero, there are no
277 // sync samples within the stream.
278 if (entries.size() == 0u)
281 for (size_t i = 0; i < entries.size(); ++i) {
289 SampleTable::SampleTable() {}
290 SampleTable::~SampleTable() {}
291 FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
293 bool SampleTable::Parse(BoxReader* reader) {
294 return reader->ScanChildren() &&
295 reader->ReadChild(&description) &&
296 reader->MaybeReadChild(&sync_sample);
299 EditList::EditList() {}
300 EditList::~EditList() {}
301 FourCC EditList::BoxType() const { return FOURCC_ELST; }
303 bool EditList::Parse(BoxReader* reader) {
305 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count));
307 if (reader->version() == 1) {
308 RCHECK(reader->HasBytes(count * 20));
310 RCHECK(reader->HasBytes(count * 12));
314 for (std::vector<EditListEntry>::iterator edit = edits.begin();
315 edit != edits.end(); ++edit) {
316 if (reader->version() == 1) {
317 RCHECK(reader->Read8(&edit->segment_duration) &&
318 reader->Read8s(&edit->media_time));
320 RCHECK(reader->Read4Into8(&edit->segment_duration) &&
321 reader->Read4sInto8s(&edit->media_time));
323 RCHECK(reader->Read2s(&edit->media_rate_integer) &&
324 reader->Read2s(&edit->media_rate_fraction));
331 FourCC Edit::BoxType() const { return FOURCC_EDTS; }
333 bool Edit::Parse(BoxReader* reader) {
334 return reader->ScanChildren() && reader->ReadChild(&list);
337 HandlerReference::HandlerReference() : type(kInvalid) {}
338 HandlerReference::~HandlerReference() {}
339 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
341 bool HandlerReference::Parse(BoxReader* reader) {
343 RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type));
344 // Note: remaining fields in box ignored
345 if (hdlr_type == FOURCC_VIDE) {
347 } else if (hdlr_type == FOURCC_SOUN) {
355 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
357 profile_indication(0),
358 profile_compatibility(0),
362 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
363 FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
365 bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
366 return ParseInternal(reader, reader->log_cb());
369 bool AVCDecoderConfigurationRecord::Parse(const uint8* data, int data_size) {
370 BufferReader reader(data, data_size);
371 return ParseInternal(&reader, LogCB());
374 bool AVCDecoderConfigurationRecord::ParseInternal(BufferReader* reader,
375 const LogCB& log_cb) {
376 RCHECK(reader->Read1(&version) && version == 1 &&
377 reader->Read1(&profile_indication) &&
378 reader->Read1(&profile_compatibility) &&
379 reader->Read1(&avc_level));
381 uint8 length_size_minus_one;
382 RCHECK(reader->Read1(&length_size_minus_one) &&
383 (length_size_minus_one & 0xfc) == 0xfc);
384 length_size = (length_size_minus_one & 0x3) + 1;
386 RCHECK(length_size != 3); // Only values of 1, 2, and 4 are valid.
389 RCHECK(reader->Read1(&num_sps) && (num_sps & 0xe0) == 0xe0);
392 sps_list.resize(num_sps);
393 for (int i = 0; i < num_sps; i++) {
395 RCHECK(reader->Read2(&sps_length) &&
396 reader->ReadVec(&sps_list[i], sps_length));
397 RCHECK(sps_list[i].size() > 4);
399 if (!log_cb.is_null()) {
400 MEDIA_LOG(log_cb) << "Video codec: avc1." << std::hex
401 << static_cast<int>(sps_list[i][1])
402 << static_cast<int>(sps_list[i][2])
403 << static_cast<int>(sps_list[i][3]);
408 RCHECK(reader->Read1(&num_pps));
410 pps_list.resize(num_pps);
411 for (int i = 0; i < num_pps; i++) {
413 RCHECK(reader->Read2(&pps_length) &&
414 reader->ReadVec(&pps_list[i], pps_length));
420 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
421 PixelAspectRatioBox::~PixelAspectRatioBox() {}
422 FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
424 bool PixelAspectRatioBox::Parse(BoxReader* reader) {
425 RCHECK(reader->Read4(&h_spacing) &&
426 reader->Read4(&v_spacing));
430 VideoSampleEntry::VideoSampleEntry()
431 : format(FOURCC_NULL),
432 data_reference_index(0),
436 VideoSampleEntry::~VideoSampleEntry() {}
437 FourCC VideoSampleEntry::BoxType() const {
438 DCHECK(false) << "VideoSampleEntry should be parsed according to the "
439 << "handler type recovered in its Media ancestor.";
443 bool VideoSampleEntry::Parse(BoxReader* reader) {
444 format = reader->type();
445 RCHECK(reader->SkipBytes(6) &&
446 reader->Read2(&data_reference_index) &&
447 reader->SkipBytes(16) &&
448 reader->Read2(&width) &&
449 reader->Read2(&height) &&
450 reader->SkipBytes(50));
452 RCHECK(reader->ScanChildren() &&
453 reader->MaybeReadChild(&pixel_aspect));
455 if (format == FOURCC_ENCV) {
456 // Continue scanning until a recognized protection scheme is found, or until
457 // we run out of protection schemes.
458 while (sinf.type.type != FOURCC_CENC) {
459 if (!reader->ReadChild(&sinf))
465 RCHECK(reader->ReadChild(&avcc));
470 bool VideoSampleEntry::IsFormatValid() const {
471 return format == FOURCC_AVC1 || format == FOURCC_AVC3 ||
472 (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 ||
473 sinf.format.format == FOURCC_AVC3));
476 ElementaryStreamDescriptor::ElementaryStreamDescriptor()
477 : object_type(kForbidden) {}
479 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
481 FourCC ElementaryStreamDescriptor::BoxType() const {
485 bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {
486 std::vector<uint8> data;
487 ESDescriptor es_desc;
489 RCHECK(reader->ReadFullBoxHeader());
490 RCHECK(reader->ReadVec(&data, reader->size() - reader->pos()));
491 RCHECK(es_desc.Parse(data));
493 object_type = es_desc.object_type();
495 if (object_type != 0x40) {
496 MEDIA_LOG(reader->log_cb()) << "Audio codec: mp4a."
497 << std::hex << static_cast<int>(object_type);
500 if (es_desc.IsAAC(object_type))
501 RCHECK(aac.Parse(es_desc.decoder_specific_info(), reader->log_cb()));
506 AudioSampleEntry::AudioSampleEntry()
507 : format(FOURCC_NULL),
508 data_reference_index(0),
513 AudioSampleEntry::~AudioSampleEntry() {}
515 FourCC AudioSampleEntry::BoxType() const {
516 DCHECK(false) << "AudioSampleEntry should be parsed according to the "
517 << "handler type recovered in its Media ancestor.";
521 bool AudioSampleEntry::Parse(BoxReader* reader) {
522 format = reader->type();
523 RCHECK(reader->SkipBytes(6) &&
524 reader->Read2(&data_reference_index) &&
525 reader->SkipBytes(8) &&
526 reader->Read2(&channelcount) &&
527 reader->Read2(&samplesize) &&
528 reader->SkipBytes(4) &&
529 reader->Read4(&samplerate));
530 // Convert from 16.16 fixed point to integer
533 RCHECK(reader->ScanChildren());
534 if (format == FOURCC_ENCA) {
535 // Continue scanning until a recognized protection scheme is found, or until
536 // we run out of protection schemes.
537 while (sinf.type.type != FOURCC_CENC) {
538 if (!reader->ReadChild(&sinf))
543 // ESDS is not valid in case of EAC3.
544 RCHECK(reader->MaybeReadChild(&esds));
548 MediaHeader::MediaHeader()
550 modification_time(0),
553 MediaHeader::~MediaHeader() {}
554 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
556 bool MediaHeader::Parse(BoxReader* reader) {
557 RCHECK(reader->ReadFullBoxHeader());
559 if (reader->version() == 1) {
560 RCHECK(reader->Read8(&creation_time) &&
561 reader->Read8(&modification_time) &&
562 reader->Read4(×cale) &&
563 reader->Read8(&duration));
565 RCHECK(reader->Read4Into8(&creation_time) &&
566 reader->Read4Into8(&modification_time) &&
567 reader->Read4(×cale) &&
568 reader->Read4Into8(&duration));
570 // Skip language information
571 return reader->SkipBytes(4);
574 MediaInformation::MediaInformation() {}
575 MediaInformation::~MediaInformation() {}
576 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
578 bool MediaInformation::Parse(BoxReader* reader) {
579 return reader->ScanChildren() &&
580 reader->ReadChild(&sample_table);
585 FourCC Media::BoxType() const { return FOURCC_MDIA; }
587 bool Media::Parse(BoxReader* reader) {
588 RCHECK(reader->ScanChildren() &&
589 reader->ReadChild(&header) &&
590 reader->ReadChild(&handler));
592 // Maddeningly, the HandlerReference box specifies how to parse the
593 // SampleDescription box, making the latter the only box (of those that we
594 // support) which cannot be parsed correctly on its own (or even with
595 // information from its strict ancestor tree). We thus copy the handler type
596 // to the sample description box *before* parsing it to provide this
597 // information while parsing.
598 information.sample_table.description.type = handler.type;
599 RCHECK(reader->ReadChild(&information));
605 FourCC Track::BoxType() const { return FOURCC_TRAK; }
607 bool Track::Parse(BoxReader* reader) {
608 RCHECK(reader->ScanChildren() &&
609 reader->ReadChild(&header) &&
610 reader->ReadChild(&media) &&
611 reader->MaybeReadChild(&edit));
615 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
616 MovieExtendsHeader::~MovieExtendsHeader() {}
617 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
619 bool MovieExtendsHeader::Parse(BoxReader* reader) {
620 RCHECK(reader->ReadFullBoxHeader());
621 if (reader->version() == 1) {
622 RCHECK(reader->Read8(&fragment_duration));
624 RCHECK(reader->Read4Into8(&fragment_duration));
629 TrackExtends::TrackExtends()
631 default_sample_description_index(0),
632 default_sample_duration(0),
633 default_sample_size(0),
634 default_sample_flags(0) {}
635 TrackExtends::~TrackExtends() {}
636 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
638 bool TrackExtends::Parse(BoxReader* reader) {
639 RCHECK(reader->ReadFullBoxHeader() &&
640 reader->Read4(&track_id) &&
641 reader->Read4(&default_sample_description_index) &&
642 reader->Read4(&default_sample_duration) &&
643 reader->Read4(&default_sample_size) &&
644 reader->Read4(&default_sample_flags));
648 MovieExtends::MovieExtends() {}
649 MovieExtends::~MovieExtends() {}
650 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
652 bool MovieExtends::Parse(BoxReader* reader) {
653 header.fragment_duration = 0;
654 return reader->ScanChildren() &&
655 reader->MaybeReadChild(&header) &&
656 reader->ReadChildren(&tracks);
659 Movie::Movie() : fragmented(false) {}
661 FourCC Movie::BoxType() const { return FOURCC_MOOV; }
663 bool Movie::Parse(BoxReader* reader) {
664 return reader->ScanChildren() &&
665 reader->ReadChild(&header) &&
666 reader->ReadChildren(&tracks) &&
667 // Media Source specific: 'mvex' required
668 reader->ReadChild(&extends) &&
669 reader->MaybeReadChildren(&pssh);
672 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
673 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
674 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
676 bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {
677 RCHECK(reader->ReadFullBoxHeader());
678 if (reader->version() == 1)
679 return reader->Read8(&decode_time);
681 return reader->Read4Into8(&decode_time);
684 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
685 MovieFragmentHeader::~MovieFragmentHeader() {}
686 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
688 bool MovieFragmentHeader::Parse(BoxReader* reader) {
689 return reader->SkipBytes(4) && reader->Read4(&sequence_number);
692 TrackFragmentHeader::TrackFragmentHeader()
694 sample_description_index(0),
695 default_sample_duration(0),
696 default_sample_size(0),
697 default_sample_flags(0),
698 has_default_sample_flags(false) {}
700 TrackFragmentHeader::~TrackFragmentHeader() {}
701 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
703 bool TrackFragmentHeader::Parse(BoxReader* reader) {
704 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id));
706 // Media Source specific: reject tracks that set 'base-data-offset-present'.
707 // Although the Media Source requires that 'default-base-is-moof' (14496-12
708 // Amendment 2) be set, we omit this check as many otherwise-valid files in
709 // the wild don't set it.
711 // RCHECK((flags & 0x020000) && !(flags & 0x1));
712 RCHECK(!(reader->flags() & 0x1));
714 if (reader->flags() & 0x2) {
715 RCHECK(reader->Read4(&sample_description_index));
717 sample_description_index = 0;
720 if (reader->flags() & 0x8) {
721 RCHECK(reader->Read4(&default_sample_duration));
723 default_sample_duration = 0;
726 if (reader->flags() & 0x10) {
727 RCHECK(reader->Read4(&default_sample_size));
729 default_sample_size = 0;
732 if (reader->flags() & 0x20) {
733 RCHECK(reader->Read4(&default_sample_flags));
734 has_default_sample_flags = true;
736 has_default_sample_flags = false;
742 TrackFragmentRun::TrackFragmentRun()
743 : sample_count(0), data_offset(0) {}
744 TrackFragmentRun::~TrackFragmentRun() {}
745 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
747 bool TrackFragmentRun::Parse(BoxReader* reader) {
748 RCHECK(reader->ReadFullBoxHeader() &&
749 reader->Read4(&sample_count));
750 const uint32 flags = reader->flags();
752 bool data_offset_present = (flags & 0x1) != 0;
753 bool first_sample_flags_present = (flags & 0x4) != 0;
754 bool sample_duration_present = (flags & 0x100) != 0;
755 bool sample_size_present = (flags & 0x200) != 0;
756 bool sample_flags_present = (flags & 0x400) != 0;
757 bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
759 if (data_offset_present) {
760 RCHECK(reader->Read4(&data_offset));
765 uint32 first_sample_flags;
766 if (first_sample_flags_present)
767 RCHECK(reader->Read4(&first_sample_flags));
769 int fields = sample_duration_present + sample_size_present +
770 sample_flags_present + sample_composition_time_offsets_present;
771 RCHECK(reader->HasBytes(fields * sample_count));
773 if (sample_duration_present)
774 sample_durations.resize(sample_count);
775 if (sample_size_present)
776 sample_sizes.resize(sample_count);
777 if (sample_flags_present)
778 sample_flags.resize(sample_count);
779 if (sample_composition_time_offsets_present)
780 sample_composition_time_offsets.resize(sample_count);
782 for (uint32 i = 0; i < sample_count; ++i) {
783 if (sample_duration_present)
784 RCHECK(reader->Read4(&sample_durations[i]));
785 if (sample_size_present)
786 RCHECK(reader->Read4(&sample_sizes[i]));
787 if (sample_flags_present)
788 RCHECK(reader->Read4(&sample_flags[i]));
789 if (sample_composition_time_offsets_present)
790 RCHECK(reader->Read4s(&sample_composition_time_offsets[i]));
793 if (first_sample_flags_present) {
794 if (sample_flags.size() == 0) {
795 sample_flags.push_back(first_sample_flags);
797 sample_flags[0] = first_sample_flags;
803 SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
804 SampleToGroup::~SampleToGroup() {}
805 FourCC SampleToGroup::BoxType() const { return FOURCC_SBGP; }
807 bool SampleToGroup::Parse(BoxReader* reader) {
808 RCHECK(reader->ReadFullBoxHeader() &&
809 reader->Read4(&grouping_type));
811 if (reader->version() == 1)
812 RCHECK(reader->Read4(&grouping_type_parameter));
814 if (grouping_type != FOURCC_SEIG) {
815 DLOG(WARNING) << "SampleToGroup box with grouping_type '" << grouping_type
816 << "' is not supported.";
821 RCHECK(reader->Read4(&count));
822 entries.resize(count);
823 for (uint32 i = 0; i < count; ++i) {
824 RCHECK(reader->Read4(&entries[i].sample_count) &&
825 reader->Read4(&entries[i].group_description_index));
830 CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
831 : is_encrypted(false), iv_size(0) {}
832 CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {}
834 SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
835 SampleGroupDescription::~SampleGroupDescription() {}
836 FourCC SampleGroupDescription::BoxType() const { return FOURCC_SGPD; }
838 bool SampleGroupDescription::Parse(BoxReader* reader) {
839 RCHECK(reader->ReadFullBoxHeader() &&
840 reader->Read4(&grouping_type));
842 if (grouping_type != FOURCC_SEIG) {
843 DLOG(WARNING) << "SampleGroupDescription box with grouping_type '"
844 << grouping_type << "' is not supported.";
848 const uint8 version = reader->version();
850 const size_t kKeyIdSize = 16;
851 const size_t kEntrySize = sizeof(uint32) + kKeyIdSize;
852 uint32 default_length = 0;
854 RCHECK(reader->Read4(&default_length));
855 RCHECK(default_length == 0 || default_length >= kEntrySize);
859 RCHECK(reader->Read4(&count));
860 entries.resize(count);
861 for (uint32 i = 0; i < count; ++i) {
863 if (default_length == 0) {
864 uint32 description_length = 0;
865 RCHECK(reader->Read4(&description_length));
866 RCHECK(description_length >= kEntrySize);
871 RCHECK(reader->SkipBytes(2) && // reserved.
872 reader->Read1(&flag) &&
873 reader->Read1(&entries[i].iv_size) &&
874 reader->ReadVec(&entries[i].key_id, kKeyIdSize));
876 entries[i].is_encrypted = (flag != 0);
877 if (entries[i].is_encrypted) {
878 RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
880 RCHECK(entries[i].iv_size == 0);
886 TrackFragment::TrackFragment() {}
887 TrackFragment::~TrackFragment() {}
888 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
890 bool TrackFragment::Parse(BoxReader* reader) {
891 RCHECK(reader->ScanChildren() &&
892 reader->ReadChild(&header) &&
893 // Media Source specific: 'tfdt' required
894 reader->ReadChild(&decode_time) &&
895 reader->MaybeReadChildren(&runs) &&
896 reader->MaybeReadChild(&auxiliary_offset) &&
897 reader->MaybeReadChild(&auxiliary_size) &&
898 reader->MaybeReadChild(&sdtp));
900 // There could be multiple SampleGroupDescription and SampleToGroup boxes with
901 // different grouping types. For common encryption, the relevant grouping type
902 // is 'seig'. Continue reading until 'seig' is found, or until running out of
904 while (sample_group_description.grouping_type != FOURCC_SEIG &&
905 reader->HasChild(&sample_group_description)) {
906 RCHECK(reader->ReadChild(&sample_group_description));
908 while (sample_to_group.grouping_type != FOURCC_SEIG &&
909 reader->HasChild(&sample_to_group)) {
910 RCHECK(reader->ReadChild(&sample_to_group));
915 MovieFragment::MovieFragment() {}
916 MovieFragment::~MovieFragment() {}
917 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
919 bool MovieFragment::Parse(BoxReader* reader) {
920 RCHECK(reader->ScanChildren() &&
921 reader->ReadChild(&header) &&
922 reader->ReadChildren(&tracks) &&
923 reader->MaybeReadChildren(&pssh));
927 IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
928 IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
929 FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; }
931 bool IndependentAndDisposableSamples::Parse(BoxReader* reader) {
932 RCHECK(reader->ReadFullBoxHeader());
933 RCHECK(reader->version() == 0);
934 RCHECK(reader->flags() == 0);
936 int sample_count = reader->size() - reader->pos();
937 sample_depends_on_.resize(sample_count);
938 for (int i = 0; i < sample_count; ++i) {
940 RCHECK(reader->Read1(&sample_info));
942 sample_depends_on_[i] =
943 static_cast<SampleDependsOn>((sample_info >> 4) & 0x3);
945 RCHECK(sample_depends_on_[i] != kSampleDependsOnReserved);
951 SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
953 if (i >= sample_depends_on_.size())
954 return kSampleDependsOnUnknown;
956 return sample_depends_on_[i];