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