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 // 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());
36 FullProtectionSystemSpecificHeader::FullProtectionSystemSpecificHeader() {}
37 FullProtectionSystemSpecificHeader::~FullProtectionSystemSpecificHeader() {}
38 FourCC
FullProtectionSystemSpecificHeader::BoxType() const {
42 // The format of a 'pssh' box is as follows:
43 // unsigned int(32) size;
44 // unsigned int(32) type = "pssh";
46 // unsigned int(64) largesize;
47 // } else if (size==0) {
48 // -- box extends to end of file
50 // unsigned int(8) version;
52 // unsigned int(8)[16] SystemID;
55 // unsigned int(32) KID_count;
57 // unsigned int(8)[16] KID;
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) {
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
);
83 RCHECK(reader
->Read4(&data_size
));
84 RCHECK(reader
->ReadVec(&data
, data_size
));
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));
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
]));
106 RCHECK(reader
->Read4Into8(&offsets
[i
]));
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
);
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
));
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
) {
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);
164 RCHECK(default_iv_size
== 8 || default_iv_size
== 16);
166 RCHECK(default_iv_size
== 0);
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.
196 MovieHeader::MovieHeader()
198 modification_time(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(×cale
) &&
214 reader
->Read8(&duration
));
216 RCHECK(reader
->Read4Into8(&creation_time
) &&
217 reader
->Read4Into8(&modification_time
) &&
218 reader
->Read4(×cale
) &&
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
));
231 TrackHeader::TrackHeader()
233 modification_time(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
));
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
));
273 SampleDescription::SampleDescription() : type(kInvalid
) {}
274 SampleDescription::~SampleDescription() {}
275 FourCC
SampleDescription::BoxType() const { return FOURCC_STSD
; }
277 bool SampleDescription::Parse(BoxReader
* reader
) {
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
));
294 SyncSample::SyncSample() : is_present(false) {}
295 SyncSample::~SyncSample() {}
296 FourCC
SyncSample::BoxType() const { return FOURCC_STSS
; }
298 bool SyncSample::Parse(BoxReader
* reader
) {
300 RCHECK(reader
->ReadFullBoxHeader() &&
301 reader
->Read4(&entry_count
));
305 entries
.resize(entry_count
);
307 if (entry_count
== 0)
310 for (size_t i
= 0; i
< entry_count
; ++i
)
311 RCHECK(reader
->Read4(&entries
[i
]));
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.
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)
327 for (size_t i
= 0; i
< entries
.size(); ++i
) {
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
347 while (reader
->HasChild(&sample_group_description
)) {
348 RCHECK(reader
->ReadChild(&sample_group_description
));
349 if (sample_group_description
.grouping_type
== FOURCC_SEIG
)
351 sample_group_description
.entries
.clear();
356 EditList::EditList() {}
357 EditList::~EditList() {}
358 FourCC
EditList::BoxType() const { return FOURCC_ELST
; }
360 bool EditList::Parse(BoxReader
* reader
) {
362 RCHECK(reader
->ReadFullBoxHeader() && reader
->Read4(&count
));
364 if (reader
->version() == 1) {
365 RCHECK(reader
->HasBytes(count
* 20));
367 RCHECK(reader
->HasBytes(count
* 12));
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
));
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
));
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
) {
400 RCHECK(reader
->SkipBytes(8) && reader
->ReadFourCC(&hdlr_type
));
401 // Note: remaining fields in box ignored
402 if (hdlr_type
== FOURCC_VIDE
) {
404 } else if (hdlr_type
== FOURCC_SOUN
) {
412 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
414 profile_indication(0),
415 profile_compatibility(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.
446 RCHECK(reader
->Read1(&num_sps
));
449 sps_list
.resize(num_sps
);
450 for (int i
= 0; i
< num_sps
; i
++) {
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]);
465 RCHECK(reader
->Read1(&num_pps
));
467 pps_list
.resize(num_pps
);
468 for (int i
= 0; i
< num_pps
; i
++) {
470 RCHECK(reader
->Read2(&pps_length
) &&
471 reader
->ReadVec(&pps_list
[i
], pps_length
));
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
));
487 VideoSampleEntry::VideoSampleEntry()
488 : format(FOURCC_NULL
),
489 data_reference_index(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.";
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
))
522 RCHECK(reader
->ReadChild(&avcc
));
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 {
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()));
563 AudioSampleEntry::AudioSampleEntry()
564 : format(FOURCC_NULL
),
565 data_reference_index(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.";
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
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
))
600 // ESDS is not valid in case of EAC3.
601 RCHECK(reader
->MaybeReadChild(&esds
));
605 MediaHeader::MediaHeader()
607 modification_time(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(×cale
) &&
620 reader
->Read8(&duration
));
622 RCHECK(reader
->Read4Into8(&creation_time
) &&
623 reader
->Read4Into8(&modification_time
) &&
624 reader
->Read4(×cale
) &&
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
);
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
));
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
));
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
));
681 RCHECK(reader
->Read4Into8(&fragment_duration
));
686 TrackExtends::TrackExtends()
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
));
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) {}
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
);
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()
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
));
777 sample_description_index
= 0;
780 if (reader
->flags() & 0x8) {
781 RCHECK(reader
->Read4(&default_sample_duration
));
783 default_sample_duration
= 0;
786 if (reader
->flags() & 0x10) {
787 RCHECK(reader
->Read4(&default_sample_size
));
789 default_sample_size
= 0;
792 if (reader
->flags() & 0x20) {
793 RCHECK(reader
->Read4(&default_sample_flags
));
794 has_default_sample_flags
= true;
796 has_default_sample_flags
= false;
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
));
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
);
857 sample_flags
[0] = first_sample_flags
;
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.";
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
));
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.";
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;
914 RCHECK(reader
->Read4(&default_length
));
915 RCHECK(default_length
== 0 || default_length
>= kEntrySize
);
919 RCHECK(reader
->Read4(&count
));
920 entries
.resize(count
);
921 for (uint32 i
= 0; i
< count
; ++i
) {
923 if (default_length
== 0) {
924 uint32 description_length
= 0;
925 RCHECK(reader
->Read4(&description_length
));
926 RCHECK(description_length
>= kEntrySize
);
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);
940 RCHECK(entries
[i
].iv_size
== 0);
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
964 while (reader
->HasChild(&sample_group_description
)) {
965 RCHECK(reader
->ReadChild(&sample_group_description
));
966 if (sample_group_description
.grouping_type
== FOURCC_SEIG
)
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
)
974 sample_to_group
.entries
.clear();
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
));
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
) {
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
);
1015 SampleDependsOn
IndependentAndDisposableSamples::sample_depends_on(
1017 if (i
>= sample_depends_on_
.size())
1018 return kSampleDependsOnUnknown
;
1020 return sample_depends_on_
[i
];
1024 } // namespace media