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.
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());
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));
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
]));
57 RCHECK(reader
->Read4Into8(&offsets
[i
]));
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
);
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
));
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
) {
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);
115 RCHECK(default_iv_size
== 8 || default_iv_size
== 16);
117 RCHECK(default_iv_size
== 0);
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.
147 MovieHeader::MovieHeader()
149 modification_time(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(×cale
) &&
165 reader
->Read8(&duration
));
167 RCHECK(reader
->Read4Into8(&creation_time
) &&
168 reader
->Read4Into8(&modification_time
) &&
169 reader
->Read4(×cale
) &&
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
));
182 TrackHeader::TrackHeader()
184 modification_time(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
));
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
));
224 SampleDescription::SampleDescription() : type(kInvalid
) {}
225 SampleDescription::~SampleDescription() {}
226 FourCC
SampleDescription::BoxType() const { return FOURCC_STSD
; }
228 bool SampleDescription::Parse(BoxReader
* reader
) {
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
));
245 SyncSample::SyncSample() : is_present(false) {}
246 SyncSample::~SyncSample() {}
247 FourCC
SyncSample::BoxType() const { return FOURCC_STSS
; }
249 bool SyncSample::Parse(BoxReader
* reader
) {
251 RCHECK(reader
->ReadFullBoxHeader() &&
252 reader
->Read4(&entry_count
));
256 entries
.resize(entry_count
);
258 if (entry_count
== 0)
261 for (size_t i
= 0; i
< entry_count
; ++i
)
262 RCHECK(reader
->Read4(&entries
[i
]));
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.
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)
278 for (size_t i
= 0; i
< entries
.size(); ++i
) {
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
) {
302 RCHECK(reader
->ReadFullBoxHeader() && reader
->Read4(&count
));
304 if (reader
->version() == 1) {
305 RCHECK(reader
->HasBytes(count
* 20));
307 RCHECK(reader
->HasBytes(count
* 12));
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
));
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
));
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
) {
340 RCHECK(reader
->SkipBytes(8) && reader
->ReadFourCC(&hdlr_type
));
341 // Note: remaining fields in box ignored
342 if (hdlr_type
== FOURCC_VIDE
) {
344 } else if (hdlr_type
== FOURCC_SOUN
) {
352 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
354 profile_indication(0),
355 profile_compatibility(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.
385 RCHECK(reader
->Read1(&num_sps
));
388 sps_list
.resize(num_sps
);
389 for (int i
= 0; i
< num_sps
; i
++) {
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]);
404 RCHECK(reader
->Read1(&num_pps
));
406 pps_list
.resize(num_pps
);
407 for (int i
= 0; i
< num_pps
; i
++) {
409 RCHECK(reader
->Read2(&pps_length
) &&
410 reader
->ReadVec(&pps_list
[i
], pps_length
));
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
));
426 VideoSampleEntry::VideoSampleEntry()
427 : format(FOURCC_NULL
),
428 data_reference_index(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.";
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
))
461 RCHECK(reader
->ReadChild(&avcc
));
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 {
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()));
502 AudioSampleEntry::AudioSampleEntry()
503 : format(FOURCC_NULL
),
504 data_reference_index(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.";
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
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
))
539 // ESDS is not valid in case of EAC3.
540 RCHECK(reader
->MaybeReadChild(&esds
));
544 MediaHeader::MediaHeader()
546 modification_time(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(×cale
) &&
559 reader
->Read8(&duration
));
561 RCHECK(reader
->Read4Into8(&creation_time
) &&
562 reader
->Read4Into8(&modification_time
) &&
563 reader
->Read4(×cale
) &&
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
);
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
));
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
));
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
));
620 RCHECK(reader
->Read4Into8(&fragment_duration
));
625 TrackExtends::TrackExtends()
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
));
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) {}
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
);
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()
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
));
716 sample_description_index
= 0;
719 if (reader
->flags() & 0x8) {
720 RCHECK(reader
->Read4(&default_sample_duration
));
722 default_sample_duration
= 0;
725 if (reader
->flags() & 0x10) {
726 RCHECK(reader
->Read4(&default_sample_size
));
728 default_sample_size
= 0;
731 if (reader
->flags() & 0x20) {
732 RCHECK(reader
->Read4(&default_sample_flags
));
733 has_default_sample_flags
= true;
735 has_default_sample_flags
= false;
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
));
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
);
796 sample_flags
[0] = first_sample_flags
;
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.";
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
));
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.";
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;
853 RCHECK(reader
->Read4(&default_length
));
854 RCHECK(default_length
== 0 || default_length
>= kEntrySize
);
858 RCHECK(reader
->Read4(&count
));
859 entries
.resize(count
);
860 for (uint32 i
= 0; i
< count
; ++i
) {
862 if (default_length
== 0) {
863 uint32 description_length
= 0;
864 RCHECK(reader
->Read4(&description_length
));
865 RCHECK(description_length
>= kEntrySize
);
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);
879 RCHECK(entries
[i
].iv_size
== 0);
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
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
));
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
));
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
) {
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
);
950 SampleDependsOn
IndependentAndDisposableSamples::sample_depends_on(
952 if (i
>= sample_depends_on_
.size())
953 return kSampleDependsOnUnknown
;
955 return sample_depends_on_
[i
];