- add sources.
[platform/framework/web/crosswalk.git] / src / media / mp4 / box_definitions.cc
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.
4
5 #include "media/mp4/box_definitions.h"
6
7 #include "base/logging.h"
8 #include "media/mp4/es_descriptor.h"
9 #include "media/mp4/rcheck.h"
10
11 namespace media {
12 namespace mp4 {
13
14 FileType::FileType() {}
15 FileType::~FileType() {}
16 FourCC FileType::BoxType() const { return FOURCC_FTYP; }
17
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
22 }
23
24 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
25 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
26 FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; }
27
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));
35
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;
40 }
41
42 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
43 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
44 FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; }
45
46 bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) {
47   RCHECK(reader->ReadFullBoxHeader());
48   if (reader->flags() & 1)
49     RCHECK(reader->SkipBytes(8));
50
51   uint32 count;
52   RCHECK(reader->Read4(&count) &&
53          reader->HasBytes(count * (reader->version() == 1 ? 8 : 4)));
54   offsets.resize(count);
55
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]));
61     }
62   }
63   return true;
64 }
65
66 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
67   : default_sample_info_size(0), sample_count(0) {
68 }
69 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
70 FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; }
71
72 bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) {
73   RCHECK(reader->ReadFullBoxHeader());
74   if (reader->flags() & 1)
75     RCHECK(reader->SkipBytes(8));
76
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;
82 }
83
84 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
85 OriginalFormat::~OriginalFormat() {}
86 FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; }
87
88 bool OriginalFormat::Parse(BoxReader* reader) {
89   return reader->ReadFourCC(&format);
90 }
91
92 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
93 SchemeType::~SchemeType() {}
94 FourCC SchemeType::BoxType() const { return FOURCC_SCHM; }
95
96 bool SchemeType::Parse(BoxReader* reader) {
97   RCHECK(reader->ReadFullBoxHeader() &&
98          reader->ReadFourCC(&type) &&
99          reader->Read4(&version));
100   return true;
101 }
102
103 TrackEncryption::TrackEncryption()
104   : is_encrypted(false), default_iv_size(0) {
105 }
106 TrackEncryption::~TrackEncryption() {}
107 FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; }
108
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);
121   }
122   return true;
123 }
124
125 SchemeInfo::SchemeInfo() {}
126 SchemeInfo::~SchemeInfo() {}
127 FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; }
128
129 bool SchemeInfo::Parse(BoxReader* reader) {
130   return reader->ScanChildren() && reader->ReadChild(&track_encryption);
131 }
132
133 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
134 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
135 FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; }
136
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;
148 }
149
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; }
160
161 bool MovieHeader::Parse(BoxReader* reader) {
162   RCHECK(reader->ReadFullBoxHeader());
163
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));
174   }
175
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;
183 }
184
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; }
197
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));
212   }
213
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;
225 }
226
227 SampleDescription::SampleDescription() : type(kInvalid) {}
228 SampleDescription::~SampleDescription() {}
229 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
230
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();
237
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));
244   }
245   return true;
246 }
247
248 SampleTable::SampleTable() {}
249 SampleTable::~SampleTable() {}
250 FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
251
252 bool SampleTable::Parse(BoxReader* reader) {
253   return reader->ScanChildren() &&
254          reader->ReadChild(&description);
255 }
256
257 EditList::EditList() {}
258 EditList::~EditList() {}
259 FourCC EditList::BoxType() const { return FOURCC_ELST; }
260
261 bool EditList::Parse(BoxReader* reader) {
262   uint32 count;
263   RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count));
264
265   if (reader->version() == 1) {
266     RCHECK(reader->HasBytes(count * 20));
267   } else {
268     RCHECK(reader->HasBytes(count * 12));
269   }
270   edits.resize(count);
271
272   for (std::vector<EditListEntry>::iterator edit = edits.begin();
273        edit != edits.end(); ++edit) {
274     if (reader->version() == 1) {
275       RCHECK(reader->Read8(&edit->segment_duration) &&
276              reader->Read8s(&edit->media_time));
277     } else {
278       RCHECK(reader->Read4Into8(&edit->segment_duration) &&
279              reader->Read4sInto8s(&edit->media_time));
280     }
281     RCHECK(reader->Read2s(&edit->media_rate_integer) &&
282            reader->Read2s(&edit->media_rate_fraction));
283   }
284   return true;
285 }
286
287 Edit::Edit() {}
288 Edit::~Edit() {}
289 FourCC Edit::BoxType() const { return FOURCC_EDTS; }
290
291 bool Edit::Parse(BoxReader* reader) {
292   return reader->ScanChildren() && reader->ReadChild(&list);
293 }
294
295 HandlerReference::HandlerReference() : type(kInvalid) {}
296 HandlerReference::~HandlerReference() {}
297 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
298
299 bool HandlerReference::Parse(BoxReader* reader) {
300   FourCC hdlr_type;
301   RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type));
302   // Note: remaining fields in box ignored
303   if (hdlr_type == FOURCC_VIDE) {
304     type = kVideo;
305   } else if (hdlr_type == FOURCC_SOUN) {
306     type = kAudio;
307   } else {
308     type = kInvalid;
309   }
310   return true;
311 }
312
313 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
314     : version(0),
315       profile_indication(0),
316       profile_compatibility(0),
317       avc_level(0),
318       length_size(0) {}
319
320 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
321 FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
322
323 bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
324   RCHECK(reader->Read1(&version) && version == 1 &&
325          reader->Read1(&profile_indication) &&
326          reader->Read1(&profile_compatibility) &&
327          reader->Read1(&avc_level));
328
329   uint8 length_size_minus_one;
330   RCHECK(reader->Read1(&length_size_minus_one) &&
331          (length_size_minus_one & 0xfc) == 0xfc);
332   length_size = (length_size_minus_one & 0x3) + 1;
333
334   uint8 num_sps;
335   RCHECK(reader->Read1(&num_sps) && (num_sps & 0xe0) == 0xe0);
336   num_sps &= 0x1f;
337
338   sps_list.resize(num_sps);
339   for (int i = 0; i < num_sps; i++) {
340     uint16 sps_length;
341     RCHECK(reader->Read2(&sps_length) &&
342            reader->ReadVec(&sps_list[i], sps_length));
343   }
344
345   uint8 num_pps;
346   RCHECK(reader->Read1(&num_pps));
347
348   pps_list.resize(num_pps);
349   for (int i = 0; i < num_pps; i++) {
350     uint16 pps_length;
351     RCHECK(reader->Read2(&pps_length) &&
352            reader->ReadVec(&pps_list[i], pps_length));
353   }
354
355   return true;
356 }
357
358 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
359 PixelAspectRatioBox::~PixelAspectRatioBox() {}
360 FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
361
362 bool PixelAspectRatioBox::Parse(BoxReader* reader) {
363   RCHECK(reader->Read4(&h_spacing) &&
364          reader->Read4(&v_spacing));
365   return true;
366 }
367
368 VideoSampleEntry::VideoSampleEntry()
369     : format(FOURCC_NULL),
370       data_reference_index(0),
371       width(0),
372       height(0) {}
373
374 VideoSampleEntry::~VideoSampleEntry() {}
375 FourCC VideoSampleEntry::BoxType() const {
376   DCHECK(false) << "VideoSampleEntry should be parsed according to the "
377                 << "handler type recovered in its Media ancestor.";
378   return FOURCC_NULL;
379 }
380
381 bool VideoSampleEntry::Parse(BoxReader* reader) {
382   format = reader->type();
383   RCHECK(reader->SkipBytes(6) &&
384          reader->Read2(&data_reference_index) &&
385          reader->SkipBytes(16) &&
386          reader->Read2(&width) &&
387          reader->Read2(&height) &&
388          reader->SkipBytes(50));
389
390   RCHECK(reader->ScanChildren() &&
391          reader->MaybeReadChild(&pixel_aspect));
392
393   if (format == FOURCC_ENCV) {
394     // Continue scanning until a recognized protection scheme is found, or until
395     // we run out of protection schemes.
396     while (sinf.type.type != FOURCC_CENC) {
397       if (!reader->ReadChild(&sinf))
398         return false;
399     }
400   }
401
402   if (IsFormatValid())
403     RCHECK(reader->ReadChild(&avcc));
404
405   return true;
406 }
407
408 bool VideoSampleEntry::IsFormatValid() const {
409   return format == FOURCC_AVC1 || format == FOURCC_AVC3 ||
410       (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 ||
411                                  sinf.format.format == FOURCC_AVC3));
412 }
413
414 ElementaryStreamDescriptor::ElementaryStreamDescriptor()
415     : object_type(kForbidden) {}
416
417 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
418
419 FourCC ElementaryStreamDescriptor::BoxType() const {
420   return FOURCC_ESDS;
421 }
422
423 bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {
424   std::vector<uint8> data;
425   ESDescriptor es_desc;
426
427   RCHECK(reader->ReadFullBoxHeader());
428   RCHECK(reader->ReadVec(&data, reader->size() - reader->pos()));
429   RCHECK(es_desc.Parse(data));
430
431   object_type = es_desc.object_type();
432
433   RCHECK(aac.Parse(es_desc.decoder_specific_info()));
434
435   return true;
436 }
437
438 AudioSampleEntry::AudioSampleEntry()
439     : format(FOURCC_NULL),
440       data_reference_index(0),
441       channelcount(0),
442       samplesize(0),
443       samplerate(0) {}
444
445 AudioSampleEntry::~AudioSampleEntry() {}
446
447 FourCC AudioSampleEntry::BoxType() const {
448   DCHECK(false) << "AudioSampleEntry should be parsed according to the "
449                 << "handler type recovered in its Media ancestor.";
450   return FOURCC_NULL;
451 }
452
453 bool AudioSampleEntry::Parse(BoxReader* reader) {
454   format = reader->type();
455   RCHECK(reader->SkipBytes(6) &&
456          reader->Read2(&data_reference_index) &&
457          reader->SkipBytes(8) &&
458          reader->Read2(&channelcount) &&
459          reader->Read2(&samplesize) &&
460          reader->SkipBytes(4) &&
461          reader->Read4(&samplerate));
462   // Convert from 16.16 fixed point to integer
463   samplerate >>= 16;
464
465   RCHECK(reader->ScanChildren());
466   if (format == FOURCC_ENCA) {
467     // Continue scanning until a recognized protection scheme is found, or until
468     // we run out of protection schemes.
469     while (sinf.type.type != FOURCC_CENC) {
470       if (!reader->ReadChild(&sinf))
471         return false;
472     }
473   }
474
475   // ESDS is not valid in case of EAC3.
476   RCHECK(reader->MaybeReadChild(&esds));
477   return true;
478 }
479
480 MediaHeader::MediaHeader()
481     : creation_time(0),
482       modification_time(0),
483       timescale(0),
484       duration(0) {}
485 MediaHeader::~MediaHeader() {}
486 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
487
488 bool MediaHeader::Parse(BoxReader* reader) {
489   RCHECK(reader->ReadFullBoxHeader());
490
491   if (reader->version() == 1) {
492     RCHECK(reader->Read8(&creation_time) &&
493            reader->Read8(&modification_time) &&
494            reader->Read4(&timescale) &&
495            reader->Read8(&duration));
496   } else {
497     RCHECK(reader->Read4Into8(&creation_time) &&
498            reader->Read4Into8(&modification_time) &&
499            reader->Read4(&timescale) &&
500            reader->Read4Into8(&duration));
501   }
502   // Skip language information
503   return reader->SkipBytes(4);
504 }
505
506 MediaInformation::MediaInformation() {}
507 MediaInformation::~MediaInformation() {}
508 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
509
510 bool MediaInformation::Parse(BoxReader* reader) {
511   return reader->ScanChildren() &&
512          reader->ReadChild(&sample_table);
513 }
514
515 Media::Media() {}
516 Media::~Media() {}
517 FourCC Media::BoxType() const { return FOURCC_MDIA; }
518
519 bool Media::Parse(BoxReader* reader) {
520   RCHECK(reader->ScanChildren() &&
521          reader->ReadChild(&header) &&
522          reader->ReadChild(&handler));
523
524   // Maddeningly, the HandlerReference box specifies how to parse the
525   // SampleDescription box, making the latter the only box (of those that we
526   // support) which cannot be parsed correctly on its own (or even with
527   // information from its strict ancestor tree). We thus copy the handler type
528   // to the sample description box *before* parsing it to provide this
529   // information while parsing.
530   information.sample_table.description.type = handler.type;
531   RCHECK(reader->ReadChild(&information));
532   return true;
533 }
534
535 Track::Track() {}
536 Track::~Track() {}
537 FourCC Track::BoxType() const { return FOURCC_TRAK; }
538
539 bool Track::Parse(BoxReader* reader) {
540   RCHECK(reader->ScanChildren() &&
541          reader->ReadChild(&header) &&
542          reader->ReadChild(&media) &&
543          reader->MaybeReadChild(&edit));
544   return true;
545 }
546
547 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
548 MovieExtendsHeader::~MovieExtendsHeader() {}
549 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
550
551 bool MovieExtendsHeader::Parse(BoxReader* reader) {
552   RCHECK(reader->ReadFullBoxHeader());
553   if (reader->version() == 1) {
554     RCHECK(reader->Read8(&fragment_duration));
555   } else {
556     RCHECK(reader->Read4Into8(&fragment_duration));
557   }
558   return true;
559 }
560
561 TrackExtends::TrackExtends()
562     : track_id(0),
563       default_sample_description_index(0),
564       default_sample_duration(0),
565       default_sample_size(0),
566       default_sample_flags(0) {}
567 TrackExtends::~TrackExtends() {}
568 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
569
570 bool TrackExtends::Parse(BoxReader* reader) {
571   RCHECK(reader->ReadFullBoxHeader() &&
572          reader->Read4(&track_id) &&
573          reader->Read4(&default_sample_description_index) &&
574          reader->Read4(&default_sample_duration) &&
575          reader->Read4(&default_sample_size) &&
576          reader->Read4(&default_sample_flags));
577   return true;
578 }
579
580 MovieExtends::MovieExtends() {}
581 MovieExtends::~MovieExtends() {}
582 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
583
584 bool MovieExtends::Parse(BoxReader* reader) {
585   header.fragment_duration = 0;
586   return reader->ScanChildren() &&
587          reader->MaybeReadChild(&header) &&
588          reader->ReadChildren(&tracks);
589 }
590
591 Movie::Movie() : fragmented(false) {}
592 Movie::~Movie() {}
593 FourCC Movie::BoxType() const { return FOURCC_MOOV; }
594
595 bool Movie::Parse(BoxReader* reader) {
596   return reader->ScanChildren() &&
597          reader->ReadChild(&header) &&
598          reader->ReadChildren(&tracks) &&
599          // Media Source specific: 'mvex' required
600          reader->ReadChild(&extends) &&
601          reader->MaybeReadChildren(&pssh);
602 }
603
604 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
605 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
606 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
607
608 bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {
609   RCHECK(reader->ReadFullBoxHeader());
610   if (reader->version() == 1)
611     return reader->Read8(&decode_time);
612   else
613     return reader->Read4Into8(&decode_time);
614 }
615
616 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
617 MovieFragmentHeader::~MovieFragmentHeader() {}
618 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
619
620 bool MovieFragmentHeader::Parse(BoxReader* reader) {
621   return reader->SkipBytes(4) && reader->Read4(&sequence_number);
622 }
623
624 TrackFragmentHeader::TrackFragmentHeader()
625     : track_id(0),
626       sample_description_index(0),
627       default_sample_duration(0),
628       default_sample_size(0),
629       default_sample_flags(0),
630       has_default_sample_flags(false) {}
631
632 TrackFragmentHeader::~TrackFragmentHeader() {}
633 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
634
635 bool TrackFragmentHeader::Parse(BoxReader* reader) {
636   RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id));
637
638   // Media Source specific: reject tracks that set 'base-data-offset-present'.
639   // Although the Media Source requires that 'default-base-is-moof' (14496-12
640   // Amendment 2) be set, we omit this check as many otherwise-valid files in
641   // the wild don't set it.
642   //
643   //  RCHECK((flags & 0x020000) && !(flags & 0x1));
644   RCHECK(!(reader->flags() & 0x1));
645
646   if (reader->flags() & 0x2) {
647     RCHECK(reader->Read4(&sample_description_index));
648   } else {
649     sample_description_index = 0;
650   }
651
652   if (reader->flags() & 0x8) {
653     RCHECK(reader->Read4(&default_sample_duration));
654   } else {
655     default_sample_duration = 0;
656   }
657
658   if (reader->flags() & 0x10) {
659     RCHECK(reader->Read4(&default_sample_size));
660   } else {
661     default_sample_size = 0;
662   }
663
664   if (reader->flags() & 0x20) {
665     RCHECK(reader->Read4(&default_sample_flags));
666     has_default_sample_flags = true;
667   } else {
668     has_default_sample_flags = false;
669   }
670
671   return true;
672 }
673
674 TrackFragmentRun::TrackFragmentRun()
675     : sample_count(0), data_offset(0) {}
676 TrackFragmentRun::~TrackFragmentRun() {}
677 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
678
679 bool TrackFragmentRun::Parse(BoxReader* reader) {
680   RCHECK(reader->ReadFullBoxHeader() &&
681          reader->Read4(&sample_count));
682   const uint32 flags = reader->flags();
683
684   bool data_offset_present = (flags & 0x1) != 0;
685   bool first_sample_flags_present = (flags & 0x4) != 0;
686   bool sample_duration_present = (flags & 0x100) != 0;
687   bool sample_size_present = (flags & 0x200) != 0;
688   bool sample_flags_present = (flags & 0x400) != 0;
689   bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
690
691   if (data_offset_present) {
692     RCHECK(reader->Read4(&data_offset));
693   } else {
694     data_offset = 0;
695   }
696
697   uint32 first_sample_flags;
698   if (first_sample_flags_present)
699     RCHECK(reader->Read4(&first_sample_flags));
700
701   int fields = sample_duration_present + sample_size_present +
702       sample_flags_present + sample_composition_time_offsets_present;
703   RCHECK(reader->HasBytes(fields * sample_count));
704
705   if (sample_duration_present)
706     sample_durations.resize(sample_count);
707   if (sample_size_present)
708     sample_sizes.resize(sample_count);
709   if (sample_flags_present)
710     sample_flags.resize(sample_count);
711   if (sample_composition_time_offsets_present)
712     sample_composition_time_offsets.resize(sample_count);
713
714   for (uint32 i = 0; i < sample_count; ++i) {
715     if (sample_duration_present)
716       RCHECK(reader->Read4(&sample_durations[i]));
717     if (sample_size_present)
718       RCHECK(reader->Read4(&sample_sizes[i]));
719     if (sample_flags_present)
720       RCHECK(reader->Read4(&sample_flags[i]));
721     if (sample_composition_time_offsets_present)
722       RCHECK(reader->Read4s(&sample_composition_time_offsets[i]));
723   }
724
725   if (first_sample_flags_present) {
726     if (sample_flags.size() == 0) {
727       sample_flags.push_back(first_sample_flags);
728     } else {
729       sample_flags[0] = first_sample_flags;
730     }
731   }
732   return true;
733 }
734
735 TrackFragment::TrackFragment() {}
736 TrackFragment::~TrackFragment() {}
737 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
738
739 bool TrackFragment::Parse(BoxReader* reader) {
740   return reader->ScanChildren() &&
741          reader->ReadChild(&header) &&
742          // Media Source specific: 'tfdt' required
743          reader->ReadChild(&decode_time) &&
744          reader->MaybeReadChildren(&runs) &&
745          reader->MaybeReadChild(&auxiliary_offset) &&
746          reader->MaybeReadChild(&auxiliary_size) &&
747          reader->MaybeReadChild(&sdtp);
748 }
749
750 MovieFragment::MovieFragment() {}
751 MovieFragment::~MovieFragment() {}
752 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
753
754 bool MovieFragment::Parse(BoxReader* reader) {
755   RCHECK(reader->ScanChildren() &&
756          reader->ReadChild(&header) &&
757          reader->ReadChildren(&tracks) &&
758          reader->MaybeReadChildren(&pssh));
759   return true;
760 }
761
762 IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
763 IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
764 FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; }
765
766 bool IndependentAndDisposableSamples::Parse(BoxReader* reader) {
767   RCHECK(reader->ReadFullBoxHeader());
768   RCHECK(reader->version() == 0);
769   RCHECK(reader->flags() == 0);
770
771   int sample_count = reader->size() - reader->pos();
772   sample_depends_on_.resize(sample_count);
773   for (int i = 0; i < sample_count; ++i) {
774     uint8 sample_info;
775     RCHECK(reader->Read1(&sample_info));
776     RCHECK((sample_info >> 6) == 0);  // reserved.
777
778     sample_depends_on_[i] =
779         static_cast<SampleDependsOn>((sample_info >> 4) & 0x3);
780
781     RCHECK(sample_depends_on_[i] != kSampleDependsOnReserved);
782   }
783
784   return true;
785 }
786
787 SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
788     size_t i) const {
789   if (i >= sample_depends_on_.size())
790     return kSampleDependsOnUnknown;
791
792   return sample_depends_on_[i];
793 }
794
795 }  // namespace mp4
796 }  // namespace media