box_definitions.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "media/formats/mp4/box_definitions.h"
6
7#include "base/logging.h"
8#include "media/formats/mp4/es_descriptor.h"
9#include "media/formats/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
248SyncSample::SyncSample() : is_present(false) {}
249SyncSample::~SyncSample() {}
250FourCC SyncSample::BoxType() const { return FOURCC_STSS; }
251
252bool SyncSample::Parse(BoxReader* reader) {
253  uint32 entry_count;
254  RCHECK(reader->ReadFullBoxHeader() &&
255         reader->Read4(&entry_count));
256
257  is_present = true;
258
259  if (entry_count == 0)
260    return true;
261
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;
269
270  RCHECK(reader->SkipBytes(skip_size));
271
272  return true;
273}
274
275SampleTable::SampleTable() {}
276SampleTable::~SampleTable() {}
277FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
278
279bool SampleTable::Parse(BoxReader* reader) {
280  return reader->ScanChildren() &&
281      reader->ReadChild(&description) &&
282      reader->MaybeReadChild(&sync_sample);
283}
284
285EditList::EditList() {}
286EditList::~EditList() {}
287FourCC EditList::BoxType() const { return FOURCC_ELST; }
288
289bool EditList::Parse(BoxReader* reader) {
290  uint32 count;
291  RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count));
292
293  if (reader->version() == 1) {
294    RCHECK(reader->HasBytes(count * 20));
295  } else {
296    RCHECK(reader->HasBytes(count * 12));
297  }
298  edits.resize(count);
299
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));
308    }
309    RCHECK(reader->Read2s(&edit->media_rate_integer) &&
310           reader->Read2s(&edit->media_rate_fraction));
311  }
312  return true;
313}
314
315Edit::Edit() {}
316Edit::~Edit() {}
317FourCC Edit::BoxType() const { return FOURCC_EDTS; }
318
319bool Edit::Parse(BoxReader* reader) {
320  return reader->ScanChildren() && reader->ReadChild(&list);
321}
322
323HandlerReference::HandlerReference() : type(kInvalid) {}
324HandlerReference::~HandlerReference() {}
325FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
326
327bool 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;
337  }
338  return true;
339}
340
341AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
342    : version(0),
343      profile_indication(0),
344      profile_compatibility(0),
345      avc_level(0),
346      length_size(0) {}
347
348AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
349FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
350
351bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
352  return ParseInternal(reader, reader->log_cb());
353}
354
355bool AVCDecoderConfigurationRecord::Parse(const uint8* data, int data_size) {
356  BufferReader reader(data, data_size);
357  return ParseInternal(&reader, LogCB());
358}
359
360bool AVCDecoderConfigurationRecord::ParseInternal(BufferReader* reader,
361                                                  const LogCB& log_cb) {
362  RCHECK(reader->Read1(&version) && version == 1 &&
363         reader->Read1(&profile_indication) &&
364         reader->Read1(&profile_compatibility) &&
365         reader->Read1(&avc_level));
366
367  uint8 length_size_minus_one;
368  RCHECK(reader->Read1(&length_size_minus_one) &&
369         (length_size_minus_one & 0xfc) == 0xfc);
370  length_size = (length_size_minus_one & 0x3) + 1;
371
372  RCHECK(length_size != 3); // Only values of 1, 2, and 4 are valid.
373
374  uint8 num_sps;
375  RCHECK(reader->Read1(&num_sps) && (num_sps & 0xe0) == 0xe0);
376  num_sps &= 0x1f;
377
378  sps_list.resize(num_sps);
379  for (int i = 0; i < num_sps; i++) {
380    uint16 sps_length;
381    RCHECK(reader->Read2(&sps_length) &&
382           reader->ReadVec(&sps_list[i], sps_length));
383    RCHECK(sps_list[i].size() > 4);
384
385    if (!log_cb.is_null()) {
386      MEDIA_LOG(log_cb) << "Video codec: avc1." << std::hex
387                        << static_cast<int>(sps_list[i][1])
388                        << static_cast<int>(sps_list[i][2])
389                        << static_cast<int>(sps_list[i][3]);
390    }
391  }
392
393  uint8 num_pps;
394  RCHECK(reader->Read1(&num_pps));
395
396  pps_list.resize(num_pps);
397  for (int i = 0; i < num_pps; i++) {
398    uint16 pps_length;
399    RCHECK(reader->Read2(&pps_length) &&
400           reader->ReadVec(&pps_list[i], pps_length));
401  }
402
403  return true;
404}
405
406PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
407PixelAspectRatioBox::~PixelAspectRatioBox() {}
408FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
409
410bool PixelAspectRatioBox::Parse(BoxReader* reader) {
411  RCHECK(reader->Read4(&h_spacing) &&
412         reader->Read4(&v_spacing));
413  return true;
414}
415
416VideoSampleEntry::VideoSampleEntry()
417    : format(FOURCC_NULL),
418      data_reference_index(0),
419      width(0),
420      height(0) {}
421
422VideoSampleEntry::~VideoSampleEntry() {}
423FourCC VideoSampleEntry::BoxType() const {
424  DCHECK(false) << "VideoSampleEntry should be parsed according to the "
425                << "handler type recovered in its Media ancestor.";
426  return FOURCC_NULL;
427}
428
429bool VideoSampleEntry::Parse(BoxReader* reader) {
430  format = reader->type();
431  RCHECK(reader->SkipBytes(6) &&
432         reader->Read2(&data_reference_index) &&
433         reader->SkipBytes(16) &&
434         reader->Read2(&width) &&
435         reader->Read2(&height) &&
436         reader->SkipBytes(50));
437
438  RCHECK(reader->ScanChildren() &&
439         reader->MaybeReadChild(&pixel_aspect));
440
441  if (format == FOURCC_ENCV) {
442    // Continue scanning until a recognized protection scheme is found, or until
443    // we run out of protection schemes.
444    while (sinf.type.type != FOURCC_CENC) {
445      if (!reader->ReadChild(&sinf))
446        return false;
447    }
448  }
449
450  if (IsFormatValid())
451    RCHECK(reader->ReadChild(&avcc));
452
453  return true;
454}
455
456bool VideoSampleEntry::IsFormatValid() const {
457  return format == FOURCC_AVC1 || format == FOURCC_AVC3 ||
458      (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 ||
459                                 sinf.format.format == FOURCC_AVC3));
460}
461
462ElementaryStreamDescriptor::ElementaryStreamDescriptor()
463    : object_type(kForbidden) {}
464
465ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
466
467FourCC ElementaryStreamDescriptor::BoxType() const {
468  return FOURCC_ESDS;
469}
470
471bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {
472  std::vector<uint8> data;
473  ESDescriptor es_desc;
474
475  RCHECK(reader->ReadFullBoxHeader());
476  RCHECK(reader->ReadVec(&data, reader->size() - reader->pos()));
477  RCHECK(es_desc.Parse(data));
478
479  object_type = es_desc.object_type();
480
481  if (object_type != 0x40) {
482    MEDIA_LOG(reader->log_cb()) << "Audio codec: mp4a."
483                                << std::hex << static_cast<int>(object_type);
484  }
485
486  if (es_desc.IsAAC(object_type))
487    RCHECK(aac.Parse(es_desc.decoder_specific_info(), reader->log_cb()));
488
489  return true;
490}
491
492AudioSampleEntry::AudioSampleEntry()
493    : format(FOURCC_NULL),
494      data_reference_index(0),
495      channelcount(0),
496      samplesize(0),
497      samplerate(0) {}
498
499AudioSampleEntry::~AudioSampleEntry() {}
500
501FourCC AudioSampleEntry::BoxType() const {
502  DCHECK(false) << "AudioSampleEntry should be parsed according to the "
503                << "handler type recovered in its Media ancestor.";
504  return FOURCC_NULL;
505}
506
507bool AudioSampleEntry::Parse(BoxReader* reader) {
508  format = reader->type();
509  RCHECK(reader->SkipBytes(6) &&
510         reader->Read2(&data_reference_index) &&
511         reader->SkipBytes(8) &&
512         reader->Read2(&channelcount) &&
513         reader->Read2(&samplesize) &&
514         reader->SkipBytes(4) &&
515         reader->Read4(&samplerate));
516  // Convert from 16.16 fixed point to integer
517  samplerate >>= 16;
518
519  RCHECK(reader->ScanChildren());
520  if (format == FOURCC_ENCA) {
521    // Continue scanning until a recognized protection scheme is found, or until
522    // we run out of protection schemes.
523    while (sinf.type.type != FOURCC_CENC) {
524      if (!reader->ReadChild(&sinf))
525        return false;
526    }
527  }
528
529  // ESDS is not valid in case of EAC3.
530  RCHECK(reader->MaybeReadChild(&esds));
531  return true;
532}
533
534MediaHeader::MediaHeader()
535    : creation_time(0),
536      modification_time(0),
537      timescale(0),
538      duration(0) {}
539MediaHeader::~MediaHeader() {}
540FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
541
542bool MediaHeader::Parse(BoxReader* reader) {
543  RCHECK(reader->ReadFullBoxHeader());
544
545  if (reader->version() == 1) {
546    RCHECK(reader->Read8(&creation_time) &&
547           reader->Read8(&modification_time) &&
548           reader->Read4(&timescale) &&
549           reader->Read8(&duration));
550  } else {
551    RCHECK(reader->Read4Into8(&creation_time) &&
552           reader->Read4Into8(&modification_time) &&
553           reader->Read4(&timescale) &&
554           reader->Read4Into8(&duration));
555  }
556  // Skip language information
557  return reader->SkipBytes(4);
558}
559
560MediaInformation::MediaInformation() {}
561MediaInformation::~MediaInformation() {}
562FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
563
564bool MediaInformation::Parse(BoxReader* reader) {
565  return reader->ScanChildren() &&
566         reader->ReadChild(&sample_table);
567}
568
569Media::Media() {}
570Media::~Media() {}
571FourCC Media::BoxType() const { return FOURCC_MDIA; }
572
573bool Media::Parse(BoxReader* reader) {
574  RCHECK(reader->ScanChildren() &&
575         reader->ReadChild(&header) &&
576         reader->ReadChild(&handler));
577
578  // Maddeningly, the HandlerReference box specifies how to parse the
579  // SampleDescription box, making the latter the only box (of those that we
580  // support) which cannot be parsed correctly on its own (or even with
581  // information from its strict ancestor tree). We thus copy the handler type
582  // to the sample description box *before* parsing it to provide this
583  // information while parsing.
584  information.sample_table.description.type = handler.type;
585  RCHECK(reader->ReadChild(&information));
586  return true;
587}
588
589Track::Track() {}
590Track::~Track() {}
591FourCC Track::BoxType() const { return FOURCC_TRAK; }
592
593bool Track::Parse(BoxReader* reader) {
594  RCHECK(reader->ScanChildren() &&
595         reader->ReadChild(&header) &&
596         reader->ReadChild(&media) &&
597         reader->MaybeReadChild(&edit));
598  return true;
599}
600
601MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
602MovieExtendsHeader::~MovieExtendsHeader() {}
603FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
604
605bool MovieExtendsHeader::Parse(BoxReader* reader) {
606  RCHECK(reader->ReadFullBoxHeader());
607  if (reader->version() == 1) {
608    RCHECK(reader->Read8(&fragment_duration));
609  } else {
610    RCHECK(reader->Read4Into8(&fragment_duration));
611  }
612  return true;
613}
614
615TrackExtends::TrackExtends()
616    : track_id(0),
617      default_sample_description_index(0),
618      default_sample_duration(0),
619      default_sample_size(0),
620      default_sample_flags(0) {}
621TrackExtends::~TrackExtends() {}
622FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
623
624bool TrackExtends::Parse(BoxReader* reader) {
625  RCHECK(reader->ReadFullBoxHeader() &&
626         reader->Read4(&track_id) &&
627         reader->Read4(&default_sample_description_index) &&
628         reader->Read4(&default_sample_duration) &&
629         reader->Read4(&default_sample_size) &&
630         reader->Read4(&default_sample_flags));
631  return true;
632}
633
634MovieExtends::MovieExtends() {}
635MovieExtends::~MovieExtends() {}
636FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
637
638bool MovieExtends::Parse(BoxReader* reader) {
639  header.fragment_duration = 0;
640  return reader->ScanChildren() &&
641         reader->MaybeReadChild(&header) &&
642         reader->ReadChildren(&tracks);
643}
644
645Movie::Movie() : fragmented(false) {}
646Movie::~Movie() {}
647FourCC Movie::BoxType() const { return FOURCC_MOOV; }
648
649bool Movie::Parse(BoxReader* reader) {
650  return reader->ScanChildren() &&
651         reader->ReadChild(&header) &&
652         reader->ReadChildren(&tracks) &&
653         // Media Source specific: 'mvex' required
654         reader->ReadChild(&extends) &&
655         reader->MaybeReadChildren(&pssh);
656}
657
658TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
659TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
660FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
661
662bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {
663  RCHECK(reader->ReadFullBoxHeader());
664  if (reader->version() == 1)
665    return reader->Read8(&decode_time);
666  else
667    return reader->Read4Into8(&decode_time);
668}
669
670MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
671MovieFragmentHeader::~MovieFragmentHeader() {}
672FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
673
674bool MovieFragmentHeader::Parse(BoxReader* reader) {
675  return reader->SkipBytes(4) && reader->Read4(&sequence_number);
676}
677
678TrackFragmentHeader::TrackFragmentHeader()
679    : track_id(0),
680      sample_description_index(0),
681      default_sample_duration(0),
682      default_sample_size(0),
683      default_sample_flags(0),
684      has_default_sample_flags(false) {}
685
686TrackFragmentHeader::~TrackFragmentHeader() {}
687FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
688
689bool TrackFragmentHeader::Parse(BoxReader* reader) {
690  RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id));
691
692  // Media Source specific: reject tracks that set 'base-data-offset-present'.
693  // Although the Media Source requires that 'default-base-is-moof' (14496-12
694  // Amendment 2) be set, we omit this check as many otherwise-valid files in
695  // the wild don't set it.
696  //
697  //  RCHECK((flags & 0x020000) && !(flags & 0x1));
698  RCHECK(!(reader->flags() & 0x1));
699
700  if (reader->flags() & 0x2) {
701    RCHECK(reader->Read4(&sample_description_index));
702  } else {
703    sample_description_index = 0;
704  }
705
706  if (reader->flags() & 0x8) {
707    RCHECK(reader->Read4(&default_sample_duration));
708  } else {
709    default_sample_duration = 0;
710  }
711
712  if (reader->flags() & 0x10) {
713    RCHECK(reader->Read4(&default_sample_size));
714  } else {
715    default_sample_size = 0;
716  }
717
718  if (reader->flags() & 0x20) {
719    RCHECK(reader->Read4(&default_sample_flags));
720    has_default_sample_flags = true;
721  } else {
722    has_default_sample_flags = false;
723  }
724
725  return true;
726}
727
728TrackFragmentRun::TrackFragmentRun()
729    : sample_count(0), data_offset(0) {}
730TrackFragmentRun::~TrackFragmentRun() {}
731FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
732
733bool TrackFragmentRun::Parse(BoxReader* reader) {
734  RCHECK(reader->ReadFullBoxHeader() &&
735         reader->Read4(&sample_count));
736  const uint32 flags = reader->flags();
737
738  bool data_offset_present = (flags & 0x1) != 0;
739  bool first_sample_flags_present = (flags & 0x4) != 0;
740  bool sample_duration_present = (flags & 0x100) != 0;
741  bool sample_size_present = (flags & 0x200) != 0;
742  bool sample_flags_present = (flags & 0x400) != 0;
743  bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
744
745  if (data_offset_present) {
746    RCHECK(reader->Read4(&data_offset));
747  } else {
748    data_offset = 0;
749  }
750
751  uint32 first_sample_flags;
752  if (first_sample_flags_present)
753    RCHECK(reader->Read4(&first_sample_flags));
754
755  int fields = sample_duration_present + sample_size_present +
756      sample_flags_present + sample_composition_time_offsets_present;
757  RCHECK(reader->HasBytes(fields * sample_count));
758
759  if (sample_duration_present)
760    sample_durations.resize(sample_count);
761  if (sample_size_present)
762    sample_sizes.resize(sample_count);
763  if (sample_flags_present)
764    sample_flags.resize(sample_count);
765  if (sample_composition_time_offsets_present)
766    sample_composition_time_offsets.resize(sample_count);
767
768  for (uint32 i = 0; i < sample_count; ++i) {
769    if (sample_duration_present)
770      RCHECK(reader->Read4(&sample_durations[i]));
771    if (sample_size_present)
772      RCHECK(reader->Read4(&sample_sizes[i]));
773    if (sample_flags_present)
774      RCHECK(reader->Read4(&sample_flags[i]));
775    if (sample_composition_time_offsets_present)
776      RCHECK(reader->Read4s(&sample_composition_time_offsets[i]));
777  }
778
779  if (first_sample_flags_present) {
780    if (sample_flags.size() == 0) {
781      sample_flags.push_back(first_sample_flags);
782    } else {
783      sample_flags[0] = first_sample_flags;
784    }
785  }
786  return true;
787}
788
789SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
790SampleToGroup::~SampleToGroup() {}
791FourCC SampleToGroup::BoxType() const { return FOURCC_SBGP; }
792
793bool SampleToGroup::Parse(BoxReader* reader) {
794  RCHECK(reader->ReadFullBoxHeader() &&
795         reader->Read4(&grouping_type));
796
797  if (reader->version() == 1)
798    RCHECK(reader->Read4(&grouping_type_parameter));
799
800  if (grouping_type != FOURCC_SEIG) {
801    DLOG(WARNING) << "SampleToGroup box with grouping_type '" << grouping_type
802                  << "' is not supported.";
803    return true;
804  }
805
806  uint32 count;
807  RCHECK(reader->Read4(&count));
808  entries.resize(count);
809  for (uint32 i = 0; i < count; ++i) {
810    RCHECK(reader->Read4(&entries[i].sample_count) &&
811           reader->Read4(&entries[i].group_description_index));
812  }
813  return true;
814}
815
816CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
817    : is_encrypted(false), iv_size(0) {}
818CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {}
819
820SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
821SampleGroupDescription::~SampleGroupDescription() {}
822FourCC SampleGroupDescription::BoxType() const { return FOURCC_SGPD; }
823
824bool SampleGroupDescription::Parse(BoxReader* reader) {
825  RCHECK(reader->ReadFullBoxHeader() &&
826         reader->Read4(&grouping_type));
827
828  if (grouping_type != FOURCC_SEIG) {
829    DLOG(WARNING) << "SampleGroupDescription box with grouping_type '"
830                  << grouping_type << "' is not supported.";
831    return true;
832  }
833
834  const uint8 version = reader->version();
835
836  const size_t kKeyIdSize = 16;
837  const size_t kEntrySize = sizeof(uint32) + kKeyIdSize;
838  uint32 default_length = 0;
839  if (version == 1) {
840      RCHECK(reader->Read4(&default_length));
841      RCHECK(default_length == 0 || default_length >= kEntrySize);
842  }
843
844  uint32 count;
845  RCHECK(reader->Read4(&count));
846  entries.resize(count);
847  for (uint32 i = 0; i < count; ++i) {
848    if (version == 1) {
849      if (default_length == 0) {
850        uint32 description_length = 0;
851        RCHECK(reader->Read4(&description_length));
852        RCHECK(description_length >= kEntrySize);
853      }
854    }
855
856    uint8 flag;
857    RCHECK(reader->SkipBytes(2) &&  // reserved.
858           reader->Read1(&flag) &&
859           reader->Read1(&entries[i].iv_size) &&
860           reader->ReadVec(&entries[i].key_id, kKeyIdSize));
861
862    entries[i].is_encrypted = (flag != 0);
863    if (entries[i].is_encrypted) {
864      RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
865    } else {
866      RCHECK(entries[i].iv_size == 0);
867    }
868  }
869  return true;
870}
871
872TrackFragment::TrackFragment() {}
873TrackFragment::~TrackFragment() {}
874FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
875
876bool TrackFragment::Parse(BoxReader* reader) {
877  RCHECK(reader->ScanChildren() &&
878         reader->ReadChild(&header) &&
879         // Media Source specific: 'tfdt' required
880         reader->ReadChild(&decode_time) &&
881         reader->MaybeReadChildren(&runs) &&
882         reader->MaybeReadChild(&auxiliary_offset) &&
883         reader->MaybeReadChild(&auxiliary_size) &&
884         reader->MaybeReadChild(&sdtp));
885
886  // There could be multiple SampleGroupDescription and SampleToGroup boxes with
887  // different grouping types. For common encryption, the relevant grouping type
888  // is 'seig'. Continue reading until 'seig' is found, or until running out of
889  // child boxes.
890  while (sample_group_description.grouping_type != FOURCC_SEIG &&
891         reader->HasChild(&sample_group_description)) {
892    RCHECK(reader->ReadChild(&sample_group_description));
893  }
894  while (sample_to_group.grouping_type != FOURCC_SEIG &&
895         reader->HasChild(&sample_to_group)) {
896    RCHECK(reader->ReadChild(&sample_to_group));
897  }
898  return true;
899}
900
901MovieFragment::MovieFragment() {}
902MovieFragment::~MovieFragment() {}
903FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
904
905bool MovieFragment::Parse(BoxReader* reader) {
906  RCHECK(reader->ScanChildren() &&
907         reader->ReadChild(&header) &&
908         reader->ReadChildren(&tracks) &&
909         reader->MaybeReadChildren(&pssh));
910  return true;
911}
912
913IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
914IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
915FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; }
916
917bool IndependentAndDisposableSamples::Parse(BoxReader* reader) {
918  RCHECK(reader->ReadFullBoxHeader());
919  RCHECK(reader->version() == 0);
920  RCHECK(reader->flags() == 0);
921
922  int sample_count = reader->size() - reader->pos();
923  sample_depends_on_.resize(sample_count);
924  for (int i = 0; i < sample_count; ++i) {
925    uint8 sample_info;
926    RCHECK(reader->Read1(&sample_info));
927
928    sample_depends_on_[i] =
929        static_cast<SampleDependsOn>((sample_info >> 4) & 0x3);
930
931    RCHECK(sample_depends_on_[i] != kSampleDependsOnReserved);
932  }
933
934  return true;
935}
936
937SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
938    size_t i) const {
939  if (i >= sample_depends_on_.size())
940    return kSampleDependsOnUnknown;
941
942  return sample_depends_on_[i];
943}
944
945}  // namespace mp4
946}  // namespace media
947