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