Roll ANGLE e754fb8..6ffeb74
[chromium-blink-merge.git] / media / formats / mp4 / box_definitions.cc
blob5a15240ebbc0f8b860fa55dba16daaa63d9fe68d
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 // Validate the box's contents and hang on to the system ID.
30 RCHECK(reader->ReadFullBoxHeader() &&
31 reader->ReadVec(&system_id, 16));
33 // Copy the entire box, including the header, for passing to EME as initData.
34 DCHECK(raw_box.empty());
35 raw_box.assign(reader->data(), reader->data() + reader->size());
36 return true;
39 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
40 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
41 FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; }
43 bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) {
44 RCHECK(reader->ReadFullBoxHeader());
45 if (reader->flags() & 1)
46 RCHECK(reader->SkipBytes(8));
48 uint32 count;
49 RCHECK(reader->Read4(&count) &&
50 reader->HasBytes(count * (reader->version() == 1 ? 8 : 4)));
51 offsets.resize(count);
53 for (uint32 i = 0; i < count; i++) {
54 if (reader->version() == 1) {
55 RCHECK(reader->Read8(&offsets[i]));
56 } else {
57 RCHECK(reader->Read4Into8(&offsets[i]));
60 return true;
63 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
64 : default_sample_info_size(0), sample_count(0) {
66 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
67 FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; }
69 bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) {
70 RCHECK(reader->ReadFullBoxHeader());
71 if (reader->flags() & 1)
72 RCHECK(reader->SkipBytes(8));
74 RCHECK(reader->Read1(&default_sample_info_size) &&
75 reader->Read4(&sample_count));
76 if (default_sample_info_size == 0)
77 return reader->ReadVec(&sample_info_sizes, sample_count);
78 return true;
81 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
82 OriginalFormat::~OriginalFormat() {}
83 FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; }
85 bool OriginalFormat::Parse(BoxReader* reader) {
86 return reader->ReadFourCC(&format);
89 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
90 SchemeType::~SchemeType() {}
91 FourCC SchemeType::BoxType() const { return FOURCC_SCHM; }
93 bool SchemeType::Parse(BoxReader* reader) {
94 RCHECK(reader->ReadFullBoxHeader() &&
95 reader->ReadFourCC(&type) &&
96 reader->Read4(&version));
97 return true;
100 TrackEncryption::TrackEncryption()
101 : is_encrypted(false), default_iv_size(0) {
103 TrackEncryption::~TrackEncryption() {}
104 FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; }
106 bool TrackEncryption::Parse(BoxReader* reader) {
107 uint8 flag;
108 RCHECK(reader->ReadFullBoxHeader() &&
109 reader->SkipBytes(2) &&
110 reader->Read1(&flag) &&
111 reader->Read1(&default_iv_size) &&
112 reader->ReadVec(&default_kid, 16));
113 is_encrypted = (flag != 0);
114 if (is_encrypted) {
115 RCHECK(default_iv_size == 8 || default_iv_size == 16);
116 } else {
117 RCHECK(default_iv_size == 0);
119 return true;
122 SchemeInfo::SchemeInfo() {}
123 SchemeInfo::~SchemeInfo() {}
124 FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; }
126 bool SchemeInfo::Parse(BoxReader* reader) {
127 return reader->ScanChildren() && reader->ReadChild(&track_encryption);
130 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
131 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
132 FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; }
134 bool ProtectionSchemeInfo::Parse(BoxReader* reader) {
135 RCHECK(reader->ScanChildren() &&
136 reader->ReadChild(&format) &&
137 reader->ReadChild(&type));
138 if (type.type == FOURCC_CENC)
139 RCHECK(reader->ReadChild(&info));
140 // Other protection schemes are silently ignored. Since the protection scheme
141 // type can't be determined until this box is opened, we return 'true' for
142 // non-CENC protection scheme types. It is the parent box's responsibility to
143 // ensure that this scheme type is a supported one.
144 return true;
147 MovieHeader::MovieHeader()
148 : creation_time(0),
149 modification_time(0),
150 timescale(0),
151 duration(0),
152 rate(-1),
153 volume(-1),
154 next_track_id(0) {}
155 MovieHeader::~MovieHeader() {}
156 FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; }
158 bool MovieHeader::Parse(BoxReader* reader) {
159 RCHECK(reader->ReadFullBoxHeader());
161 if (reader->version() == 1) {
162 RCHECK(reader->Read8(&creation_time) &&
163 reader->Read8(&modification_time) &&
164 reader->Read4(&timescale) &&
165 reader->Read8(&duration));
166 } else {
167 RCHECK(reader->Read4Into8(&creation_time) &&
168 reader->Read4Into8(&modification_time) &&
169 reader->Read4(&timescale) &&
170 reader->Read4Into8(&duration));
173 RCHECK(reader->Read4s(&rate) &&
174 reader->Read2s(&volume) &&
175 reader->SkipBytes(10) && // reserved
176 reader->SkipBytes(36) && // matrix
177 reader->SkipBytes(24) && // predefined zero
178 reader->Read4(&next_track_id));
179 return true;
182 TrackHeader::TrackHeader()
183 : creation_time(0),
184 modification_time(0),
185 track_id(0),
186 duration(0),
187 layer(-1),
188 alternate_group(-1),
189 volume(-1),
190 width(0),
191 height(0) {}
192 TrackHeader::~TrackHeader() {}
193 FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; }
195 bool TrackHeader::Parse(BoxReader* reader) {
196 RCHECK(reader->ReadFullBoxHeader());
197 if (reader->version() == 1) {
198 RCHECK(reader->Read8(&creation_time) &&
199 reader->Read8(&modification_time) &&
200 reader->Read4(&track_id) &&
201 reader->SkipBytes(4) && // reserved
202 reader->Read8(&duration));
203 } else {
204 RCHECK(reader->Read4Into8(&creation_time) &&
205 reader->Read4Into8(&modification_time) &&
206 reader->Read4(&track_id) &&
207 reader->SkipBytes(4) && // reserved
208 reader->Read4Into8(&duration));
211 RCHECK(reader->SkipBytes(8) && // reserved
212 reader->Read2s(&layer) &&
213 reader->Read2s(&alternate_group) &&
214 reader->Read2s(&volume) &&
215 reader->SkipBytes(2) && // reserved
216 reader->SkipBytes(36) && // matrix
217 reader->Read4(&width) &&
218 reader->Read4(&height));
219 width >>= 16;
220 height >>= 16;
221 return true;
224 SampleDescription::SampleDescription() : type(kInvalid) {}
225 SampleDescription::~SampleDescription() {}
226 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
228 bool SampleDescription::Parse(BoxReader* reader) {
229 uint32 count;
230 RCHECK(reader->SkipBytes(4) &&
231 reader->Read4(&count));
232 video_entries.clear();
233 audio_entries.clear();
235 // Note: this value is preset before scanning begins. See comments in the
236 // Parse(Media*) function.
237 if (type == kVideo) {
238 RCHECK(reader->ReadAllChildren(&video_entries));
239 } else if (type == kAudio) {
240 RCHECK(reader->ReadAllChildren(&audio_entries));
242 return true;
245 SyncSample::SyncSample() : is_present(false) {}
246 SyncSample::~SyncSample() {}
247 FourCC SyncSample::BoxType() const { return FOURCC_STSS; }
249 bool SyncSample::Parse(BoxReader* reader) {
250 uint32 entry_count;
251 RCHECK(reader->ReadFullBoxHeader() &&
252 reader->Read4(&entry_count));
254 is_present = true;
256 entries.resize(entry_count);
258 if (entry_count == 0)
259 return true;
261 for (size_t i = 0; i < entry_count; ++i)
262 RCHECK(reader->Read4(&entries[i]));
264 return true;
267 bool SyncSample::IsSyncSample(size_t k) const {
268 // ISO/IEC 14496-12 Section 8.6.2.1 : If the sync sample box is not present,
269 // every sample is a sync sample.
270 if (!is_present)
271 return true;
273 // ISO/IEC 14496-12 Section 8.6.2.3 : If entry_count is zero, there are no
274 // sync samples within the stream.
275 if (entries.size() == 0u)
276 return false;
278 for (size_t i = 0; i < entries.size(); ++i) {
279 if (entries[i] == k)
280 return true;
283 return false;
286 SampleTable::SampleTable() {}
287 SampleTable::~SampleTable() {}
288 FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
290 bool SampleTable::Parse(BoxReader* reader) {
291 return reader->ScanChildren() &&
292 reader->ReadChild(&description) &&
293 reader->MaybeReadChild(&sync_sample);
296 EditList::EditList() {}
297 EditList::~EditList() {}
298 FourCC EditList::BoxType() const { return FOURCC_ELST; }
300 bool EditList::Parse(BoxReader* reader) {
301 uint32 count;
302 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count));
304 if (reader->version() == 1) {
305 RCHECK(reader->HasBytes(count * 20));
306 } else {
307 RCHECK(reader->HasBytes(count * 12));
309 edits.resize(count);
311 for (std::vector<EditListEntry>::iterator edit = edits.begin();
312 edit != edits.end(); ++edit) {
313 if (reader->version() == 1) {
314 RCHECK(reader->Read8(&edit->segment_duration) &&
315 reader->Read8s(&edit->media_time));
316 } else {
317 RCHECK(reader->Read4Into8(&edit->segment_duration) &&
318 reader->Read4sInto8s(&edit->media_time));
320 RCHECK(reader->Read2s(&edit->media_rate_integer) &&
321 reader->Read2s(&edit->media_rate_fraction));
323 return true;
326 Edit::Edit() {}
327 Edit::~Edit() {}
328 FourCC Edit::BoxType() const { return FOURCC_EDTS; }
330 bool Edit::Parse(BoxReader* reader) {
331 return reader->ScanChildren() && reader->ReadChild(&list);
334 HandlerReference::HandlerReference() : type(kInvalid) {}
335 HandlerReference::~HandlerReference() {}
336 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
338 bool HandlerReference::Parse(BoxReader* reader) {
339 FourCC hdlr_type;
340 RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type));
341 // Note: remaining fields in box ignored
342 if (hdlr_type == FOURCC_VIDE) {
343 type = kVideo;
344 } else if (hdlr_type == FOURCC_SOUN) {
345 type = kAudio;
346 } else {
347 type = kInvalid;
349 return true;
352 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
353 : version(0),
354 profile_indication(0),
355 profile_compatibility(0),
356 avc_level(0),
357 length_size(0) {}
359 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
360 FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
362 bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
363 return ParseInternal(reader, reader->log_cb());
366 bool AVCDecoderConfigurationRecord::Parse(const uint8* data, int data_size) {
367 BufferReader reader(data, data_size);
368 return ParseInternal(&reader, LogCB());
371 bool AVCDecoderConfigurationRecord::ParseInternal(BufferReader* reader,
372 const LogCB& log_cb) {
373 RCHECK(reader->Read1(&version) && version == 1 &&
374 reader->Read1(&profile_indication) &&
375 reader->Read1(&profile_compatibility) &&
376 reader->Read1(&avc_level));
378 uint8 length_size_minus_one;
379 RCHECK(reader->Read1(&length_size_minus_one));
380 length_size = (length_size_minus_one & 0x3) + 1;
382 RCHECK(length_size != 3); // Only values of 1, 2, and 4 are valid.
384 uint8 num_sps;
385 RCHECK(reader->Read1(&num_sps));
386 num_sps &= 0x1f;
388 sps_list.resize(num_sps);
389 for (int i = 0; i < num_sps; i++) {
390 uint16 sps_length;
391 RCHECK(reader->Read2(&sps_length) &&
392 reader->ReadVec(&sps_list[i], sps_length));
393 RCHECK(sps_list[i].size() > 4);
395 if (!log_cb.is_null()) {
396 MEDIA_LOG(INFO, log_cb) << "Video codec: avc1." << std::hex
397 << static_cast<int>(sps_list[i][1])
398 << static_cast<int>(sps_list[i][2])
399 << static_cast<int>(sps_list[i][3]);
403 uint8 num_pps;
404 RCHECK(reader->Read1(&num_pps));
406 pps_list.resize(num_pps);
407 for (int i = 0; i < num_pps; i++) {
408 uint16 pps_length;
409 RCHECK(reader->Read2(&pps_length) &&
410 reader->ReadVec(&pps_list[i], pps_length));
413 return true;
416 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
417 PixelAspectRatioBox::~PixelAspectRatioBox() {}
418 FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
420 bool PixelAspectRatioBox::Parse(BoxReader* reader) {
421 RCHECK(reader->Read4(&h_spacing) &&
422 reader->Read4(&v_spacing));
423 return true;
426 VideoSampleEntry::VideoSampleEntry()
427 : format(FOURCC_NULL),
428 data_reference_index(0),
429 width(0),
430 height(0) {}
432 VideoSampleEntry::~VideoSampleEntry() {}
433 FourCC VideoSampleEntry::BoxType() const {
434 DCHECK(false) << "VideoSampleEntry should be parsed according to the "
435 << "handler type recovered in its Media ancestor.";
436 return FOURCC_NULL;
439 bool VideoSampleEntry::Parse(BoxReader* reader) {
440 format = reader->type();
441 RCHECK(reader->SkipBytes(6) &&
442 reader->Read2(&data_reference_index) &&
443 reader->SkipBytes(16) &&
444 reader->Read2(&width) &&
445 reader->Read2(&height) &&
446 reader->SkipBytes(50));
448 RCHECK(reader->ScanChildren() &&
449 reader->MaybeReadChild(&pixel_aspect));
451 if (format == FOURCC_ENCV) {
452 // Continue scanning until a recognized protection scheme is found, or until
453 // we run out of protection schemes.
454 while (sinf.type.type != FOURCC_CENC) {
455 if (!reader->ReadChild(&sinf))
456 return false;
460 if (IsFormatValid())
461 RCHECK(reader->ReadChild(&avcc));
463 return true;
466 bool VideoSampleEntry::IsFormatValid() const {
467 return format == FOURCC_AVC1 || format == FOURCC_AVC3 ||
468 (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 ||
469 sinf.format.format == FOURCC_AVC3));
472 ElementaryStreamDescriptor::ElementaryStreamDescriptor()
473 : object_type(kForbidden) {}
475 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
477 FourCC ElementaryStreamDescriptor::BoxType() const {
478 return FOURCC_ESDS;
481 bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {
482 std::vector<uint8> data;
483 ESDescriptor es_desc;
485 RCHECK(reader->ReadFullBoxHeader());
486 RCHECK(reader->ReadVec(&data, reader->size() - reader->pos()));
487 RCHECK(es_desc.Parse(data));
489 object_type = es_desc.object_type();
491 if (object_type != 0x40) {
492 MEDIA_LOG(INFO, reader->log_cb()) << "Audio codec: mp4a." << std::hex
493 << static_cast<int>(object_type);
496 if (es_desc.IsAAC(object_type))
497 RCHECK(aac.Parse(es_desc.decoder_specific_info(), reader->log_cb()));
499 return true;
502 AudioSampleEntry::AudioSampleEntry()
503 : format(FOURCC_NULL),
504 data_reference_index(0),
505 channelcount(0),
506 samplesize(0),
507 samplerate(0) {}
509 AudioSampleEntry::~AudioSampleEntry() {}
511 FourCC AudioSampleEntry::BoxType() const {
512 DCHECK(false) << "AudioSampleEntry should be parsed according to the "
513 << "handler type recovered in its Media ancestor.";
514 return FOURCC_NULL;
517 bool AudioSampleEntry::Parse(BoxReader* reader) {
518 format = reader->type();
519 RCHECK(reader->SkipBytes(6) &&
520 reader->Read2(&data_reference_index) &&
521 reader->SkipBytes(8) &&
522 reader->Read2(&channelcount) &&
523 reader->Read2(&samplesize) &&
524 reader->SkipBytes(4) &&
525 reader->Read4(&samplerate));
526 // Convert from 16.16 fixed point to integer
527 samplerate >>= 16;
529 RCHECK(reader->ScanChildren());
530 if (format == FOURCC_ENCA) {
531 // Continue scanning until a recognized protection scheme is found, or until
532 // we run out of protection schemes.
533 while (sinf.type.type != FOURCC_CENC) {
534 if (!reader->ReadChild(&sinf))
535 return false;
539 // ESDS is not valid in case of EAC3.
540 RCHECK(reader->MaybeReadChild(&esds));
541 return true;
544 MediaHeader::MediaHeader()
545 : creation_time(0),
546 modification_time(0),
547 timescale(0),
548 duration(0) {}
549 MediaHeader::~MediaHeader() {}
550 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
552 bool MediaHeader::Parse(BoxReader* reader) {
553 RCHECK(reader->ReadFullBoxHeader());
555 if (reader->version() == 1) {
556 RCHECK(reader->Read8(&creation_time) &&
557 reader->Read8(&modification_time) &&
558 reader->Read4(&timescale) &&
559 reader->Read8(&duration));
560 } else {
561 RCHECK(reader->Read4Into8(&creation_time) &&
562 reader->Read4Into8(&modification_time) &&
563 reader->Read4(&timescale) &&
564 reader->Read4Into8(&duration));
566 // Skip language information
567 return reader->SkipBytes(4);
570 MediaInformation::MediaInformation() {}
571 MediaInformation::~MediaInformation() {}
572 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
574 bool MediaInformation::Parse(BoxReader* reader) {
575 return reader->ScanChildren() &&
576 reader->ReadChild(&sample_table);
579 Media::Media() {}
580 Media::~Media() {}
581 FourCC Media::BoxType() const { return FOURCC_MDIA; }
583 bool Media::Parse(BoxReader* reader) {
584 RCHECK(reader->ScanChildren() &&
585 reader->ReadChild(&header) &&
586 reader->ReadChild(&handler));
588 // Maddeningly, the HandlerReference box specifies how to parse the
589 // SampleDescription box, making the latter the only box (of those that we
590 // support) which cannot be parsed correctly on its own (or even with
591 // information from its strict ancestor tree). We thus copy the handler type
592 // to the sample description box *before* parsing it to provide this
593 // information while parsing.
594 information.sample_table.description.type = handler.type;
595 RCHECK(reader->ReadChild(&information));
596 return true;
599 Track::Track() {}
600 Track::~Track() {}
601 FourCC Track::BoxType() const { return FOURCC_TRAK; }
603 bool Track::Parse(BoxReader* reader) {
604 RCHECK(reader->ScanChildren() &&
605 reader->ReadChild(&header) &&
606 reader->ReadChild(&media) &&
607 reader->MaybeReadChild(&edit));
608 return true;
611 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
612 MovieExtendsHeader::~MovieExtendsHeader() {}
613 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
615 bool MovieExtendsHeader::Parse(BoxReader* reader) {
616 RCHECK(reader->ReadFullBoxHeader());
617 if (reader->version() == 1) {
618 RCHECK(reader->Read8(&fragment_duration));
619 } else {
620 RCHECK(reader->Read4Into8(&fragment_duration));
622 return true;
625 TrackExtends::TrackExtends()
626 : track_id(0),
627 default_sample_description_index(0),
628 default_sample_duration(0),
629 default_sample_size(0),
630 default_sample_flags(0) {}
631 TrackExtends::~TrackExtends() {}
632 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
634 bool TrackExtends::Parse(BoxReader* reader) {
635 RCHECK(reader->ReadFullBoxHeader() &&
636 reader->Read4(&track_id) &&
637 reader->Read4(&default_sample_description_index) &&
638 reader->Read4(&default_sample_duration) &&
639 reader->Read4(&default_sample_size) &&
640 reader->Read4(&default_sample_flags));
641 return true;
644 MovieExtends::MovieExtends() {}
645 MovieExtends::~MovieExtends() {}
646 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
648 bool MovieExtends::Parse(BoxReader* reader) {
649 header.fragment_duration = 0;
650 return reader->ScanChildren() &&
651 reader->MaybeReadChild(&header) &&
652 reader->ReadChildren(&tracks);
655 Movie::Movie() : fragmented(false) {}
656 Movie::~Movie() {}
657 FourCC Movie::BoxType() const { return FOURCC_MOOV; }
659 bool Movie::Parse(BoxReader* reader) {
660 RCHECK(reader->ScanChildren() && reader->ReadChild(&header) &&
661 reader->ReadChildren(&tracks));
663 RCHECK_MEDIA_LOGGED(reader->ReadChild(&extends), reader->log_cb(),
664 "Detected unfragmented MP4. Media Source Extensions "
665 "require ISO BMFF moov to contain mvex to indicate that "
666 "Movie Fragments are to be expected.");
668 return reader->MaybeReadChildren(&pssh);
671 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
672 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
673 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
675 bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {
676 RCHECK(reader->ReadFullBoxHeader());
677 if (reader->version() == 1)
678 return reader->Read8(&decode_time);
679 else
680 return reader->Read4Into8(&decode_time);
683 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
684 MovieFragmentHeader::~MovieFragmentHeader() {}
685 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
687 bool MovieFragmentHeader::Parse(BoxReader* reader) {
688 return reader->SkipBytes(4) && reader->Read4(&sequence_number);
691 TrackFragmentHeader::TrackFragmentHeader()
692 : track_id(0),
693 sample_description_index(0),
694 default_sample_duration(0),
695 default_sample_size(0),
696 default_sample_flags(0),
697 has_default_sample_flags(false) {}
699 TrackFragmentHeader::~TrackFragmentHeader() {}
700 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
702 bool TrackFragmentHeader::Parse(BoxReader* reader) {
703 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id));
705 // Media Source specific: reject tracks that set 'base-data-offset-present'.
706 // Although the Media Source requires that 'default-base-is-moof' (14496-12
707 // Amendment 2) be set, we omit this check as many otherwise-valid files in
708 // the wild don't set it.
710 // RCHECK((flags & 0x020000) && !(flags & 0x1));
711 RCHECK(!(reader->flags() & 0x1));
713 if (reader->flags() & 0x2) {
714 RCHECK(reader->Read4(&sample_description_index));
715 } else {
716 sample_description_index = 0;
719 if (reader->flags() & 0x8) {
720 RCHECK(reader->Read4(&default_sample_duration));
721 } else {
722 default_sample_duration = 0;
725 if (reader->flags() & 0x10) {
726 RCHECK(reader->Read4(&default_sample_size));
727 } else {
728 default_sample_size = 0;
731 if (reader->flags() & 0x20) {
732 RCHECK(reader->Read4(&default_sample_flags));
733 has_default_sample_flags = true;
734 } else {
735 has_default_sample_flags = false;
738 return true;
741 TrackFragmentRun::TrackFragmentRun()
742 : sample_count(0), data_offset(0) {}
743 TrackFragmentRun::~TrackFragmentRun() {}
744 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
746 bool TrackFragmentRun::Parse(BoxReader* reader) {
747 RCHECK(reader->ReadFullBoxHeader() &&
748 reader->Read4(&sample_count));
749 const uint32 flags = reader->flags();
751 bool data_offset_present = (flags & 0x1) != 0;
752 bool first_sample_flags_present = (flags & 0x4) != 0;
753 bool sample_duration_present = (flags & 0x100) != 0;
754 bool sample_size_present = (flags & 0x200) != 0;
755 bool sample_flags_present = (flags & 0x400) != 0;
756 bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
758 if (data_offset_present) {
759 RCHECK(reader->Read4(&data_offset));
760 } else {
761 data_offset = 0;
764 uint32 first_sample_flags = 0;
765 if (first_sample_flags_present)
766 RCHECK(reader->Read4(&first_sample_flags));
768 int fields = sample_duration_present + sample_size_present +
769 sample_flags_present + sample_composition_time_offsets_present;
770 RCHECK(reader->HasBytes(fields * sample_count));
772 if (sample_duration_present)
773 sample_durations.resize(sample_count);
774 if (sample_size_present)
775 sample_sizes.resize(sample_count);
776 if (sample_flags_present)
777 sample_flags.resize(sample_count);
778 if (sample_composition_time_offsets_present)
779 sample_composition_time_offsets.resize(sample_count);
781 for (uint32 i = 0; i < sample_count; ++i) {
782 if (sample_duration_present)
783 RCHECK(reader->Read4(&sample_durations[i]));
784 if (sample_size_present)
785 RCHECK(reader->Read4(&sample_sizes[i]));
786 if (sample_flags_present)
787 RCHECK(reader->Read4(&sample_flags[i]));
788 if (sample_composition_time_offsets_present)
789 RCHECK(reader->Read4s(&sample_composition_time_offsets[i]));
792 if (first_sample_flags_present) {
793 if (sample_flags.size() == 0) {
794 sample_flags.push_back(first_sample_flags);
795 } else {
796 sample_flags[0] = first_sample_flags;
799 return true;
802 SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
803 SampleToGroup::~SampleToGroup() {}
804 FourCC SampleToGroup::BoxType() const { return FOURCC_SBGP; }
806 bool SampleToGroup::Parse(BoxReader* reader) {
807 RCHECK(reader->ReadFullBoxHeader() &&
808 reader->Read4(&grouping_type));
810 if (reader->version() == 1)
811 RCHECK(reader->Read4(&grouping_type_parameter));
813 if (grouping_type != FOURCC_SEIG) {
814 DLOG(WARNING) << "SampleToGroup box with grouping_type '" << grouping_type
815 << "' is not supported.";
816 return true;
819 uint32 count;
820 RCHECK(reader->Read4(&count));
821 entries.resize(count);
822 for (uint32 i = 0; i < count; ++i) {
823 RCHECK(reader->Read4(&entries[i].sample_count) &&
824 reader->Read4(&entries[i].group_description_index));
826 return true;
829 CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
830 : is_encrypted(false), iv_size(0) {}
831 CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {}
833 SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
834 SampleGroupDescription::~SampleGroupDescription() {}
835 FourCC SampleGroupDescription::BoxType() const { return FOURCC_SGPD; }
837 bool SampleGroupDescription::Parse(BoxReader* reader) {
838 RCHECK(reader->ReadFullBoxHeader() &&
839 reader->Read4(&grouping_type));
841 if (grouping_type != FOURCC_SEIG) {
842 DLOG(WARNING) << "SampleGroupDescription box with grouping_type '"
843 << grouping_type << "' is not supported.";
844 return true;
847 const uint8 version = reader->version();
849 const size_t kKeyIdSize = 16;
850 const size_t kEntrySize = sizeof(uint32) + kKeyIdSize;
851 uint32 default_length = 0;
852 if (version == 1) {
853 RCHECK(reader->Read4(&default_length));
854 RCHECK(default_length == 0 || default_length >= kEntrySize);
857 uint32 count;
858 RCHECK(reader->Read4(&count));
859 entries.resize(count);
860 for (uint32 i = 0; i < count; ++i) {
861 if (version == 1) {
862 if (default_length == 0) {
863 uint32 description_length = 0;
864 RCHECK(reader->Read4(&description_length));
865 RCHECK(description_length >= kEntrySize);
869 uint8 flag;
870 RCHECK(reader->SkipBytes(2) && // reserved.
871 reader->Read1(&flag) &&
872 reader->Read1(&entries[i].iv_size) &&
873 reader->ReadVec(&entries[i].key_id, kKeyIdSize));
875 entries[i].is_encrypted = (flag != 0);
876 if (entries[i].is_encrypted) {
877 RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
878 } else {
879 RCHECK(entries[i].iv_size == 0);
882 return true;
885 TrackFragment::TrackFragment() {}
886 TrackFragment::~TrackFragment() {}
887 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
889 bool TrackFragment::Parse(BoxReader* reader) {
890 RCHECK(reader->ScanChildren() &&
891 reader->ReadChild(&header) &&
892 // Media Source specific: 'tfdt' required
893 reader->ReadChild(&decode_time) &&
894 reader->MaybeReadChildren(&runs) &&
895 reader->MaybeReadChild(&auxiliary_offset) &&
896 reader->MaybeReadChild(&auxiliary_size) &&
897 reader->MaybeReadChild(&sdtp));
899 // There could be multiple SampleGroupDescription and SampleToGroup boxes with
900 // different grouping types. For common encryption, the relevant grouping type
901 // is 'seig'. Continue reading until 'seig' is found, or until running out of
902 // child boxes.
903 while (sample_group_description.grouping_type != FOURCC_SEIG &&
904 reader->HasChild(&sample_group_description)) {
905 RCHECK(reader->ReadChild(&sample_group_description));
907 while (sample_to_group.grouping_type != FOURCC_SEIG &&
908 reader->HasChild(&sample_to_group)) {
909 RCHECK(reader->ReadChild(&sample_to_group));
911 return true;
914 MovieFragment::MovieFragment() {}
915 MovieFragment::~MovieFragment() {}
916 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
918 bool MovieFragment::Parse(BoxReader* reader) {
919 RCHECK(reader->ScanChildren() &&
920 reader->ReadChild(&header) &&
921 reader->ReadChildren(&tracks) &&
922 reader->MaybeReadChildren(&pssh));
923 return true;
926 IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
927 IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
928 FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; }
930 bool IndependentAndDisposableSamples::Parse(BoxReader* reader) {
931 RCHECK(reader->ReadFullBoxHeader());
932 RCHECK(reader->version() == 0);
933 RCHECK(reader->flags() == 0);
935 int sample_count = reader->size() - reader->pos();
936 sample_depends_on_.resize(sample_count);
937 for (int i = 0; i < sample_count; ++i) {
938 uint8 sample_info;
939 RCHECK(reader->Read1(&sample_info));
941 sample_depends_on_[i] =
942 static_cast<SampleDependsOn>((sample_info >> 4) & 0x3);
944 RCHECK(sample_depends_on_[i] != kSampleDependsOnReserved);
947 return true;
950 SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
951 size_t i) const {
952 if (i >= sample_depends_on_.size())
953 return kSampleDependsOnUnknown;
955 return sample_depends_on_[i];
958 } // namespace mp4
959 } // namespace media