1 // Copyright (c) 2012 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/mp4/box_definitions.h"
7 #include "base/logging.h"
8 #include "media/mp4/es_descriptor.h"
9 #include "media/mp4/rcheck.h"
14 FileType::FileType() {}
15 FileType::~FileType() {}
16 FourCC
FileType::BoxType() const { return FOURCC_FTYP
; }
18 bool FileType::Parse(BoxReader
* reader
) {
19 RCHECK(reader
->ReadFourCC(&major_brand
) && reader
->Read4(&minor_version
));
20 size_t num_brands
= (reader
->size() - reader
->pos()) / sizeof(FourCC
);
21 return reader
->SkipBytes(sizeof(FourCC
) * num_brands
); // compatible_brands
24 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
25 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
26 FourCC
ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH
; }
28 bool ProtectionSystemSpecificHeader::Parse(BoxReader
* reader
) {
29 // Validate the box's contents and hang on to the system ID.
31 RCHECK(reader
->ReadFullBoxHeader() &&
32 reader
->ReadVec(&system_id
, 16) &&
33 reader
->Read4(&size
) &&
34 reader
->HasBytes(size
));
36 // Copy the entire box, including the header, for passing to EME as initData.
37 DCHECK(raw_box
.empty());
38 raw_box
.assign(reader
->data(), reader
->data() + reader
->size());
42 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
43 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
44 FourCC
SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO
; }
46 bool SampleAuxiliaryInformationOffset::Parse(BoxReader
* reader
) {
47 RCHECK(reader
->ReadFullBoxHeader());
48 if (reader
->flags() & 1)
49 RCHECK(reader
->SkipBytes(8));
52 RCHECK(reader
->Read4(&count
) &&
53 reader
->HasBytes(count
* (reader
->version() == 1 ? 8 : 4)));
54 offsets
.resize(count
);
56 for (uint32 i
= 0; i
< count
; i
++) {
57 if (reader
->version() == 1) {
58 RCHECK(reader
->Read8(&offsets
[i
]));
60 RCHECK(reader
->Read4Into8(&offsets
[i
]));
66 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
67 : default_sample_info_size(0), sample_count(0) {
69 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
70 FourCC
SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ
; }
72 bool SampleAuxiliaryInformationSize::Parse(BoxReader
* reader
) {
73 RCHECK(reader
->ReadFullBoxHeader());
74 if (reader
->flags() & 1)
75 RCHECK(reader
->SkipBytes(8));
77 RCHECK(reader
->Read1(&default_sample_info_size
) &&
78 reader
->Read4(&sample_count
));
79 if (default_sample_info_size
== 0)
80 return reader
->ReadVec(&sample_info_sizes
, sample_count
);
84 OriginalFormat::OriginalFormat() : format(FOURCC_NULL
) {}
85 OriginalFormat::~OriginalFormat() {}
86 FourCC
OriginalFormat::BoxType() const { return FOURCC_FRMA
; }
88 bool OriginalFormat::Parse(BoxReader
* reader
) {
89 return reader
->ReadFourCC(&format
);
92 SchemeType::SchemeType() : type(FOURCC_NULL
), version(0) {}
93 SchemeType::~SchemeType() {}
94 FourCC
SchemeType::BoxType() const { return FOURCC_SCHM
; }
96 bool SchemeType::Parse(BoxReader
* reader
) {
97 RCHECK(reader
->ReadFullBoxHeader() &&
98 reader
->ReadFourCC(&type
) &&
99 reader
->Read4(&version
));
103 TrackEncryption::TrackEncryption()
104 : is_encrypted(false), default_iv_size(0) {
106 TrackEncryption::~TrackEncryption() {}
107 FourCC
TrackEncryption::BoxType() const { return FOURCC_TENC
; }
109 bool TrackEncryption::Parse(BoxReader
* reader
) {
111 RCHECK(reader
->ReadFullBoxHeader() &&
112 reader
->SkipBytes(2) &&
113 reader
->Read1(&flag
) &&
114 reader
->Read1(&default_iv_size
) &&
115 reader
->ReadVec(&default_kid
, 16));
116 is_encrypted
= (flag
!= 0);
118 RCHECK(default_iv_size
== 8 || default_iv_size
== 16);
120 RCHECK(default_iv_size
== 0);
125 SchemeInfo::SchemeInfo() {}
126 SchemeInfo::~SchemeInfo() {}
127 FourCC
SchemeInfo::BoxType() const { return FOURCC_SCHI
; }
129 bool SchemeInfo::Parse(BoxReader
* reader
) {
130 return reader
->ScanChildren() && reader
->ReadChild(&track_encryption
);
133 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
134 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
135 FourCC
ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF
; }
137 bool ProtectionSchemeInfo::Parse(BoxReader
* reader
) {
138 RCHECK(reader
->ScanChildren() &&
139 reader
->ReadChild(&format
) &&
140 reader
->ReadChild(&type
));
141 if (type
.type
== FOURCC_CENC
)
142 RCHECK(reader
->ReadChild(&info
));
143 // Other protection schemes are silently ignored. Since the protection scheme
144 // type can't be determined until this box is opened, we return 'true' for
145 // non-CENC protection scheme types. It is the parent box's responsibility to
146 // ensure that this scheme type is a supported one.
150 MovieHeader::MovieHeader()
152 modification_time(0),
158 MovieHeader::~MovieHeader() {}
159 FourCC
MovieHeader::BoxType() const { return FOURCC_MVHD
; }
161 bool MovieHeader::Parse(BoxReader
* reader
) {
162 RCHECK(reader
->ReadFullBoxHeader());
164 if (reader
->version() == 1) {
165 RCHECK(reader
->Read8(&creation_time
) &&
166 reader
->Read8(&modification_time
) &&
167 reader
->Read4(×cale
) &&
168 reader
->Read8(&duration
));
170 RCHECK(reader
->Read4Into8(&creation_time
) &&
171 reader
->Read4Into8(&modification_time
) &&
172 reader
->Read4(×cale
) &&
173 reader
->Read4Into8(&duration
));
176 RCHECK(reader
->Read4s(&rate
) &&
177 reader
->Read2s(&volume
) &&
178 reader
->SkipBytes(10) && // reserved
179 reader
->SkipBytes(36) && // matrix
180 reader
->SkipBytes(24) && // predefined zero
181 reader
->Read4(&next_track_id
));
185 TrackHeader::TrackHeader()
187 modification_time(0),
195 TrackHeader::~TrackHeader() {}
196 FourCC
TrackHeader::BoxType() const { return FOURCC_TKHD
; }
198 bool TrackHeader::Parse(BoxReader
* reader
) {
199 RCHECK(reader
->ReadFullBoxHeader());
200 if (reader
->version() == 1) {
201 RCHECK(reader
->Read8(&creation_time
) &&
202 reader
->Read8(&modification_time
) &&
203 reader
->Read4(&track_id
) &&
204 reader
->SkipBytes(4) && // reserved
205 reader
->Read8(&duration
));
207 RCHECK(reader
->Read4Into8(&creation_time
) &&
208 reader
->Read4Into8(&modification_time
) &&
209 reader
->Read4(&track_id
) &&
210 reader
->SkipBytes(4) && // reserved
211 reader
->Read4Into8(&duration
));
214 RCHECK(reader
->SkipBytes(8) && // reserved
215 reader
->Read2s(&layer
) &&
216 reader
->Read2s(&alternate_group
) &&
217 reader
->Read2s(&volume
) &&
218 reader
->SkipBytes(2) && // reserved
219 reader
->SkipBytes(36) && // matrix
220 reader
->Read4(&width
) &&
221 reader
->Read4(&height
));
227 SampleDescription::SampleDescription() : type(kInvalid
) {}
228 SampleDescription::~SampleDescription() {}
229 FourCC
SampleDescription::BoxType() const { return FOURCC_STSD
; }
231 bool SampleDescription::Parse(BoxReader
* reader
) {
233 RCHECK(reader
->SkipBytes(4) &&
234 reader
->Read4(&count
));
235 video_entries
.clear();
236 audio_entries
.clear();
238 // Note: this value is preset before scanning begins. See comments in the
239 // Parse(Media*) function.
240 if (type
== kVideo
) {
241 RCHECK(reader
->ReadAllChildren(&video_entries
));
242 } else if (type
== kAudio
) {
243 RCHECK(reader
->ReadAllChildren(&audio_entries
));
248 SyncSample::SyncSample() : is_present(false) {}
249 SyncSample::~SyncSample() {}
250 FourCC
SyncSample::BoxType() const { return FOURCC_STSS
; }
252 bool SyncSample::Parse(BoxReader
* reader
) {
254 RCHECK(reader
->ReadFullBoxHeader() &&
255 reader
->Read4(&entry_count
));
259 if (entry_count
== 0)
262 // Skip over the entries since we don't actually care about
263 // them right now. In most fragmented files with an stss, there
264 // aren't any entries anyways because the random access point info
265 // is signalled in the fragments.
266 int64 skip_size
= 4 * entry_count
;
267 if (skip_size
> INT_MAX
)
270 RCHECK(reader
->SkipBytes(skip_size
));
275 SampleTable::SampleTable() {}
276 SampleTable::~SampleTable() {}
277 FourCC
SampleTable::BoxType() const { return FOURCC_STBL
; }
279 bool SampleTable::Parse(BoxReader
* reader
) {
280 return reader
->ScanChildren() &&
281 reader
->ReadChild(&description
) &&
282 reader
->MaybeReadChild(&sync_sample
);
285 EditList::EditList() {}
286 EditList::~EditList() {}
287 FourCC
EditList::BoxType() const { return FOURCC_ELST
; }
289 bool EditList::Parse(BoxReader
* reader
) {
291 RCHECK(reader
->ReadFullBoxHeader() && reader
->Read4(&count
));
293 if (reader
->version() == 1) {
294 RCHECK(reader
->HasBytes(count
* 20));
296 RCHECK(reader
->HasBytes(count
* 12));
300 for (std::vector
<EditListEntry
>::iterator edit
= edits
.begin();
301 edit
!= edits
.end(); ++edit
) {
302 if (reader
->version() == 1) {
303 RCHECK(reader
->Read8(&edit
->segment_duration
) &&
304 reader
->Read8s(&edit
->media_time
));
306 RCHECK(reader
->Read4Into8(&edit
->segment_duration
) &&
307 reader
->Read4sInto8s(&edit
->media_time
));
309 RCHECK(reader
->Read2s(&edit
->media_rate_integer
) &&
310 reader
->Read2s(&edit
->media_rate_fraction
));
317 FourCC
Edit::BoxType() const { return FOURCC_EDTS
; }
319 bool Edit::Parse(BoxReader
* reader
) {
320 return reader
->ScanChildren() && reader
->ReadChild(&list
);
323 HandlerReference::HandlerReference() : type(kInvalid
) {}
324 HandlerReference::~HandlerReference() {}
325 FourCC
HandlerReference::BoxType() const { return FOURCC_HDLR
; }
327 bool HandlerReference::Parse(BoxReader
* reader
) {
329 RCHECK(reader
->SkipBytes(8) && reader
->ReadFourCC(&hdlr_type
));
330 // Note: remaining fields in box ignored
331 if (hdlr_type
== FOURCC_VIDE
) {
333 } else if (hdlr_type
== FOURCC_SOUN
) {
341 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
343 profile_indication(0),
344 profile_compatibility(0),
348 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
349 FourCC
AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC
; }
351 bool AVCDecoderConfigurationRecord::Parse(BoxReader
* reader
) {
352 RCHECK(reader
->Read1(&version
) && version
== 1 &&
353 reader
->Read1(&profile_indication
) &&
354 reader
->Read1(&profile_compatibility
) &&
355 reader
->Read1(&avc_level
));
357 uint8 length_size_minus_one
;
358 RCHECK(reader
->Read1(&length_size_minus_one
) &&
359 (length_size_minus_one
& 0xfc) == 0xfc);
360 length_size
= (length_size_minus_one
& 0x3) + 1;
363 RCHECK(reader
->Read1(&num_sps
) && (num_sps
& 0xe0) == 0xe0);
366 sps_list
.resize(num_sps
);
367 for (int i
= 0; i
< num_sps
; i
++) {
369 RCHECK(reader
->Read2(&sps_length
) &&
370 reader
->ReadVec(&sps_list
[i
], sps_length
));
374 RCHECK(reader
->Read1(&num_pps
));
376 pps_list
.resize(num_pps
);
377 for (int i
= 0; i
< num_pps
; i
++) {
379 RCHECK(reader
->Read2(&pps_length
) &&
380 reader
->ReadVec(&pps_list
[i
], pps_length
));
386 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
387 PixelAspectRatioBox::~PixelAspectRatioBox() {}
388 FourCC
PixelAspectRatioBox::BoxType() const { return FOURCC_PASP
; }
390 bool PixelAspectRatioBox::Parse(BoxReader
* reader
) {
391 RCHECK(reader
->Read4(&h_spacing
) &&
392 reader
->Read4(&v_spacing
));
396 VideoSampleEntry::VideoSampleEntry()
397 : format(FOURCC_NULL
),
398 data_reference_index(0),
402 VideoSampleEntry::~VideoSampleEntry() {}
403 FourCC
VideoSampleEntry::BoxType() const {
404 DCHECK(false) << "VideoSampleEntry should be parsed according to the "
405 << "handler type recovered in its Media ancestor.";
409 bool VideoSampleEntry::Parse(BoxReader
* reader
) {
410 format
= reader
->type();
411 RCHECK(reader
->SkipBytes(6) &&
412 reader
->Read2(&data_reference_index
) &&
413 reader
->SkipBytes(16) &&
414 reader
->Read2(&width
) &&
415 reader
->Read2(&height
) &&
416 reader
->SkipBytes(50));
418 RCHECK(reader
->ScanChildren() &&
419 reader
->MaybeReadChild(&pixel_aspect
));
421 if (format
== FOURCC_ENCV
) {
422 // Continue scanning until a recognized protection scheme is found, or until
423 // we run out of protection schemes.
424 while (sinf
.type
.type
!= FOURCC_CENC
) {
425 if (!reader
->ReadChild(&sinf
))
431 RCHECK(reader
->ReadChild(&avcc
));
436 bool VideoSampleEntry::IsFormatValid() const {
437 return format
== FOURCC_AVC1
|| format
== FOURCC_AVC3
||
438 (format
== FOURCC_ENCV
&& (sinf
.format
.format
== FOURCC_AVC1
||
439 sinf
.format
.format
== FOURCC_AVC3
));
442 ElementaryStreamDescriptor::ElementaryStreamDescriptor()
443 : object_type(kForbidden
) {}
445 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
447 FourCC
ElementaryStreamDescriptor::BoxType() const {
451 bool ElementaryStreamDescriptor::Parse(BoxReader
* reader
) {
452 std::vector
<uint8
> data
;
453 ESDescriptor es_desc
;
455 RCHECK(reader
->ReadFullBoxHeader());
456 RCHECK(reader
->ReadVec(&data
, reader
->size() - reader
->pos()));
457 RCHECK(es_desc
.Parse(data
));
459 object_type
= es_desc
.object_type();
461 RCHECK(aac
.Parse(es_desc
.decoder_specific_info()));
466 AudioSampleEntry::AudioSampleEntry()
467 : format(FOURCC_NULL
),
468 data_reference_index(0),
473 AudioSampleEntry::~AudioSampleEntry() {}
475 FourCC
AudioSampleEntry::BoxType() const {
476 DCHECK(false) << "AudioSampleEntry should be parsed according to the "
477 << "handler type recovered in its Media ancestor.";
481 bool AudioSampleEntry::Parse(BoxReader
* reader
) {
482 format
= reader
->type();
483 RCHECK(reader
->SkipBytes(6) &&
484 reader
->Read2(&data_reference_index
) &&
485 reader
->SkipBytes(8) &&
486 reader
->Read2(&channelcount
) &&
487 reader
->Read2(&samplesize
) &&
488 reader
->SkipBytes(4) &&
489 reader
->Read4(&samplerate
));
490 // Convert from 16.16 fixed point to integer
493 RCHECK(reader
->ScanChildren());
494 if (format
== FOURCC_ENCA
) {
495 // Continue scanning until a recognized protection scheme is found, or until
496 // we run out of protection schemes.
497 while (sinf
.type
.type
!= FOURCC_CENC
) {
498 if (!reader
->ReadChild(&sinf
))
503 // ESDS is not valid in case of EAC3.
504 RCHECK(reader
->MaybeReadChild(&esds
));
508 MediaHeader::MediaHeader()
510 modification_time(0),
513 MediaHeader::~MediaHeader() {}
514 FourCC
MediaHeader::BoxType() const { return FOURCC_MDHD
; }
516 bool MediaHeader::Parse(BoxReader
* reader
) {
517 RCHECK(reader
->ReadFullBoxHeader());
519 if (reader
->version() == 1) {
520 RCHECK(reader
->Read8(&creation_time
) &&
521 reader
->Read8(&modification_time
) &&
522 reader
->Read4(×cale
) &&
523 reader
->Read8(&duration
));
525 RCHECK(reader
->Read4Into8(&creation_time
) &&
526 reader
->Read4Into8(&modification_time
) &&
527 reader
->Read4(×cale
) &&
528 reader
->Read4Into8(&duration
));
530 // Skip language information
531 return reader
->SkipBytes(4);
534 MediaInformation::MediaInformation() {}
535 MediaInformation::~MediaInformation() {}
536 FourCC
MediaInformation::BoxType() const { return FOURCC_MINF
; }
538 bool MediaInformation::Parse(BoxReader
* reader
) {
539 return reader
->ScanChildren() &&
540 reader
->ReadChild(&sample_table
);
545 FourCC
Media::BoxType() const { return FOURCC_MDIA
; }
547 bool Media::Parse(BoxReader
* reader
) {
548 RCHECK(reader
->ScanChildren() &&
549 reader
->ReadChild(&header
) &&
550 reader
->ReadChild(&handler
));
552 // Maddeningly, the HandlerReference box specifies how to parse the
553 // SampleDescription box, making the latter the only box (of those that we
554 // support) which cannot be parsed correctly on its own (or even with
555 // information from its strict ancestor tree). We thus copy the handler type
556 // to the sample description box *before* parsing it to provide this
557 // information while parsing.
558 information
.sample_table
.description
.type
= handler
.type
;
559 RCHECK(reader
->ReadChild(&information
));
565 FourCC
Track::BoxType() const { return FOURCC_TRAK
; }
567 bool Track::Parse(BoxReader
* reader
) {
568 RCHECK(reader
->ScanChildren() &&
569 reader
->ReadChild(&header
) &&
570 reader
->ReadChild(&media
) &&
571 reader
->MaybeReadChild(&edit
));
575 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
576 MovieExtendsHeader::~MovieExtendsHeader() {}
577 FourCC
MovieExtendsHeader::BoxType() const { return FOURCC_MEHD
; }
579 bool MovieExtendsHeader::Parse(BoxReader
* reader
) {
580 RCHECK(reader
->ReadFullBoxHeader());
581 if (reader
->version() == 1) {
582 RCHECK(reader
->Read8(&fragment_duration
));
584 RCHECK(reader
->Read4Into8(&fragment_duration
));
589 TrackExtends::TrackExtends()
591 default_sample_description_index(0),
592 default_sample_duration(0),
593 default_sample_size(0),
594 default_sample_flags(0) {}
595 TrackExtends::~TrackExtends() {}
596 FourCC
TrackExtends::BoxType() const { return FOURCC_TREX
; }
598 bool TrackExtends::Parse(BoxReader
* reader
) {
599 RCHECK(reader
->ReadFullBoxHeader() &&
600 reader
->Read4(&track_id
) &&
601 reader
->Read4(&default_sample_description_index
) &&
602 reader
->Read4(&default_sample_duration
) &&
603 reader
->Read4(&default_sample_size
) &&
604 reader
->Read4(&default_sample_flags
));
608 MovieExtends::MovieExtends() {}
609 MovieExtends::~MovieExtends() {}
610 FourCC
MovieExtends::BoxType() const { return FOURCC_MVEX
; }
612 bool MovieExtends::Parse(BoxReader
* reader
) {
613 header
.fragment_duration
= 0;
614 return reader
->ScanChildren() &&
615 reader
->MaybeReadChild(&header
) &&
616 reader
->ReadChildren(&tracks
);
619 Movie::Movie() : fragmented(false) {}
621 FourCC
Movie::BoxType() const { return FOURCC_MOOV
; }
623 bool Movie::Parse(BoxReader
* reader
) {
624 return reader
->ScanChildren() &&
625 reader
->ReadChild(&header
) &&
626 reader
->ReadChildren(&tracks
) &&
627 // Media Source specific: 'mvex' required
628 reader
->ReadChild(&extends
) &&
629 reader
->MaybeReadChildren(&pssh
);
632 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
633 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
634 FourCC
TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT
; }
636 bool TrackFragmentDecodeTime::Parse(BoxReader
* reader
) {
637 RCHECK(reader
->ReadFullBoxHeader());
638 if (reader
->version() == 1)
639 return reader
->Read8(&decode_time
);
641 return reader
->Read4Into8(&decode_time
);
644 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
645 MovieFragmentHeader::~MovieFragmentHeader() {}
646 FourCC
MovieFragmentHeader::BoxType() const { return FOURCC_MFHD
; }
648 bool MovieFragmentHeader::Parse(BoxReader
* reader
) {
649 return reader
->SkipBytes(4) && reader
->Read4(&sequence_number
);
652 TrackFragmentHeader::TrackFragmentHeader()
654 sample_description_index(0),
655 default_sample_duration(0),
656 default_sample_size(0),
657 default_sample_flags(0),
658 has_default_sample_flags(false) {}
660 TrackFragmentHeader::~TrackFragmentHeader() {}
661 FourCC
TrackFragmentHeader::BoxType() const { return FOURCC_TFHD
; }
663 bool TrackFragmentHeader::Parse(BoxReader
* reader
) {
664 RCHECK(reader
->ReadFullBoxHeader() && reader
->Read4(&track_id
));
666 // Media Source specific: reject tracks that set 'base-data-offset-present'.
667 // Although the Media Source requires that 'default-base-is-moof' (14496-12
668 // Amendment 2) be set, we omit this check as many otherwise-valid files in
669 // the wild don't set it.
671 // RCHECK((flags & 0x020000) && !(flags & 0x1));
672 RCHECK(!(reader
->flags() & 0x1));
674 if (reader
->flags() & 0x2) {
675 RCHECK(reader
->Read4(&sample_description_index
));
677 sample_description_index
= 0;
680 if (reader
->flags() & 0x8) {
681 RCHECK(reader
->Read4(&default_sample_duration
));
683 default_sample_duration
= 0;
686 if (reader
->flags() & 0x10) {
687 RCHECK(reader
->Read4(&default_sample_size
));
689 default_sample_size
= 0;
692 if (reader
->flags() & 0x20) {
693 RCHECK(reader
->Read4(&default_sample_flags
));
694 has_default_sample_flags
= true;
696 has_default_sample_flags
= false;
702 TrackFragmentRun::TrackFragmentRun()
703 : sample_count(0), data_offset(0) {}
704 TrackFragmentRun::~TrackFragmentRun() {}
705 FourCC
TrackFragmentRun::BoxType() const { return FOURCC_TRUN
; }
707 bool TrackFragmentRun::Parse(BoxReader
* reader
) {
708 RCHECK(reader
->ReadFullBoxHeader() &&
709 reader
->Read4(&sample_count
));
710 const uint32 flags
= reader
->flags();
712 bool data_offset_present
= (flags
& 0x1) != 0;
713 bool first_sample_flags_present
= (flags
& 0x4) != 0;
714 bool sample_duration_present
= (flags
& 0x100) != 0;
715 bool sample_size_present
= (flags
& 0x200) != 0;
716 bool sample_flags_present
= (flags
& 0x400) != 0;
717 bool sample_composition_time_offsets_present
= (flags
& 0x800) != 0;
719 if (data_offset_present
) {
720 RCHECK(reader
->Read4(&data_offset
));
725 uint32 first_sample_flags
;
726 if (first_sample_flags_present
)
727 RCHECK(reader
->Read4(&first_sample_flags
));
729 int fields
= sample_duration_present
+ sample_size_present
+
730 sample_flags_present
+ sample_composition_time_offsets_present
;
731 RCHECK(reader
->HasBytes(fields
* sample_count
));
733 if (sample_duration_present
)
734 sample_durations
.resize(sample_count
);
735 if (sample_size_present
)
736 sample_sizes
.resize(sample_count
);
737 if (sample_flags_present
)
738 sample_flags
.resize(sample_count
);
739 if (sample_composition_time_offsets_present
)
740 sample_composition_time_offsets
.resize(sample_count
);
742 for (uint32 i
= 0; i
< sample_count
; ++i
) {
743 if (sample_duration_present
)
744 RCHECK(reader
->Read4(&sample_durations
[i
]));
745 if (sample_size_present
)
746 RCHECK(reader
->Read4(&sample_sizes
[i
]));
747 if (sample_flags_present
)
748 RCHECK(reader
->Read4(&sample_flags
[i
]));
749 if (sample_composition_time_offsets_present
)
750 RCHECK(reader
->Read4s(&sample_composition_time_offsets
[i
]));
753 if (first_sample_flags_present
) {
754 if (sample_flags
.size() == 0) {
755 sample_flags
.push_back(first_sample_flags
);
757 sample_flags
[0] = first_sample_flags
;
763 TrackFragment::TrackFragment() {}
764 TrackFragment::~TrackFragment() {}
765 FourCC
TrackFragment::BoxType() const { return FOURCC_TRAF
; }
767 bool TrackFragment::Parse(BoxReader
* reader
) {
768 return reader
->ScanChildren() &&
769 reader
->ReadChild(&header
) &&
770 // Media Source specific: 'tfdt' required
771 reader
->ReadChild(&decode_time
) &&
772 reader
->MaybeReadChildren(&runs
) &&
773 reader
->MaybeReadChild(&auxiliary_offset
) &&
774 reader
->MaybeReadChild(&auxiliary_size
) &&
775 reader
->MaybeReadChild(&sdtp
);
778 MovieFragment::MovieFragment() {}
779 MovieFragment::~MovieFragment() {}
780 FourCC
MovieFragment::BoxType() const { return FOURCC_MOOF
; }
782 bool MovieFragment::Parse(BoxReader
* reader
) {
783 RCHECK(reader
->ScanChildren() &&
784 reader
->ReadChild(&header
) &&
785 reader
->ReadChildren(&tracks
) &&
786 reader
->MaybeReadChildren(&pssh
));
790 IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
791 IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
792 FourCC
IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP
; }
794 bool IndependentAndDisposableSamples::Parse(BoxReader
* reader
) {
795 RCHECK(reader
->ReadFullBoxHeader());
796 RCHECK(reader
->version() == 0);
797 RCHECK(reader
->flags() == 0);
799 int sample_count
= reader
->size() - reader
->pos();
800 sample_depends_on_
.resize(sample_count
);
801 for (int i
= 0; i
< sample_count
; ++i
) {
803 RCHECK(reader
->Read1(&sample_info
));
804 RCHECK((sample_info
>> 6) == 0); // reserved.
806 sample_depends_on_
[i
] =
807 static_cast<SampleDependsOn
>((sample_info
>> 4) & 0x3);
809 RCHECK(sample_depends_on_
[i
] != kSampleDependsOnReserved
);
815 SampleDependsOn
IndependentAndDisposableSamples::sample_depends_on(
817 if (i
>= sample_depends_on_
.size())
818 return kSampleDependsOnUnknown
;
820 return sample_depends_on_
[i
];