Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / formats / mp4 / box_definitions.cc
blob1d758a9e33ab09612620f148e48910ae5e64e8e3
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"
11 namespace media {
12 namespace mp4 {
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 // Don't bother validating the box's contents.
30 // Copy the entire box, including the header, for passing to EME as initData.
31 DCHECK(raw_box.empty());
32 raw_box.assign(reader->data(), reader->data() + reader->size());
33 return true;
36 FullProtectionSystemSpecificHeader::FullProtectionSystemSpecificHeader() {}
37 FullProtectionSystemSpecificHeader::~FullProtectionSystemSpecificHeader() {}
38 FourCC FullProtectionSystemSpecificHeader::BoxType() const {
39 return FOURCC_PSSH;
42 // The format of a 'pssh' box is as follows:
43 // unsigned int(32) size;
44 // unsigned int(32) type = "pssh";
45 // if (size==1) {
46 // unsigned int(64) largesize;
47 // } else if (size==0) {
48 // -- box extends to end of file
49 // }
50 // unsigned int(8) version;
51 // bit(24) flags;
52 // unsigned int(8)[16] SystemID;
53 // if (version > 0)
54 // {
55 // unsigned int(32) KID_count;
56 // {
57 // unsigned int(8)[16] KID;
58 // } [KID_count]
59 // }
60 // unsigned int(32) DataSize;
61 // unsigned int(8)[DataSize] Data;
63 bool FullProtectionSystemSpecificHeader::Parse(mp4::BoxReader* reader) {
64 RCHECK(reader->type() == BoxType() && reader->ReadFullBoxHeader());
66 // Only versions 0 and 1 of the 'pssh' boxes are supported. Any other
67 // versions are ignored.
68 RCHECK(reader->version() == 0 || reader->version() == 1);
69 RCHECK(reader->flags() == 0);
70 RCHECK(reader->ReadVec(&system_id, 16));
72 if (reader->version() > 0) {
73 uint32_t kid_count;
74 RCHECK(reader->Read4(&kid_count));
75 for (uint32_t i = 0; i < kid_count; ++i) {
76 std::vector<uint8_t> kid;
77 RCHECK(reader->ReadVec(&kid, 16));
78 key_ids.push_back(kid);
82 uint32_t data_size;
83 RCHECK(reader->Read4(&data_size));
84 RCHECK(reader->ReadVec(&data, data_size));
85 return true;
88 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
89 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
90 FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; }
92 bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) {
93 RCHECK(reader->ReadFullBoxHeader());
94 if (reader->flags() & 1)
95 RCHECK(reader->SkipBytes(8));
97 uint32 count;
98 RCHECK(reader->Read4(&count) &&
99 reader->HasBytes(count * (reader->version() == 1 ? 8 : 4)));
100 offsets.resize(count);
102 for (uint32 i = 0; i < count; i++) {
103 if (reader->version() == 1) {
104 RCHECK(reader->Read8(&offsets[i]));
105 } else {
106 RCHECK(reader->Read4Into8(&offsets[i]));
109 return true;
112 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
113 : default_sample_info_size(0), sample_count(0) {
115 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
116 FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; }
118 bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) {
119 RCHECK(reader->ReadFullBoxHeader());
120 if (reader->flags() & 1)
121 RCHECK(reader->SkipBytes(8));
123 RCHECK(reader->Read1(&default_sample_info_size) &&
124 reader->Read4(&sample_count));
125 if (default_sample_info_size == 0)
126 return reader->ReadVec(&sample_info_sizes, sample_count);
127 return true;
130 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
131 OriginalFormat::~OriginalFormat() {}
132 FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; }
134 bool OriginalFormat::Parse(BoxReader* reader) {
135 return reader->ReadFourCC(&format);
138 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
139 SchemeType::~SchemeType() {}
140 FourCC SchemeType::BoxType() const { return FOURCC_SCHM; }
142 bool SchemeType::Parse(BoxReader* reader) {
143 RCHECK(reader->ReadFullBoxHeader() &&
144 reader->ReadFourCC(&type) &&
145 reader->Read4(&version));
146 return true;
149 TrackEncryption::TrackEncryption()
150 : is_encrypted(false), default_iv_size(0) {
152 TrackEncryption::~TrackEncryption() {}
153 FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; }
155 bool TrackEncryption::Parse(BoxReader* reader) {
156 uint8 flag;
157 RCHECK(reader->ReadFullBoxHeader() &&
158 reader->SkipBytes(2) &&
159 reader->Read1(&flag) &&
160 reader->Read1(&default_iv_size) &&
161 reader->ReadVec(&default_kid, 16));
162 is_encrypted = (flag != 0);
163 if (is_encrypted) {
164 RCHECK(default_iv_size == 8 || default_iv_size == 16);
165 } else {
166 RCHECK(default_iv_size == 0);
168 return true;
171 SchemeInfo::SchemeInfo() {}
172 SchemeInfo::~SchemeInfo() {}
173 FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; }
175 bool SchemeInfo::Parse(BoxReader* reader) {
176 return reader->ScanChildren() && reader->ReadChild(&track_encryption);
179 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
180 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
181 FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; }
183 bool ProtectionSchemeInfo::Parse(BoxReader* reader) {
184 RCHECK(reader->ScanChildren() &&
185 reader->ReadChild(&format) &&
186 reader->ReadChild(&type));
187 if (type.type == FOURCC_CENC)
188 RCHECK(reader->ReadChild(&info));
189 // Other protection schemes are silently ignored. Since the protection scheme
190 // type can't be determined until this box is opened, we return 'true' for
191 // non-CENC protection scheme types. It is the parent box's responsibility to
192 // ensure that this scheme type is a supported one.
193 return true;
196 MovieHeader::MovieHeader()
197 : creation_time(0),
198 modification_time(0),
199 timescale(0),
200 duration(0),
201 rate(-1),
202 volume(-1),
203 next_track_id(0) {}
204 MovieHeader::~MovieHeader() {}
205 FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; }
207 bool MovieHeader::Parse(BoxReader* reader) {
208 RCHECK(reader->ReadFullBoxHeader());
210 if (reader->version() == 1) {
211 RCHECK(reader->Read8(&creation_time) &&
212 reader->Read8(&modification_time) &&
213 reader->Read4(&timescale) &&
214 reader->Read8(&duration));
215 } else {
216 RCHECK(reader->Read4Into8(&creation_time) &&
217 reader->Read4Into8(&modification_time) &&
218 reader->Read4(&timescale) &&
219 reader->Read4Into8(&duration));
222 RCHECK(reader->Read4s(&rate) &&
223 reader->Read2s(&volume) &&
224 reader->SkipBytes(10) && // reserved
225 reader->SkipBytes(36) && // matrix
226 reader->SkipBytes(24) && // predefined zero
227 reader->Read4(&next_track_id));
228 return true;
231 TrackHeader::TrackHeader()
232 : creation_time(0),
233 modification_time(0),
234 track_id(0),
235 duration(0),
236 layer(-1),
237 alternate_group(-1),
238 volume(-1),
239 width(0),
240 height(0) {}
241 TrackHeader::~TrackHeader() {}
242 FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; }
244 bool TrackHeader::Parse(BoxReader* reader) {
245 RCHECK(reader->ReadFullBoxHeader());
246 if (reader->version() == 1) {
247 RCHECK(reader->Read8(&creation_time) &&
248 reader->Read8(&modification_time) &&
249 reader->Read4(&track_id) &&
250 reader->SkipBytes(4) && // reserved
251 reader->Read8(&duration));
252 } else {
253 RCHECK(reader->Read4Into8(&creation_time) &&
254 reader->Read4Into8(&modification_time) &&
255 reader->Read4(&track_id) &&
256 reader->SkipBytes(4) && // reserved
257 reader->Read4Into8(&duration));
260 RCHECK(reader->SkipBytes(8) && // reserved
261 reader->Read2s(&layer) &&
262 reader->Read2s(&alternate_group) &&
263 reader->Read2s(&volume) &&
264 reader->SkipBytes(2) && // reserved
265 reader->SkipBytes(36) && // matrix
266 reader->Read4(&width) &&
267 reader->Read4(&height));
268 width >>= 16;
269 height >>= 16;
270 return true;
273 SampleDescription::SampleDescription() : type(kInvalid) {}
274 SampleDescription::~SampleDescription() {}
275 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
277 bool SampleDescription::Parse(BoxReader* reader) {
278 uint32 count;
279 RCHECK(reader->SkipBytes(4) &&
280 reader->Read4(&count));
281 video_entries.clear();
282 audio_entries.clear();
284 // Note: this value is preset before scanning begins. See comments in the
285 // Parse(Media*) function.
286 if (type == kVideo) {
287 RCHECK(reader->ReadAllChildren(&video_entries));
288 } else if (type == kAudio) {
289 RCHECK(reader->ReadAllChildren(&audio_entries));
291 return true;
294 SyncSample::SyncSample() : is_present(false) {}
295 SyncSample::~SyncSample() {}
296 FourCC SyncSample::BoxType() const { return FOURCC_STSS; }
298 bool SyncSample::Parse(BoxReader* reader) {
299 uint32 entry_count;
300 RCHECK(reader->ReadFullBoxHeader() &&
301 reader->Read4(&entry_count));
303 is_present = true;
305 entries.resize(entry_count);
307 if (entry_count == 0)
308 return true;
310 for (size_t i = 0; i < entry_count; ++i)
311 RCHECK(reader->Read4(&entries[i]));
313 return true;
316 bool SyncSample::IsSyncSample(size_t k) const {
317 // ISO/IEC 14496-12 Section 8.6.2.1 : If the sync sample box is not present,
318 // every sample is a sync sample.
319 if (!is_present)
320 return true;
322 // ISO/IEC 14496-12 Section 8.6.2.3 : If entry_count is zero, there are no
323 // sync samples within the stream.
324 if (entries.size() == 0u)
325 return false;
327 for (size_t i = 0; i < entries.size(); ++i) {
328 if (entries[i] == k)
329 return true;
332 return false;
335 SampleTable::SampleTable() {}
336 SampleTable::~SampleTable() {}
337 FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
339 bool SampleTable::Parse(BoxReader* reader) {
340 RCHECK(reader->ScanChildren() &&
341 reader->ReadChild(&description) &&
342 reader->MaybeReadChild(&sync_sample));
343 // There could be multiple SampleGroupDescription boxes with different
344 // grouping types. For common encryption, the relevant grouping type is
345 // 'seig'. Continue reading until 'seig' is found, or until running out of
346 // child boxes.
347 while (reader->HasChild(&sample_group_description)) {
348 RCHECK(reader->ReadChild(&sample_group_description));
349 if (sample_group_description.grouping_type == FOURCC_SEIG)
350 break;
351 sample_group_description.entries.clear();
353 return true;
356 EditList::EditList() {}
357 EditList::~EditList() {}
358 FourCC EditList::BoxType() const { return FOURCC_ELST; }
360 bool EditList::Parse(BoxReader* reader) {
361 uint32 count;
362 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count));
364 if (reader->version() == 1) {
365 RCHECK(reader->HasBytes(count * 20));
366 } else {
367 RCHECK(reader->HasBytes(count * 12));
369 edits.resize(count);
371 for (std::vector<EditListEntry>::iterator edit = edits.begin();
372 edit != edits.end(); ++edit) {
373 if (reader->version() == 1) {
374 RCHECK(reader->Read8(&edit->segment_duration) &&
375 reader->Read8s(&edit->media_time));
376 } else {
377 RCHECK(reader->Read4Into8(&edit->segment_duration) &&
378 reader->Read4sInto8s(&edit->media_time));
380 RCHECK(reader->Read2s(&edit->media_rate_integer) &&
381 reader->Read2s(&edit->media_rate_fraction));
383 return true;
386 Edit::Edit() {}
387 Edit::~Edit() {}
388 FourCC Edit::BoxType() const { return FOURCC_EDTS; }
390 bool Edit::Parse(BoxReader* reader) {
391 return reader->ScanChildren() && reader->ReadChild(&list);
394 HandlerReference::HandlerReference() : type(kInvalid) {}
395 HandlerReference::~HandlerReference() {}
396 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
398 bool HandlerReference::Parse(BoxReader* reader) {
399 FourCC hdlr_type;
400 RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type));
401 // Note: remaining fields in box ignored
402 if (hdlr_type == FOURCC_VIDE) {
403 type = kVideo;
404 } else if (hdlr_type == FOURCC_SOUN) {
405 type = kAudio;
406 } else {
407 type = kInvalid;
409 return true;
412 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
413 : version(0),
414 profile_indication(0),
415 profile_compatibility(0),
416 avc_level(0),
417 length_size(0) {}
419 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
420 FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
422 bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
423 return ParseInternal(reader, reader->media_log());
426 bool AVCDecoderConfigurationRecord::Parse(const uint8* data, int data_size) {
427 BufferReader reader(data, data_size);
428 return ParseInternal(&reader, new MediaLog());
431 bool AVCDecoderConfigurationRecord::ParseInternal(
432 BufferReader* reader,
433 const scoped_refptr<MediaLog>& media_log) {
434 RCHECK(reader->Read1(&version) && version == 1 &&
435 reader->Read1(&profile_indication) &&
436 reader->Read1(&profile_compatibility) &&
437 reader->Read1(&avc_level));
439 uint8 length_size_minus_one;
440 RCHECK(reader->Read1(&length_size_minus_one));
441 length_size = (length_size_minus_one & 0x3) + 1;
443 RCHECK(length_size != 3); // Only values of 1, 2, and 4 are valid.
445 uint8 num_sps;
446 RCHECK(reader->Read1(&num_sps));
447 num_sps &= 0x1f;
449 sps_list.resize(num_sps);
450 for (int i = 0; i < num_sps; i++) {
451 uint16 sps_length;
452 RCHECK(reader->Read2(&sps_length) &&
453 reader->ReadVec(&sps_list[i], sps_length));
454 RCHECK(sps_list[i].size() > 4);
456 if (media_log.get()) {
457 MEDIA_LOG(INFO, media_log) << "Video codec: avc1." << std::hex
458 << static_cast<int>(sps_list[i][1])
459 << static_cast<int>(sps_list[i][2])
460 << static_cast<int>(sps_list[i][3]);
464 uint8 num_pps;
465 RCHECK(reader->Read1(&num_pps));
467 pps_list.resize(num_pps);
468 for (int i = 0; i < num_pps; i++) {
469 uint16 pps_length;
470 RCHECK(reader->Read2(&pps_length) &&
471 reader->ReadVec(&pps_list[i], pps_length));
474 return true;
477 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
478 PixelAspectRatioBox::~PixelAspectRatioBox() {}
479 FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
481 bool PixelAspectRatioBox::Parse(BoxReader* reader) {
482 RCHECK(reader->Read4(&h_spacing) &&
483 reader->Read4(&v_spacing));
484 return true;
487 VideoSampleEntry::VideoSampleEntry()
488 : format(FOURCC_NULL),
489 data_reference_index(0),
490 width(0),
491 height(0) {}
493 VideoSampleEntry::~VideoSampleEntry() {}
494 FourCC VideoSampleEntry::BoxType() const {
495 DCHECK(false) << "VideoSampleEntry should be parsed according to the "
496 << "handler type recovered in its Media ancestor.";
497 return FOURCC_NULL;
500 bool VideoSampleEntry::Parse(BoxReader* reader) {
501 format = reader->type();
502 RCHECK(reader->SkipBytes(6) &&
503 reader->Read2(&data_reference_index) &&
504 reader->SkipBytes(16) &&
505 reader->Read2(&width) &&
506 reader->Read2(&height) &&
507 reader->SkipBytes(50));
509 RCHECK(reader->ScanChildren() &&
510 reader->MaybeReadChild(&pixel_aspect));
512 if (format == FOURCC_ENCV) {
513 // Continue scanning until a recognized protection scheme is found, or until
514 // we run out of protection schemes.
515 while (sinf.type.type != FOURCC_CENC) {
516 if (!reader->ReadChild(&sinf))
517 return false;
521 if (IsFormatValid())
522 RCHECK(reader->ReadChild(&avcc));
524 return true;
527 bool VideoSampleEntry::IsFormatValid() const {
528 return format == FOURCC_AVC1 || format == FOURCC_AVC3 ||
529 (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 ||
530 sinf.format.format == FOURCC_AVC3));
533 ElementaryStreamDescriptor::ElementaryStreamDescriptor()
534 : object_type(kForbidden) {}
536 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
538 FourCC ElementaryStreamDescriptor::BoxType() const {
539 return FOURCC_ESDS;
542 bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {
543 std::vector<uint8> data;
544 ESDescriptor es_desc;
546 RCHECK(reader->ReadFullBoxHeader());
547 RCHECK(reader->ReadVec(&data, reader->size() - reader->pos()));
548 RCHECK(es_desc.Parse(data));
550 object_type = es_desc.object_type();
552 if (object_type != 0x40) {
553 MEDIA_LOG(INFO, reader->media_log()) << "Audio codec: mp4a." << std::hex
554 << static_cast<int>(object_type);
557 if (es_desc.IsAAC(object_type))
558 RCHECK(aac.Parse(es_desc.decoder_specific_info(), reader->media_log()));
560 return true;
563 AudioSampleEntry::AudioSampleEntry()
564 : format(FOURCC_NULL),
565 data_reference_index(0),
566 channelcount(0),
567 samplesize(0),
568 samplerate(0) {}
570 AudioSampleEntry::~AudioSampleEntry() {}
572 FourCC AudioSampleEntry::BoxType() const {
573 DCHECK(false) << "AudioSampleEntry should be parsed according to the "
574 << "handler type recovered in its Media ancestor.";
575 return FOURCC_NULL;
578 bool AudioSampleEntry::Parse(BoxReader* reader) {
579 format = reader->type();
580 RCHECK(reader->SkipBytes(6) &&
581 reader->Read2(&data_reference_index) &&
582 reader->SkipBytes(8) &&
583 reader->Read2(&channelcount) &&
584 reader->Read2(&samplesize) &&
585 reader->SkipBytes(4) &&
586 reader->Read4(&samplerate));
587 // Convert from 16.16 fixed point to integer
588 samplerate >>= 16;
590 RCHECK(reader->ScanChildren());
591 if (format == FOURCC_ENCA) {
592 // Continue scanning until a recognized protection scheme is found, or until
593 // we run out of protection schemes.
594 while (sinf.type.type != FOURCC_CENC) {
595 if (!reader->ReadChild(&sinf))
596 return false;
600 // ESDS is not valid in case of EAC3.
601 RCHECK(reader->MaybeReadChild(&esds));
602 return true;
605 MediaHeader::MediaHeader()
606 : creation_time(0),
607 modification_time(0),
608 timescale(0),
609 duration(0) {}
610 MediaHeader::~MediaHeader() {}
611 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
613 bool MediaHeader::Parse(BoxReader* reader) {
614 RCHECK(reader->ReadFullBoxHeader());
616 if (reader->version() == 1) {
617 RCHECK(reader->Read8(&creation_time) &&
618 reader->Read8(&modification_time) &&
619 reader->Read4(&timescale) &&
620 reader->Read8(&duration));
621 } else {
622 RCHECK(reader->Read4Into8(&creation_time) &&
623 reader->Read4Into8(&modification_time) &&
624 reader->Read4(&timescale) &&
625 reader->Read4Into8(&duration));
627 // Skip language information
628 return reader->SkipBytes(4);
631 MediaInformation::MediaInformation() {}
632 MediaInformation::~MediaInformation() {}
633 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
635 bool MediaInformation::Parse(BoxReader* reader) {
636 return reader->ScanChildren() &&
637 reader->ReadChild(&sample_table);
640 Media::Media() {}
641 Media::~Media() {}
642 FourCC Media::BoxType() const { return FOURCC_MDIA; }
644 bool Media::Parse(BoxReader* reader) {
645 RCHECK(reader->ScanChildren() &&
646 reader->ReadChild(&header) &&
647 reader->ReadChild(&handler));
649 // Maddeningly, the HandlerReference box specifies how to parse the
650 // SampleDescription box, making the latter the only box (of those that we
651 // support) which cannot be parsed correctly on its own (or even with
652 // information from its strict ancestor tree). We thus copy the handler type
653 // to the sample description box *before* parsing it to provide this
654 // information while parsing.
655 information.sample_table.description.type = handler.type;
656 RCHECK(reader->ReadChild(&information));
657 return true;
660 Track::Track() {}
661 Track::~Track() {}
662 FourCC Track::BoxType() const { return FOURCC_TRAK; }
664 bool Track::Parse(BoxReader* reader) {
665 RCHECK(reader->ScanChildren() &&
666 reader->ReadChild(&header) &&
667 reader->ReadChild(&media) &&
668 reader->MaybeReadChild(&edit));
669 return true;
672 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
673 MovieExtendsHeader::~MovieExtendsHeader() {}
674 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
676 bool MovieExtendsHeader::Parse(BoxReader* reader) {
677 RCHECK(reader->ReadFullBoxHeader());
678 if (reader->version() == 1) {
679 RCHECK(reader->Read8(&fragment_duration));
680 } else {
681 RCHECK(reader->Read4Into8(&fragment_duration));
683 return true;
686 TrackExtends::TrackExtends()
687 : track_id(0),
688 default_sample_description_index(0),
689 default_sample_duration(0),
690 default_sample_size(0),
691 default_sample_flags(0) {}
692 TrackExtends::~TrackExtends() {}
693 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
695 bool TrackExtends::Parse(BoxReader* reader) {
696 RCHECK(reader->ReadFullBoxHeader() &&
697 reader->Read4(&track_id) &&
698 reader->Read4(&default_sample_description_index) &&
699 reader->Read4(&default_sample_duration) &&
700 reader->Read4(&default_sample_size) &&
701 reader->Read4(&default_sample_flags));
702 return true;
705 MovieExtends::MovieExtends() {}
706 MovieExtends::~MovieExtends() {}
707 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
709 bool MovieExtends::Parse(BoxReader* reader) {
710 header.fragment_duration = 0;
711 return reader->ScanChildren() &&
712 reader->MaybeReadChild(&header) &&
713 reader->ReadChildren(&tracks);
716 Movie::Movie() : fragmented(false) {}
717 Movie::~Movie() {}
718 FourCC Movie::BoxType() const { return FOURCC_MOOV; }
720 bool Movie::Parse(BoxReader* reader) {
721 RCHECK(reader->ScanChildren() && reader->ReadChild(&header) &&
722 reader->ReadChildren(&tracks));
724 RCHECK_MEDIA_LOGGED(reader->ReadChild(&extends), reader->media_log(),
725 "Detected unfragmented MP4. Media Source Extensions "
726 "require ISO BMFF moov to contain mvex to indicate that "
727 "Movie Fragments are to be expected.");
729 return reader->MaybeReadChildren(&pssh);
732 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
733 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
734 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
736 bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {
737 RCHECK(reader->ReadFullBoxHeader());
738 if (reader->version() == 1)
739 return reader->Read8(&decode_time);
740 else
741 return reader->Read4Into8(&decode_time);
744 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
745 MovieFragmentHeader::~MovieFragmentHeader() {}
746 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
748 bool MovieFragmentHeader::Parse(BoxReader* reader) {
749 return reader->SkipBytes(4) && reader->Read4(&sequence_number);
752 TrackFragmentHeader::TrackFragmentHeader()
753 : track_id(0),
754 sample_description_index(0),
755 default_sample_duration(0),
756 default_sample_size(0),
757 default_sample_flags(0),
758 has_default_sample_flags(false) {}
760 TrackFragmentHeader::~TrackFragmentHeader() {}
761 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
763 bool TrackFragmentHeader::Parse(BoxReader* reader) {
764 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id));
766 // Media Source specific: reject tracks that set 'base-data-offset-present'.
767 // Although the Media Source requires that 'default-base-is-moof' (14496-12
768 // Amendment 2) be set, we omit this check as many otherwise-valid files in
769 // the wild don't set it.
771 // RCHECK((flags & 0x020000) && !(flags & 0x1));
772 RCHECK(!(reader->flags() & 0x1));
774 if (reader->flags() & 0x2) {
775 RCHECK(reader->Read4(&sample_description_index));
776 } else {
777 sample_description_index = 0;
780 if (reader->flags() & 0x8) {
781 RCHECK(reader->Read4(&default_sample_duration));
782 } else {
783 default_sample_duration = 0;
786 if (reader->flags() & 0x10) {
787 RCHECK(reader->Read4(&default_sample_size));
788 } else {
789 default_sample_size = 0;
792 if (reader->flags() & 0x20) {
793 RCHECK(reader->Read4(&default_sample_flags));
794 has_default_sample_flags = true;
795 } else {
796 has_default_sample_flags = false;
799 return true;
802 TrackFragmentRun::TrackFragmentRun()
803 : sample_count(0), data_offset(0) {}
804 TrackFragmentRun::~TrackFragmentRun() {}
805 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
807 bool TrackFragmentRun::Parse(BoxReader* reader) {
808 RCHECK(reader->ReadFullBoxHeader() &&
809 reader->Read4(&sample_count));
810 const uint32 flags = reader->flags();
812 bool data_offset_present = (flags & 0x1) != 0;
813 bool first_sample_flags_present = (flags & 0x4) != 0;
814 bool sample_duration_present = (flags & 0x100) != 0;
815 bool sample_size_present = (flags & 0x200) != 0;
816 bool sample_flags_present = (flags & 0x400) != 0;
817 bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
819 if (data_offset_present) {
820 RCHECK(reader->Read4(&data_offset));
821 } else {
822 data_offset = 0;
825 uint32 first_sample_flags = 0;
826 if (first_sample_flags_present)
827 RCHECK(reader->Read4(&first_sample_flags));
829 int fields = sample_duration_present + sample_size_present +
830 sample_flags_present + sample_composition_time_offsets_present;
831 RCHECK(reader->HasBytes(fields * sample_count));
833 if (sample_duration_present)
834 sample_durations.resize(sample_count);
835 if (sample_size_present)
836 sample_sizes.resize(sample_count);
837 if (sample_flags_present)
838 sample_flags.resize(sample_count);
839 if (sample_composition_time_offsets_present)
840 sample_composition_time_offsets.resize(sample_count);
842 for (uint32 i = 0; i < sample_count; ++i) {
843 if (sample_duration_present)
844 RCHECK(reader->Read4(&sample_durations[i]));
845 if (sample_size_present)
846 RCHECK(reader->Read4(&sample_sizes[i]));
847 if (sample_flags_present)
848 RCHECK(reader->Read4(&sample_flags[i]));
849 if (sample_composition_time_offsets_present)
850 RCHECK(reader->Read4s(&sample_composition_time_offsets[i]));
853 if (first_sample_flags_present) {
854 if (sample_flags.size() == 0) {
855 sample_flags.push_back(first_sample_flags);
856 } else {
857 sample_flags[0] = first_sample_flags;
860 return true;
863 SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
864 SampleToGroup::~SampleToGroup() {}
865 FourCC SampleToGroup::BoxType() const { return FOURCC_SBGP; }
867 bool SampleToGroup::Parse(BoxReader* reader) {
868 RCHECK(reader->ReadFullBoxHeader() &&
869 reader->Read4(&grouping_type));
871 if (reader->version() == 1)
872 RCHECK(reader->Read4(&grouping_type_parameter));
874 if (grouping_type != FOURCC_SEIG) {
875 DLOG(WARNING) << "SampleToGroup box with grouping_type '" << grouping_type
876 << "' is not supported.";
877 return true;
880 uint32 count;
881 RCHECK(reader->Read4(&count));
882 entries.resize(count);
883 for (uint32 i = 0; i < count; ++i) {
884 RCHECK(reader->Read4(&entries[i].sample_count) &&
885 reader->Read4(&entries[i].group_description_index));
887 return true;
890 CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
891 : is_encrypted(false), iv_size(0) {}
892 CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {}
894 SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
895 SampleGroupDescription::~SampleGroupDescription() {}
896 FourCC SampleGroupDescription::BoxType() const { return FOURCC_SGPD; }
898 bool SampleGroupDescription::Parse(BoxReader* reader) {
899 RCHECK(reader->ReadFullBoxHeader() &&
900 reader->Read4(&grouping_type));
902 if (grouping_type != FOURCC_SEIG) {
903 DLOG(WARNING) << "SampleGroupDescription box with grouping_type '"
904 << grouping_type << "' is not supported.";
905 return true;
908 const uint8 version = reader->version();
910 const size_t kKeyIdSize = 16;
911 const size_t kEntrySize = sizeof(uint32) + kKeyIdSize;
912 uint32 default_length = 0;
913 if (version == 1) {
914 RCHECK(reader->Read4(&default_length));
915 RCHECK(default_length == 0 || default_length >= kEntrySize);
918 uint32 count;
919 RCHECK(reader->Read4(&count));
920 entries.resize(count);
921 for (uint32 i = 0; i < count; ++i) {
922 if (version == 1) {
923 if (default_length == 0) {
924 uint32 description_length = 0;
925 RCHECK(reader->Read4(&description_length));
926 RCHECK(description_length >= kEntrySize);
930 uint8 flag;
931 RCHECK(reader->SkipBytes(2) && // reserved.
932 reader->Read1(&flag) &&
933 reader->Read1(&entries[i].iv_size) &&
934 reader->ReadVec(&entries[i].key_id, kKeyIdSize));
936 entries[i].is_encrypted = (flag != 0);
937 if (entries[i].is_encrypted) {
938 RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
939 } else {
940 RCHECK(entries[i].iv_size == 0);
943 return true;
946 TrackFragment::TrackFragment() {}
947 TrackFragment::~TrackFragment() {}
948 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
950 bool TrackFragment::Parse(BoxReader* reader) {
951 RCHECK(reader->ScanChildren() &&
952 reader->ReadChild(&header) &&
953 // Media Source specific: 'tfdt' required
954 reader->ReadChild(&decode_time) &&
955 reader->MaybeReadChildren(&runs) &&
956 reader->MaybeReadChild(&auxiliary_offset) &&
957 reader->MaybeReadChild(&auxiliary_size) &&
958 reader->MaybeReadChild(&sdtp));
960 // There could be multiple SampleGroupDescription and SampleToGroup boxes with
961 // different grouping types. For common encryption, the relevant grouping type
962 // is 'seig'. Continue reading until 'seig' is found, or until running out of
963 // child boxes.
964 while (reader->HasChild(&sample_group_description)) {
965 RCHECK(reader->ReadChild(&sample_group_description));
966 if (sample_group_description.grouping_type == FOURCC_SEIG)
967 break;
968 sample_group_description.entries.clear();
970 while (reader->HasChild(&sample_to_group)) {
971 RCHECK(reader->ReadChild(&sample_to_group));
972 if (sample_to_group.grouping_type == FOURCC_SEIG)
973 break;
974 sample_to_group.entries.clear();
976 return true;
979 MovieFragment::MovieFragment() {}
980 MovieFragment::~MovieFragment() {}
981 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
983 bool MovieFragment::Parse(BoxReader* reader) {
984 RCHECK(reader->ScanChildren() &&
985 reader->ReadChild(&header) &&
986 reader->ReadChildren(&tracks) &&
987 reader->MaybeReadChildren(&pssh));
988 return true;
991 IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
992 IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
993 FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; }
995 bool IndependentAndDisposableSamples::Parse(BoxReader* reader) {
996 RCHECK(reader->ReadFullBoxHeader());
997 RCHECK(reader->version() == 0);
998 RCHECK(reader->flags() == 0);
1000 int sample_count = reader->size() - reader->pos();
1001 sample_depends_on_.resize(sample_count);
1002 for (int i = 0; i < sample_count; ++i) {
1003 uint8 sample_info;
1004 RCHECK(reader->Read1(&sample_info));
1006 sample_depends_on_[i] =
1007 static_cast<SampleDependsOn>((sample_info >> 4) & 0x3);
1009 RCHECK(sample_depends_on_[i] != kSampleDependsOnReserved);
1012 return true;
1015 SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
1016 size_t i) const {
1017 if (i >= sample_depends_on_.size())
1018 return kSampleDependsOnUnknown;
1020 return sample_depends_on_[i];
1023 } // namespace mp4
1024 } // namespace media