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
11namespace media {
12namespace mp4 {
13
14FileType::FileType() {}
15FileType::~FileType() {}
16FourCC FileType::BoxType() const { return FOURCC_FTYP; }
17
18bool 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
24ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
25ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
26FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; }
27
28bool 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
42SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
43SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
44FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; }
45
46bool 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
66SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
67  : default_sample_info_size(0), sample_count(0) {
68}
69SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
70FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; }
71
72bool 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
84OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
85OriginalFormat::~OriginalFormat() {}
86FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; }
87
88bool OriginalFormat::Parse(BoxReader* reader) {
89  return reader->ReadFourCC(&format);
90}
91
92SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
93SchemeType::~SchemeType() {}
94FourCC SchemeType::BoxType() const { return FOURCC_SCHM; }
95
96bool SchemeType::Parse(BoxReader* reader) {
97  RCHECK(reader->ReadFullBoxHeader() &&
98         reader->ReadFourCC(&type) &&
99         reader->Read4(&version));
100  return true;
101}
102
103TrackEncryption::TrackEncryption()
104  : is_encrypted(false), default_iv_size(0) {
105}
106TrackEncryption::~TrackEncryption() {}
107FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; }
108
109bool 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
125SchemeInfo::SchemeInfo() {}
126SchemeInfo::~SchemeInfo() {}
127FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; }
128
129bool SchemeInfo::Parse(BoxReader* reader) {
130  return reader->ScanChildren() && reader->ReadChild(&track_encryption);
131}
132
133ProtectionSchemeInfo::ProtectionSchemeInfo() {}
134ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
135FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; }
136
137bool 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
150MovieHeader::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) {}
158MovieHeader::~MovieHeader() {}
159FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; }
160
161bool 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
185TrackHeader::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) {}
195TrackHeader::~TrackHeader() {}
196FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; }
197
198bool 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
227SampleDescription::SampleDescription() : type(kInvalid) {}
228SampleDescription::~SampleDescription() {}
229FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
230
231bool 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
248SampleTable::SampleTable() {}
249SampleTable::~SampleTable() {}
250FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
251
252bool SampleTable::Parse(BoxReader* reader) {
253  return reader->ScanChildren() &&
254         reader->ReadChild(&description);
255}
256
257EditList::EditList() {}
258EditList::~EditList() {}
259FourCC EditList::BoxType() const { return FOURCC_ELST; }
260
261bool 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
287Edit::Edit() {}
288Edit::~Edit() {}
289FourCC Edit::BoxType() const { return FOURCC_EDTS; }
290
291bool Edit::Parse(BoxReader* reader) {
292  return reader->ScanChildren() && reader->ReadChild(&list);
293}
294
295HandlerReference::HandlerReference() : type(kInvalid) {}
296HandlerReference::~HandlerReference() {}
297FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
298
299bool 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
313AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
314    : version(0),
315      profile_indication(0),
316      profile_compatibility(0),
317      avc_level(0),
318      length_size(0) {}
319
320AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
321FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
322
323bool 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
358PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
359PixelAspectRatioBox::~PixelAspectRatioBox() {}
360FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
361
362bool PixelAspectRatioBox::Parse(BoxReader* reader) {
363  RCHECK(reader->Read4(&h_spacing) &&
364         reader->Read4(&v_spacing));
365  return true;
366}
367
368VideoSampleEntry::VideoSampleEntry()
369    : format(FOURCC_NULL),
370      data_reference_index(0),
371      width(0),
372      height(0) {}
373
374VideoSampleEntry::~VideoSampleEntry() {}
375FourCC 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
381bool 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 (format == FOURCC_AVC1 ||
403      (format == FOURCC_ENCV && sinf.format.format == FOURCC_AVC1)) {
404    RCHECK(reader->ReadChild(&avcc));
405  }
406  return true;
407}
408
409ElementaryStreamDescriptor::ElementaryStreamDescriptor()
410    : object_type(kForbidden) {}
411
412ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
413
414FourCC ElementaryStreamDescriptor::BoxType() const {
415  return FOURCC_ESDS;
416}
417
418bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {
419  std::vector<uint8> data;
420  ESDescriptor es_desc;
421
422  RCHECK(reader->ReadFullBoxHeader());
423  RCHECK(reader->ReadVec(&data, reader->size() - reader->pos()));
424  RCHECK(es_desc.Parse(data));
425
426  object_type = es_desc.object_type();
427
428  RCHECK(aac.Parse(es_desc.decoder_specific_info()));
429
430  return true;
431}
432
433AudioSampleEntry::AudioSampleEntry()
434    : format(FOURCC_NULL),
435      data_reference_index(0),
436      channelcount(0),
437      samplesize(0),
438      samplerate(0) {}
439
440AudioSampleEntry::~AudioSampleEntry() {}
441
442FourCC AudioSampleEntry::BoxType() const {
443  DCHECK(false) << "AudioSampleEntry should be parsed according to the "
444                << "handler type recovered in its Media ancestor.";
445  return FOURCC_NULL;
446}
447
448bool AudioSampleEntry::Parse(BoxReader* reader) {
449  format = reader->type();
450  RCHECK(reader->SkipBytes(6) &&
451         reader->Read2(&data_reference_index) &&
452         reader->SkipBytes(8) &&
453         reader->Read2(&channelcount) &&
454         reader->Read2(&samplesize) &&
455         reader->SkipBytes(4) &&
456         reader->Read4(&samplerate));
457  // Convert from 16.16 fixed point to integer
458  samplerate >>= 16;
459
460  RCHECK(reader->ScanChildren());
461  if (format == FOURCC_ENCA) {
462    // Continue scanning until a recognized protection scheme is found, or until
463    // we run out of protection schemes.
464    while (sinf.type.type != FOURCC_CENC) {
465      if (!reader->ReadChild(&sinf))
466        return false;
467    }
468  }
469
470  // ESDS is not valid in case of EAC3.
471  RCHECK(reader->MaybeReadChild(&esds));
472  return true;
473}
474
475MediaHeader::MediaHeader()
476    : creation_time(0),
477      modification_time(0),
478      timescale(0),
479      duration(0) {}
480MediaHeader::~MediaHeader() {}
481FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
482
483bool MediaHeader::Parse(BoxReader* reader) {
484  RCHECK(reader->ReadFullBoxHeader());
485
486  if (reader->version() == 1) {
487    RCHECK(reader->Read8(&creation_time) &&
488           reader->Read8(&modification_time) &&
489           reader->Read4(&timescale) &&
490           reader->Read8(&duration));
491  } else {
492    RCHECK(reader->Read4Into8(&creation_time) &&
493           reader->Read4Into8(&modification_time) &&
494           reader->Read4(&timescale) &&
495           reader->Read4Into8(&duration));
496  }
497  // Skip language information
498  return reader->SkipBytes(4);
499}
500
501MediaInformation::MediaInformation() {}
502MediaInformation::~MediaInformation() {}
503FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
504
505bool MediaInformation::Parse(BoxReader* reader) {
506  return reader->ScanChildren() &&
507         reader->ReadChild(&sample_table);
508}
509
510Media::Media() {}
511Media::~Media() {}
512FourCC Media::BoxType() const { return FOURCC_MDIA; }
513
514bool Media::Parse(BoxReader* reader) {
515  RCHECK(reader->ScanChildren() &&
516         reader->ReadChild(&header) &&
517         reader->ReadChild(&handler));
518
519  // Maddeningly, the HandlerReference box specifies how to parse the
520  // SampleDescription box, making the latter the only box (of those that we
521  // support) which cannot be parsed correctly on its own (or even with
522  // information from its strict ancestor tree). We thus copy the handler type
523  // to the sample description box *before* parsing it to provide this
524  // information while parsing.
525  information.sample_table.description.type = handler.type;
526  RCHECK(reader->ReadChild(&information));
527  return true;
528}
529
530Track::Track() {}
531Track::~Track() {}
532FourCC Track::BoxType() const { return FOURCC_TRAK; }
533
534bool Track::Parse(BoxReader* reader) {
535  RCHECK(reader->ScanChildren() &&
536         reader->ReadChild(&header) &&
537         reader->ReadChild(&media) &&
538         reader->MaybeReadChild(&edit));
539  return true;
540}
541
542MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
543MovieExtendsHeader::~MovieExtendsHeader() {}
544FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
545
546bool MovieExtendsHeader::Parse(BoxReader* reader) {
547  RCHECK(reader->ReadFullBoxHeader());
548  if (reader->version() == 1) {
549    RCHECK(reader->Read8(&fragment_duration));
550  } else {
551    RCHECK(reader->Read4Into8(&fragment_duration));
552  }
553  return true;
554}
555
556TrackExtends::TrackExtends()
557    : track_id(0),
558      default_sample_description_index(0),
559      default_sample_duration(0),
560      default_sample_size(0),
561      default_sample_flags(0) {}
562TrackExtends::~TrackExtends() {}
563FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
564
565bool TrackExtends::Parse(BoxReader* reader) {
566  RCHECK(reader->ReadFullBoxHeader() &&
567         reader->Read4(&track_id) &&
568         reader->Read4(&default_sample_description_index) &&
569         reader->Read4(&default_sample_duration) &&
570         reader->Read4(&default_sample_size) &&
571         reader->Read4(&default_sample_flags));
572  return true;
573}
574
575MovieExtends::MovieExtends() {}
576MovieExtends::~MovieExtends() {}
577FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
578
579bool MovieExtends::Parse(BoxReader* reader) {
580  header.fragment_duration = 0;
581  return reader->ScanChildren() &&
582         reader->MaybeReadChild(&header) &&
583         reader->ReadChildren(&tracks);
584}
585
586Movie::Movie() : fragmented(false) {}
587Movie::~Movie() {}
588FourCC Movie::BoxType() const { return FOURCC_MOOV; }
589
590bool Movie::Parse(BoxReader* reader) {
591  return reader->ScanChildren() &&
592         reader->ReadChild(&header) &&
593         reader->ReadChildren(&tracks) &&
594         // Media Source specific: 'mvex' required
595         reader->ReadChild(&extends) &&
596         reader->MaybeReadChildren(&pssh);
597}
598
599TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
600TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
601FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
602
603bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {
604  RCHECK(reader->ReadFullBoxHeader());
605  if (reader->version() == 1)
606    return reader->Read8(&decode_time);
607  else
608    return reader->Read4Into8(&decode_time);
609}
610
611MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
612MovieFragmentHeader::~MovieFragmentHeader() {}
613FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
614
615bool MovieFragmentHeader::Parse(BoxReader* reader) {
616  return reader->SkipBytes(4) && reader->Read4(&sequence_number);
617}
618
619TrackFragmentHeader::TrackFragmentHeader()
620    : track_id(0),
621      sample_description_index(0),
622      default_sample_duration(0),
623      default_sample_size(0),
624      default_sample_flags(0),
625      has_default_sample_flags(false) {}
626
627TrackFragmentHeader::~TrackFragmentHeader() {}
628FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
629
630bool TrackFragmentHeader::Parse(BoxReader* reader) {
631  RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id));
632
633  // Media Source specific: reject tracks that set 'base-data-offset-present'.
634  // Although the Media Source requires that 'default-base-is-moof' (14496-12
635  // Amendment 2) be set, we omit this check as many otherwise-valid files in
636  // the wild don't set it.
637  //
638  //  RCHECK((flags & 0x020000) && !(flags & 0x1));
639  RCHECK(!(reader->flags() & 0x1));
640
641  if (reader->flags() & 0x2) {
642    RCHECK(reader->Read4(&sample_description_index));
643  } else {
644    sample_description_index = 0;
645  }
646
647  if (reader->flags() & 0x8) {
648    RCHECK(reader->Read4(&default_sample_duration));
649  } else {
650    default_sample_duration = 0;
651  }
652
653  if (reader->flags() & 0x10) {
654    RCHECK(reader->Read4(&default_sample_size));
655  } else {
656    default_sample_size = 0;
657  }
658
659  if (reader->flags() & 0x20) {
660    RCHECK(reader->Read4(&default_sample_flags));
661    has_default_sample_flags = true;
662  } else {
663    has_default_sample_flags = false;
664  }
665
666  return true;
667}
668
669TrackFragmentRun::TrackFragmentRun()
670    : sample_count(0), data_offset(0) {}
671TrackFragmentRun::~TrackFragmentRun() {}
672FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
673
674bool TrackFragmentRun::Parse(BoxReader* reader) {
675  RCHECK(reader->ReadFullBoxHeader() &&
676         reader->Read4(&sample_count));
677  const uint32 flags = reader->flags();
678
679  bool data_offset_present = (flags & 0x1) != 0;
680  bool first_sample_flags_present = (flags & 0x4) != 0;
681  bool sample_duration_present = (flags & 0x100) != 0;
682  bool sample_size_present = (flags & 0x200) != 0;
683  bool sample_flags_present = (flags & 0x400) != 0;
684  bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
685
686  if (data_offset_present) {
687    RCHECK(reader->Read4(&data_offset));
688  } else {
689    data_offset = 0;
690  }
691
692  uint32 first_sample_flags;
693  if (first_sample_flags_present)
694    RCHECK(reader->Read4(&first_sample_flags));
695
696  int fields = sample_duration_present + sample_size_present +
697      sample_flags_present + sample_composition_time_offsets_present;
698  RCHECK(reader->HasBytes(fields * sample_count));
699
700  if (sample_duration_present)
701    sample_durations.resize(sample_count);
702  if (sample_size_present)
703    sample_sizes.resize(sample_count);
704  if (sample_flags_present)
705    sample_flags.resize(sample_count);
706  if (sample_composition_time_offsets_present)
707    sample_composition_time_offsets.resize(sample_count);
708
709  for (uint32 i = 0; i < sample_count; ++i) {
710    if (sample_duration_present)
711      RCHECK(reader->Read4(&sample_durations[i]));
712    if (sample_size_present)
713      RCHECK(reader->Read4(&sample_sizes[i]));
714    if (sample_flags_present)
715      RCHECK(reader->Read4(&sample_flags[i]));
716    if (sample_composition_time_offsets_present)
717      RCHECK(reader->Read4s(&sample_composition_time_offsets[i]));
718  }
719
720  if (first_sample_flags_present) {
721    if (sample_flags.size() == 0) {
722      sample_flags.push_back(first_sample_flags);
723    } else {
724      sample_flags[0] = first_sample_flags;
725    }
726  }
727  return true;
728}
729
730TrackFragment::TrackFragment() {}
731TrackFragment::~TrackFragment() {}
732FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
733
734bool TrackFragment::Parse(BoxReader* reader) {
735  return reader->ScanChildren() &&
736         reader->ReadChild(&header) &&
737         // Media Source specific: 'tfdt' required
738         reader->ReadChild(&decode_time) &&
739         reader->MaybeReadChildren(&runs) &&
740         reader->MaybeReadChild(&auxiliary_offset) &&
741         reader->MaybeReadChild(&auxiliary_size);
742}
743
744MovieFragment::MovieFragment() {}
745MovieFragment::~MovieFragment() {}
746FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
747
748bool MovieFragment::Parse(BoxReader* reader) {
749  RCHECK(reader->ScanChildren() &&
750         reader->ReadChild(&header) &&
751         reader->ReadChildren(&tracks) &&
752         reader->MaybeReadChildren(&pssh));
753  return true;
754}
755
756}  // namespace mp4
757}  // namespace media
758