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
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(×cale) &&
168 reader->Read8(&duration));
169 } else {
170 RCHECK(reader->Read4Into8(&creation_time) &&
171 reader->Read4Into8(&modification_time) &&
172 reader->Read4(×cale) &&
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
SampleTable()248 SampleTable::SampleTable() {}
~SampleTable()249 SampleTable::~SampleTable() {}
BoxType() const250 FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
251
Parse(BoxReader * reader)252 bool SampleTable::Parse(BoxReader* reader) {
253 return reader->ScanChildren() &&
254 reader->ReadChild(&description);
255 }
256
EditList()257 EditList::EditList() {}
~EditList()258 EditList::~EditList() {}
BoxType() const259 FourCC EditList::BoxType() const { return FOURCC_ELST; }
260
Parse(BoxReader * reader)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
Edit()287 Edit::Edit() {}
~Edit()288 Edit::~Edit() {}
BoxType() const289 FourCC Edit::BoxType() const { return FOURCC_EDTS; }
290
Parse(BoxReader * reader)291 bool Edit::Parse(BoxReader* reader) {
292 return reader->ScanChildren() && reader->ReadChild(&list);
293 }
294
HandlerReference()295 HandlerReference::HandlerReference() : type(kInvalid) {}
~HandlerReference()296 HandlerReference::~HandlerReference() {}
BoxType() const297 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
298
Parse(BoxReader * reader)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
AVCDecoderConfigurationRecord()313 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
314 : version(0),
315 profile_indication(0),
316 profile_compatibility(0),
317 avc_level(0),
318 length_size(0) {}
319
~AVCDecoderConfigurationRecord()320 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
BoxType() const321 FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
322
Parse(BoxReader * reader)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
PixelAspectRatioBox()358 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
~PixelAspectRatioBox()359 PixelAspectRatioBox::~PixelAspectRatioBox() {}
BoxType() const360 FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
361
Parse(BoxReader * reader)362 bool PixelAspectRatioBox::Parse(BoxReader* reader) {
363 RCHECK(reader->Read4(&h_spacing) &&
364 reader->Read4(&v_spacing));
365 return true;
366 }
367
VideoSampleEntry()368 VideoSampleEntry::VideoSampleEntry()
369 : format(FOURCC_NULL),
370 data_reference_index(0),
371 width(0),
372 height(0) {}
373
~VideoSampleEntry()374 VideoSampleEntry::~VideoSampleEntry() {}
BoxType() const375 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
Parse(BoxReader * reader)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
IsFormatValid() const408 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
ElementaryStreamDescriptor()414 ElementaryStreamDescriptor::ElementaryStreamDescriptor()
415 : object_type(kForbidden) {}
416
~ElementaryStreamDescriptor()417 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
418
BoxType() const419 FourCC ElementaryStreamDescriptor::BoxType() const {
420 return FOURCC_ESDS;
421 }
422
Parse(BoxReader * reader)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
AudioSampleEntry()438 AudioSampleEntry::AudioSampleEntry()
439 : format(FOURCC_NULL),
440 data_reference_index(0),
441 channelcount(0),
442 samplesize(0),
443 samplerate(0) {}
444
~AudioSampleEntry()445 AudioSampleEntry::~AudioSampleEntry() {}
446
BoxType() const447 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
Parse(BoxReader * reader)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
MediaHeader()480 MediaHeader::MediaHeader()
481 : creation_time(0),
482 modification_time(0),
483 timescale(0),
484 duration(0) {}
~MediaHeader()485 MediaHeader::~MediaHeader() {}
BoxType() const486 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
487
Parse(BoxReader * reader)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(×cale) &&
495 reader->Read8(&duration));
496 } else {
497 RCHECK(reader->Read4Into8(&creation_time) &&
498 reader->Read4Into8(&modification_time) &&
499 reader->Read4(×cale) &&
500 reader->Read4Into8(&duration));
501 }
502 // Skip language information
503 return reader->SkipBytes(4);
504 }
505
MediaInformation()506 MediaInformation::MediaInformation() {}
~MediaInformation()507 MediaInformation::~MediaInformation() {}
BoxType() const508 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
509
Parse(BoxReader * reader)510 bool MediaInformation::Parse(BoxReader* reader) {
511 return reader->ScanChildren() &&
512 reader->ReadChild(&sample_table);
513 }
514
Media()515 Media::Media() {}
~Media()516 Media::~Media() {}
BoxType() const517 FourCC Media::BoxType() const { return FOURCC_MDIA; }
518
Parse(BoxReader * reader)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
Track()535 Track::Track() {}
~Track()536 Track::~Track() {}
BoxType() const537 FourCC Track::BoxType() const { return FOURCC_TRAK; }
538
Parse(BoxReader * reader)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
MovieExtendsHeader()547 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
~MovieExtendsHeader()548 MovieExtendsHeader::~MovieExtendsHeader() {}
BoxType() const549 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
550
Parse(BoxReader * reader)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
TrackExtends()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) {}
~TrackExtends()567 TrackExtends::~TrackExtends() {}
BoxType() const568 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
569
Parse(BoxReader * reader)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
MovieExtends()580 MovieExtends::MovieExtends() {}
~MovieExtends()581 MovieExtends::~MovieExtends() {}
BoxType() const582 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
583
Parse(BoxReader * reader)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
Movie()591 Movie::Movie() : fragmented(false) {}
~Movie()592 Movie::~Movie() {}
BoxType() const593 FourCC Movie::BoxType() const { return FOURCC_MOOV; }
594
Parse(BoxReader * reader)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
TrackFragmentDecodeTime()604 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
~TrackFragmentDecodeTime()605 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
BoxType() const606 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
607
Parse(BoxReader * reader)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
MovieFragmentHeader()616 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
~MovieFragmentHeader()617 MovieFragmentHeader::~MovieFragmentHeader() {}
BoxType() const618 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
619
Parse(BoxReader * reader)620 bool MovieFragmentHeader::Parse(BoxReader* reader) {
621 return reader->SkipBytes(4) && reader->Read4(&sequence_number);
622 }
623
TrackFragmentHeader()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
~TrackFragmentHeader()632 TrackFragmentHeader::~TrackFragmentHeader() {}
BoxType() const633 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
634
Parse(BoxReader * reader)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
TrackFragmentRun()674 TrackFragmentRun::TrackFragmentRun()
675 : sample_count(0), data_offset(0) {}
~TrackFragmentRun()676 TrackFragmentRun::~TrackFragmentRun() {}
BoxType() const677 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
678
Parse(BoxReader * reader)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
TrackFragment()735 TrackFragment::TrackFragment() {}
~TrackFragment()736 TrackFragment::~TrackFragment() {}
BoxType() const737 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
738
Parse(BoxReader * reader)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
MovieFragment()750 MovieFragment::MovieFragment() {}
~MovieFragment()751 MovieFragment::~MovieFragment() {}
BoxType() const752 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
753
Parse(BoxReader * reader)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
IndependentAndDisposableSamples()762 IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
~IndependentAndDisposableSamples()763 IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
BoxType() const764 FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; }
765
Parse(BoxReader * reader)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
sample_depends_on(size_t i) const787 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