Add explicit |forceOnlineSignin| to user pod status
[chromium-blink-merge.git] / media / mp4 / box_definitions.cc
blob6ceda304b8e01d3d9f4b41c7d71d595405d079e9
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"
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 uint32 size;
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());
39 return true;
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));
51 uint32 count;
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]));
59 } else {
60 RCHECK(reader->Read4Into8(&offsets[i]));
63 return true;
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);
81 return true;
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));
100 return true;
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) {
110 uint8 flag;
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);
117 if (is_encrypted) {
118 RCHECK(default_iv_size == 8 || default_iv_size == 16);
119 } else {
120 RCHECK(default_iv_size == 0);
122 return true;
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.
147 return true;
150 MovieHeader::MovieHeader()
151 : creation_time(0),
152 modification_time(0),
153 timescale(0),
154 duration(0),
155 rate(-1),
156 volume(-1),
157 next_track_id(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(&timescale) &&
168 reader->Read8(&duration));
169 } else {
170 RCHECK(reader->Read4Into8(&creation_time) &&
171 reader->Read4Into8(&modification_time) &&
172 reader->Read4(&timescale) &&
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));
182 return true;
185 TrackHeader::TrackHeader()
186 : creation_time(0),
187 modification_time(0),
188 track_id(0),
189 duration(0),
190 layer(-1),
191 alternate_group(-1),
192 volume(-1),
193 width(0),
194 height(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));
206 } else {
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));
222 width >>= 16;
223 height >>= 16;
224 return true;
227 SampleDescription::SampleDescription() : type(kInvalid) {}
228 SampleDescription::~SampleDescription() {}
229 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
231 bool SampleDescription::Parse(BoxReader* reader) {
232 uint32 count;
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));
245 return true;
248 SyncSample::SyncSample() : is_present(false) {}
249 SyncSample::~SyncSample() {}
250 FourCC SyncSample::BoxType() const { return FOURCC_STSS; }
252 bool SyncSample::Parse(BoxReader* reader) {
253 uint32 entry_count;
254 RCHECK(reader->ReadFullBoxHeader() &&
255 reader->Read4(&entry_count));
257 is_present = true;
259 if (entry_count == 0)
260 return true;
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)
268 return false;
270 RCHECK(reader->SkipBytes(skip_size));
272 return true;
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) {
290 uint32 count;
291 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count));
293 if (reader->version() == 1) {
294 RCHECK(reader->HasBytes(count * 20));
295 } else {
296 RCHECK(reader->HasBytes(count * 12));
298 edits.resize(count);
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));
305 } else {
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));
312 return true;
315 Edit::Edit() {}
316 Edit::~Edit() {}
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) {
328 FourCC hdlr_type;
329 RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type));
330 // Note: remaining fields in box ignored
331 if (hdlr_type == FOURCC_VIDE) {
332 type = kVideo;
333 } else if (hdlr_type == FOURCC_SOUN) {
334 type = kAudio;
335 } else {
336 type = kInvalid;
338 return true;
341 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
342 : version(0),
343 profile_indication(0),
344 profile_compatibility(0),
345 avc_level(0),
346 length_size(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;
362 uint8 num_sps;
363 RCHECK(reader->Read1(&num_sps) && (num_sps & 0xe0) == 0xe0);
364 num_sps &= 0x1f;
366 sps_list.resize(num_sps);
367 for (int i = 0; i < num_sps; i++) {
368 uint16 sps_length;
369 RCHECK(reader->Read2(&sps_length) &&
370 reader->ReadVec(&sps_list[i], sps_length));
373 uint8 num_pps;
374 RCHECK(reader->Read1(&num_pps));
376 pps_list.resize(num_pps);
377 for (int i = 0; i < num_pps; i++) {
378 uint16 pps_length;
379 RCHECK(reader->Read2(&pps_length) &&
380 reader->ReadVec(&pps_list[i], pps_length));
383 return true;
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));
393 return true;
396 VideoSampleEntry::VideoSampleEntry()
397 : format(FOURCC_NULL),
398 data_reference_index(0),
399 width(0),
400 height(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.";
406 return FOURCC_NULL;
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))
426 return false;
430 if (IsFormatValid())
431 RCHECK(reader->ReadChild(&avcc));
433 return true;
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 {
448 return FOURCC_ESDS;
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()));
463 return true;
466 AudioSampleEntry::AudioSampleEntry()
467 : format(FOURCC_NULL),
468 data_reference_index(0),
469 channelcount(0),
470 samplesize(0),
471 samplerate(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.";
478 return FOURCC_NULL;
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
491 samplerate >>= 16;
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))
499 return false;
503 // ESDS is not valid in case of EAC3.
504 RCHECK(reader->MaybeReadChild(&esds));
505 return true;
508 MediaHeader::MediaHeader()
509 : creation_time(0),
510 modification_time(0),
511 timescale(0),
512 duration(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(&timescale) &&
523 reader->Read8(&duration));
524 } else {
525 RCHECK(reader->Read4Into8(&creation_time) &&
526 reader->Read4Into8(&modification_time) &&
527 reader->Read4(&timescale) &&
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);
543 Media::Media() {}
544 Media::~Media() {}
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));
560 return true;
563 Track::Track() {}
564 Track::~Track() {}
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));
572 return true;
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));
583 } else {
584 RCHECK(reader->Read4Into8(&fragment_duration));
586 return true;
589 TrackExtends::TrackExtends()
590 : track_id(0),
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));
605 return true;
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) {}
620 Movie::~Movie() {}
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);
640 else
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()
653 : track_id(0),
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));
676 } else {
677 sample_description_index = 0;
680 if (reader->flags() & 0x8) {
681 RCHECK(reader->Read4(&default_sample_duration));
682 } else {
683 default_sample_duration = 0;
686 if (reader->flags() & 0x10) {
687 RCHECK(reader->Read4(&default_sample_size));
688 } else {
689 default_sample_size = 0;
692 if (reader->flags() & 0x20) {
693 RCHECK(reader->Read4(&default_sample_flags));
694 has_default_sample_flags = true;
695 } else {
696 has_default_sample_flags = false;
699 return true;
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));
721 } else {
722 data_offset = 0;
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);
756 } else {
757 sample_flags[0] = first_sample_flags;
760 return true;
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));
787 return true;
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) {
802 uint8 sample_info;
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);
812 return true;
815 SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
816 size_t i) const {
817 if (i >= sample_depends_on_.size())
818 return kSampleDependsOnUnknown;
820 return sample_depends_on_[i];
823 } // namespace mp4
824 } // namespace media