Revert "Omit calls to set composing region when pasting image."
[chromium-blink-merge.git] / media / formats / mp4 / box_definitions.cc
blobfc0250d13cbf63f350f4a0f398d5c777e7f6455c
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.
5 #include "media/formats/mp4/box_definitions.h"
7 #include "base/logging.h"
8 #include "media/base/video_types.h"
9 #include "media/base/video_util.h"
10 #include "media/formats/mp4/avc.h"
11 #include "media/formats/mp4/es_descriptor.h"
12 #include "media/formats/mp4/rcheck.h"
14 #if defined(ENABLE_HEVC_DEMUXING)
15 #include "media/formats/mp4/hevc.h"
16 #endif
18 namespace media {
19 namespace mp4 {
21 FileType::FileType() {}
22 FileType::~FileType() {}
23 FourCC FileType::BoxType() const { return FOURCC_FTYP; }
25 bool FileType::Parse(BoxReader* reader) {
26 RCHECK(reader->ReadFourCC(&major_brand) && reader->Read4(&minor_version));
27 size_t num_brands = (reader->size() - reader->pos()) / sizeof(FourCC);
28 return reader->SkipBytes(sizeof(FourCC) * num_brands); // compatible_brands
31 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
32 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
33 FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; }
35 bool ProtectionSystemSpecificHeader::Parse(BoxReader* reader) {
36 // Don't bother validating the box's contents.
37 // Copy the entire box, including the header, for passing to EME as initData.
38 DCHECK(raw_box.empty());
39 raw_box.assign(reader->data(), reader->data() + reader->size());
40 return true;
43 FullProtectionSystemSpecificHeader::FullProtectionSystemSpecificHeader() {}
44 FullProtectionSystemSpecificHeader::~FullProtectionSystemSpecificHeader() {}
45 FourCC FullProtectionSystemSpecificHeader::BoxType() const {
46 return FOURCC_PSSH;
49 // The format of a 'pssh' box is as follows:
50 // unsigned int(32) size;
51 // unsigned int(32) type = "pssh";
52 // if (size==1) {
53 // unsigned int(64) largesize;
54 // } else if (size==0) {
55 // -- box extends to end of file
56 // }
57 // unsigned int(8) version;
58 // bit(24) flags;
59 // unsigned int(8)[16] SystemID;
60 // if (version > 0)
61 // {
62 // unsigned int(32) KID_count;
63 // {
64 // unsigned int(8)[16] KID;
65 // } [KID_count]
66 // }
67 // unsigned int(32) DataSize;
68 // unsigned int(8)[DataSize] Data;
70 bool FullProtectionSystemSpecificHeader::Parse(mp4::BoxReader* reader) {
71 RCHECK(reader->type() == BoxType() && reader->ReadFullBoxHeader());
73 // Only versions 0 and 1 of the 'pssh' boxes are supported. Any other
74 // versions are ignored.
75 RCHECK(reader->version() == 0 || reader->version() == 1);
76 RCHECK(reader->flags() == 0);
77 RCHECK(reader->ReadVec(&system_id, 16));
79 if (reader->version() > 0) {
80 uint32_t kid_count;
81 RCHECK(reader->Read4(&kid_count));
82 for (uint32_t i = 0; i < kid_count; ++i) {
83 std::vector<uint8_t> kid;
84 RCHECK(reader->ReadVec(&kid, 16));
85 key_ids.push_back(kid);
89 uint32_t data_size;
90 RCHECK(reader->Read4(&data_size));
91 RCHECK(reader->ReadVec(&data, data_size));
92 return true;
95 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
96 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
97 FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; }
99 bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) {
100 RCHECK(reader->ReadFullBoxHeader());
101 if (reader->flags() & 1)
102 RCHECK(reader->SkipBytes(8));
104 uint32 count;
105 RCHECK(reader->Read4(&count) &&
106 reader->HasBytes(count * (reader->version() == 1 ? 8 : 4)));
107 offsets.resize(count);
109 for (uint32 i = 0; i < count; i++) {
110 if (reader->version() == 1) {
111 RCHECK(reader->Read8(&offsets[i]));
112 } else {
113 RCHECK(reader->Read4Into8(&offsets[i]));
116 return true;
119 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
120 : default_sample_info_size(0), sample_count(0) {
122 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
123 FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; }
125 bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) {
126 RCHECK(reader->ReadFullBoxHeader());
127 if (reader->flags() & 1)
128 RCHECK(reader->SkipBytes(8));
130 RCHECK(reader->Read1(&default_sample_info_size) &&
131 reader->Read4(&sample_count));
132 if (default_sample_info_size == 0)
133 return reader->ReadVec(&sample_info_sizes, sample_count);
134 return true;
137 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
138 OriginalFormat::~OriginalFormat() {}
139 FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; }
141 bool OriginalFormat::Parse(BoxReader* reader) {
142 return reader->ReadFourCC(&format);
145 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
146 SchemeType::~SchemeType() {}
147 FourCC SchemeType::BoxType() const { return FOURCC_SCHM; }
149 bool SchemeType::Parse(BoxReader* reader) {
150 RCHECK(reader->ReadFullBoxHeader() &&
151 reader->ReadFourCC(&type) &&
152 reader->Read4(&version));
153 return true;
156 TrackEncryption::TrackEncryption()
157 : is_encrypted(false), default_iv_size(0) {
159 TrackEncryption::~TrackEncryption() {}
160 FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; }
162 bool TrackEncryption::Parse(BoxReader* reader) {
163 uint8 flag;
164 RCHECK(reader->ReadFullBoxHeader() &&
165 reader->SkipBytes(2) &&
166 reader->Read1(&flag) &&
167 reader->Read1(&default_iv_size) &&
168 reader->ReadVec(&default_kid, 16));
169 is_encrypted = (flag != 0);
170 if (is_encrypted) {
171 RCHECK(default_iv_size == 8 || default_iv_size == 16);
172 } else {
173 RCHECK(default_iv_size == 0);
175 return true;
178 SchemeInfo::SchemeInfo() {}
179 SchemeInfo::~SchemeInfo() {}
180 FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; }
182 bool SchemeInfo::Parse(BoxReader* reader) {
183 return reader->ScanChildren() && reader->ReadChild(&track_encryption);
186 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
187 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
188 FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; }
190 bool ProtectionSchemeInfo::Parse(BoxReader* reader) {
191 RCHECK(reader->ScanChildren() &&
192 reader->ReadChild(&format) &&
193 reader->ReadChild(&type));
194 if (type.type == FOURCC_CENC)
195 RCHECK(reader->ReadChild(&info));
196 // Other protection schemes are silently ignored. Since the protection scheme
197 // type can't be determined until this box is opened, we return 'true' for
198 // non-CENC protection scheme types. It is the parent box's responsibility to
199 // ensure that this scheme type is a supported one.
200 return true;
203 MovieHeader::MovieHeader()
204 : creation_time(0),
205 modification_time(0),
206 timescale(0),
207 duration(0),
208 rate(-1),
209 volume(-1),
210 next_track_id(0) {}
211 MovieHeader::~MovieHeader() {}
212 FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; }
214 bool MovieHeader::Parse(BoxReader* reader) {
215 RCHECK(reader->ReadFullBoxHeader());
217 if (reader->version() == 1) {
218 RCHECK(reader->Read8(&creation_time) &&
219 reader->Read8(&modification_time) &&
220 reader->Read4(&timescale) &&
221 reader->Read8(&duration));
222 } else {
223 RCHECK(reader->Read4Into8(&creation_time) &&
224 reader->Read4Into8(&modification_time) &&
225 reader->Read4(&timescale) &&
226 reader->Read4Into8(&duration));
229 RCHECK(reader->Read4s(&rate) &&
230 reader->Read2s(&volume) &&
231 reader->SkipBytes(10) && // reserved
232 reader->SkipBytes(36) && // matrix
233 reader->SkipBytes(24) && // predefined zero
234 reader->Read4(&next_track_id));
235 return true;
238 TrackHeader::TrackHeader()
239 : creation_time(0),
240 modification_time(0),
241 track_id(0),
242 duration(0),
243 layer(-1),
244 alternate_group(-1),
245 volume(-1),
246 width(0),
247 height(0) {}
248 TrackHeader::~TrackHeader() {}
249 FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; }
251 bool TrackHeader::Parse(BoxReader* reader) {
252 RCHECK(reader->ReadFullBoxHeader());
253 if (reader->version() == 1) {
254 RCHECK(reader->Read8(&creation_time) &&
255 reader->Read8(&modification_time) &&
256 reader->Read4(&track_id) &&
257 reader->SkipBytes(4) && // reserved
258 reader->Read8(&duration));
259 } else {
260 RCHECK(reader->Read4Into8(&creation_time) &&
261 reader->Read4Into8(&modification_time) &&
262 reader->Read4(&track_id) &&
263 reader->SkipBytes(4) && // reserved
264 reader->Read4Into8(&duration));
267 RCHECK(reader->SkipBytes(8) && // reserved
268 reader->Read2s(&layer) &&
269 reader->Read2s(&alternate_group) &&
270 reader->Read2s(&volume) &&
271 reader->SkipBytes(2) && // reserved
272 reader->SkipBytes(36) && // matrix
273 reader->Read4(&width) &&
274 reader->Read4(&height));
276 // Round width and height to the nearest number.
277 // Note: width and height are fixed-point 16.16 values. The following code
278 // rounds a.1x to a + 1, and a.0x to a.
279 width >>= 15;
280 width += 1;
281 width >>= 1;
282 height >>= 15;
283 height += 1;
284 height >>= 1;
286 return true;
289 SampleDescription::SampleDescription() : type(kInvalid) {}
290 SampleDescription::~SampleDescription() {}
291 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
293 bool SampleDescription::Parse(BoxReader* reader) {
294 uint32 count;
295 RCHECK(reader->SkipBytes(4) &&
296 reader->Read4(&count));
297 video_entries.clear();
298 audio_entries.clear();
300 // Note: this value is preset before scanning begins. See comments in the
301 // Parse(Media*) function.
302 if (type == kVideo) {
303 RCHECK(reader->ReadAllChildren(&video_entries));
304 } else if (type == kAudio) {
305 RCHECK(reader->ReadAllChildren(&audio_entries));
307 return true;
310 SampleTable::SampleTable() {}
311 SampleTable::~SampleTable() {}
312 FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
314 bool SampleTable::Parse(BoxReader* reader) {
315 RCHECK(reader->ScanChildren() &&
316 reader->ReadChild(&description));
317 // There could be multiple SampleGroupDescription boxes with different
318 // grouping types. For common encryption, the relevant grouping type is
319 // 'seig'. Continue reading until 'seig' is found, or until running out of
320 // child boxes.
321 while (reader->HasChild(&sample_group_description)) {
322 RCHECK(reader->ReadChild(&sample_group_description));
323 if (sample_group_description.grouping_type == FOURCC_SEIG)
324 break;
325 sample_group_description.entries.clear();
327 return true;
330 EditList::EditList() {}
331 EditList::~EditList() {}
332 FourCC EditList::BoxType() const { return FOURCC_ELST; }
334 bool EditList::Parse(BoxReader* reader) {
335 uint32 count;
336 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&count));
338 if (reader->version() == 1) {
339 RCHECK(reader->HasBytes(count * 20));
340 } else {
341 RCHECK(reader->HasBytes(count * 12));
343 edits.resize(count);
345 for (std::vector<EditListEntry>::iterator edit = edits.begin();
346 edit != edits.end(); ++edit) {
347 if (reader->version() == 1) {
348 RCHECK(reader->Read8(&edit->segment_duration) &&
349 reader->Read8s(&edit->media_time));
350 } else {
351 RCHECK(reader->Read4Into8(&edit->segment_duration) &&
352 reader->Read4sInto8s(&edit->media_time));
354 RCHECK(reader->Read2s(&edit->media_rate_integer) &&
355 reader->Read2s(&edit->media_rate_fraction));
357 return true;
360 Edit::Edit() {}
361 Edit::~Edit() {}
362 FourCC Edit::BoxType() const { return FOURCC_EDTS; }
364 bool Edit::Parse(BoxReader* reader) {
365 return reader->ScanChildren() && reader->ReadChild(&list);
368 HandlerReference::HandlerReference() : type(kInvalid) {}
369 HandlerReference::~HandlerReference() {}
370 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
372 bool HandlerReference::Parse(BoxReader* reader) {
373 FourCC hdlr_type;
374 RCHECK(reader->SkipBytes(8) && reader->ReadFourCC(&hdlr_type));
375 // Note: remaining fields in box ignored
376 if (hdlr_type == FOURCC_VIDE) {
377 type = kVideo;
378 } else if (hdlr_type == FOURCC_SOUN) {
379 type = kAudio;
380 } else {
381 type = kInvalid;
383 return true;
386 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
387 : version(0),
388 profile_indication(0),
389 profile_compatibility(0),
390 avc_level(0),
391 length_size(0) {}
393 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
394 FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }
396 bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
397 return ParseInternal(reader, reader->media_log());
400 bool AVCDecoderConfigurationRecord::Parse(const uint8* data, int data_size) {
401 BufferReader reader(data, data_size);
402 return ParseInternal(&reader, new MediaLog());
405 bool AVCDecoderConfigurationRecord::ParseInternal(
406 BufferReader* reader,
407 const scoped_refptr<MediaLog>& media_log) {
408 RCHECK(reader->Read1(&version) && version == 1 &&
409 reader->Read1(&profile_indication) &&
410 reader->Read1(&profile_compatibility) &&
411 reader->Read1(&avc_level));
413 uint8 length_size_minus_one;
414 RCHECK(reader->Read1(&length_size_minus_one));
415 length_size = (length_size_minus_one & 0x3) + 1;
417 RCHECK(length_size != 3); // Only values of 1, 2, and 4 are valid.
419 uint8 num_sps;
420 RCHECK(reader->Read1(&num_sps));
421 num_sps &= 0x1f;
423 sps_list.resize(num_sps);
424 for (int i = 0; i < num_sps; i++) {
425 uint16 sps_length;
426 RCHECK(reader->Read2(&sps_length) &&
427 reader->ReadVec(&sps_list[i], sps_length));
428 RCHECK(sps_list[i].size() > 4);
430 if (media_log.get()) {
431 MEDIA_LOG(INFO, media_log) << "Video codec: avc1." << std::hex
432 << static_cast<int>(sps_list[i][1])
433 << static_cast<int>(sps_list[i][2])
434 << static_cast<int>(sps_list[i][3]);
438 uint8 num_pps;
439 RCHECK(reader->Read1(&num_pps));
441 pps_list.resize(num_pps);
442 for (int i = 0; i < num_pps; i++) {
443 uint16 pps_length;
444 RCHECK(reader->Read2(&pps_length) &&
445 reader->ReadVec(&pps_list[i], pps_length));
448 return true;
451 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {}
452 PixelAspectRatioBox::~PixelAspectRatioBox() {}
453 FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; }
455 bool PixelAspectRatioBox::Parse(BoxReader* reader) {
456 RCHECK(reader->Read4(&h_spacing) &&
457 reader->Read4(&v_spacing));
458 return true;
461 VideoSampleEntry::VideoSampleEntry()
462 : format(FOURCC_NULL),
463 data_reference_index(0),
464 width(0),
465 height(0),
466 video_codec(kUnknownVideoCodec),
467 video_codec_profile(VIDEO_CODEC_PROFILE_UNKNOWN) {}
469 VideoSampleEntry::~VideoSampleEntry() {}
470 FourCC VideoSampleEntry::BoxType() const {
471 DCHECK(false) << "VideoSampleEntry should be parsed according to the "
472 << "handler type recovered in its Media ancestor.";
473 return FOURCC_NULL;
476 namespace {
478 bool IsFormatValidH264(const FourCC& format,
479 const ProtectionSchemeInfo& sinf) {
480 return format == FOURCC_AVC1 || format == FOURCC_AVC3 ||
481 (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 ||
482 sinf.format.format == FOURCC_AVC3));
485 #if defined(ENABLE_HEVC_DEMUXING)
486 bool IsFormatValidHEVC(const FourCC& format,
487 const ProtectionSchemeInfo& sinf) {
488 return format == FOURCC_HEV1 || format == FOURCC_HVC1 ||
489 (format == FOURCC_ENCV && (sinf.format.format == FOURCC_HEV1 ||
490 sinf.format.format == FOURCC_HVC1));
492 #endif
496 bool VideoSampleEntry::Parse(BoxReader* reader) {
497 format = reader->type();
498 RCHECK(reader->SkipBytes(6) &&
499 reader->Read2(&data_reference_index) &&
500 reader->SkipBytes(16) &&
501 reader->Read2(&width) &&
502 reader->Read2(&height) &&
503 reader->SkipBytes(50));
505 RCHECK(reader->ScanChildren() &&
506 reader->MaybeReadChild(&pixel_aspect));
508 if (format == FOURCC_ENCV) {
509 // Continue scanning until a recognized protection scheme is found, or until
510 // we run out of protection schemes.
511 while (sinf.type.type != FOURCC_CENC) {
512 if (!reader->ReadChild(&sinf))
513 return false;
517 if (IsFormatValidH264(format, sinf)) {
518 DVLOG(2) << __FUNCTION__
519 << " reading AVCDecoderConfigurationRecord (avcC)";
520 scoped_ptr<AVCDecoderConfigurationRecord> avcConfig(
521 new AVCDecoderConfigurationRecord());
522 RCHECK(reader->ReadChild(avcConfig.get()));
523 frame_bitstream_converter = make_scoped_refptr(
524 new AVCBitstreamConverter(avcConfig.Pass()));
525 video_codec = kCodecH264;
526 video_codec_profile = H264PROFILE_MAIN;
527 #if defined(ENABLE_HEVC_DEMUXING)
528 } else if (IsFormatValidHEVC(format, sinf)) {
529 DVLOG(2) << __FUNCTION__
530 << " parsing HEVCDecoderConfigurationRecord (hvcC)";
531 scoped_ptr<HEVCDecoderConfigurationRecord> hevcConfig(
532 new HEVCDecoderConfigurationRecord());
533 RCHECK(reader->ReadChild(hevcConfig.get()));
534 frame_bitstream_converter = make_scoped_refptr(
535 new HEVCBitstreamConverter(hevcConfig.Pass()));
536 video_codec = kCodecHEVC;
537 #endif
538 } else {
539 // Unknown/unsupported format
540 MEDIA_LOG(ERROR, reader->media_log()) << __FUNCTION__
541 << " unsupported video format "
542 << FourCCToString(format);
543 return false;
546 return true;
549 bool VideoSampleEntry::IsFormatValid() const {
550 #if defined(ENABLE_HEVC_DEMUXING)
551 if (IsFormatValidHEVC(format, sinf))
552 return true;
553 #endif
554 return IsFormatValidH264(format, sinf);
557 ElementaryStreamDescriptor::ElementaryStreamDescriptor()
558 : object_type(kForbidden) {}
560 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
562 FourCC ElementaryStreamDescriptor::BoxType() const {
563 return FOURCC_ESDS;
566 bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {
567 std::vector<uint8> data;
568 ESDescriptor es_desc;
570 RCHECK(reader->ReadFullBoxHeader());
571 RCHECK(reader->ReadVec(&data, reader->size() - reader->pos()));
572 RCHECK(es_desc.Parse(data));
574 object_type = es_desc.object_type();
576 if (object_type != 0x40) {
577 MEDIA_LOG(INFO, reader->media_log()) << "Audio codec: mp4a." << std::hex
578 << static_cast<int>(object_type);
581 if (es_desc.IsAAC(object_type))
582 RCHECK(aac.Parse(es_desc.decoder_specific_info(), reader->media_log()));
584 return true;
587 AudioSampleEntry::AudioSampleEntry()
588 : format(FOURCC_NULL),
589 data_reference_index(0),
590 channelcount(0),
591 samplesize(0),
592 samplerate(0) {}
594 AudioSampleEntry::~AudioSampleEntry() {}
596 FourCC AudioSampleEntry::BoxType() const {
597 DCHECK(false) << "AudioSampleEntry should be parsed according to the "
598 << "handler type recovered in its Media ancestor.";
599 return FOURCC_NULL;
602 bool AudioSampleEntry::Parse(BoxReader* reader) {
603 format = reader->type();
604 RCHECK(reader->SkipBytes(6) &&
605 reader->Read2(&data_reference_index) &&
606 reader->SkipBytes(8) &&
607 reader->Read2(&channelcount) &&
608 reader->Read2(&samplesize) &&
609 reader->SkipBytes(4) &&
610 reader->Read4(&samplerate));
611 // Convert from 16.16 fixed point to integer
612 samplerate >>= 16;
614 RCHECK(reader->ScanChildren());
615 if (format == FOURCC_ENCA) {
616 // Continue scanning until a recognized protection scheme is found, or until
617 // we run out of protection schemes.
618 while (sinf.type.type != FOURCC_CENC) {
619 if (!reader->ReadChild(&sinf))
620 return false;
624 // ESDS is not valid in case of EAC3.
625 RCHECK(reader->MaybeReadChild(&esds));
626 return true;
629 MediaHeader::MediaHeader()
630 : creation_time(0),
631 modification_time(0),
632 timescale(0),
633 duration(0) {}
634 MediaHeader::~MediaHeader() {}
635 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
637 bool MediaHeader::Parse(BoxReader* reader) {
638 RCHECK(reader->ReadFullBoxHeader());
640 if (reader->version() == 1) {
641 RCHECK(reader->Read8(&creation_time) &&
642 reader->Read8(&modification_time) &&
643 reader->Read4(&timescale) &&
644 reader->Read8(&duration));
645 } else {
646 RCHECK(reader->Read4Into8(&creation_time) &&
647 reader->Read4Into8(&modification_time) &&
648 reader->Read4(&timescale) &&
649 reader->Read4Into8(&duration));
651 // Skip language information
652 return reader->SkipBytes(4);
655 MediaInformation::MediaInformation() {}
656 MediaInformation::~MediaInformation() {}
657 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
659 bool MediaInformation::Parse(BoxReader* reader) {
660 return reader->ScanChildren() &&
661 reader->ReadChild(&sample_table);
664 Media::Media() {}
665 Media::~Media() {}
666 FourCC Media::BoxType() const { return FOURCC_MDIA; }
668 bool Media::Parse(BoxReader* reader) {
669 RCHECK(reader->ScanChildren() &&
670 reader->ReadChild(&header) &&
671 reader->ReadChild(&handler));
673 // Maddeningly, the HandlerReference box specifies how to parse the
674 // SampleDescription box, making the latter the only box (of those that we
675 // support) which cannot be parsed correctly on its own (or even with
676 // information from its strict ancestor tree). We thus copy the handler type
677 // to the sample description box *before* parsing it to provide this
678 // information while parsing.
679 information.sample_table.description.type = handler.type;
680 RCHECK(reader->ReadChild(&information));
681 return true;
684 Track::Track() {}
685 Track::~Track() {}
686 FourCC Track::BoxType() const { return FOURCC_TRAK; }
688 bool Track::Parse(BoxReader* reader) {
689 RCHECK(reader->ScanChildren() &&
690 reader->ReadChild(&header) &&
691 reader->ReadChild(&media) &&
692 reader->MaybeReadChild(&edit));
693 return true;
696 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
697 MovieExtendsHeader::~MovieExtendsHeader() {}
698 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
700 bool MovieExtendsHeader::Parse(BoxReader* reader) {
701 RCHECK(reader->ReadFullBoxHeader());
702 if (reader->version() == 1) {
703 RCHECK(reader->Read8(&fragment_duration));
704 } else {
705 RCHECK(reader->Read4Into8(&fragment_duration));
707 return true;
710 TrackExtends::TrackExtends()
711 : track_id(0),
712 default_sample_description_index(0),
713 default_sample_duration(0),
714 default_sample_size(0),
715 default_sample_flags(0) {}
716 TrackExtends::~TrackExtends() {}
717 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
719 bool TrackExtends::Parse(BoxReader* reader) {
720 RCHECK(reader->ReadFullBoxHeader() &&
721 reader->Read4(&track_id) &&
722 reader->Read4(&default_sample_description_index) &&
723 reader->Read4(&default_sample_duration) &&
724 reader->Read4(&default_sample_size) &&
725 reader->Read4(&default_sample_flags));
726 return true;
729 MovieExtends::MovieExtends() {}
730 MovieExtends::~MovieExtends() {}
731 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
733 bool MovieExtends::Parse(BoxReader* reader) {
734 header.fragment_duration = 0;
735 return reader->ScanChildren() &&
736 reader->MaybeReadChild(&header) &&
737 reader->ReadChildren(&tracks);
740 Movie::Movie() : fragmented(false) {}
741 Movie::~Movie() {}
742 FourCC Movie::BoxType() const { return FOURCC_MOOV; }
744 bool Movie::Parse(BoxReader* reader) {
745 RCHECK(reader->ScanChildren() && reader->ReadChild(&header) &&
746 reader->ReadChildren(&tracks));
748 RCHECK_MEDIA_LOGGED(reader->ReadChild(&extends), reader->media_log(),
749 "Detected unfragmented MP4. Media Source Extensions "
750 "require ISO BMFF moov to contain mvex to indicate that "
751 "Movie Fragments are to be expected.");
753 return reader->MaybeReadChildren(&pssh);
756 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
757 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
758 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
760 bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {
761 RCHECK(reader->ReadFullBoxHeader());
762 if (reader->version() == 1)
763 return reader->Read8(&decode_time);
764 else
765 return reader->Read4Into8(&decode_time);
768 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
769 MovieFragmentHeader::~MovieFragmentHeader() {}
770 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
772 bool MovieFragmentHeader::Parse(BoxReader* reader) {
773 return reader->SkipBytes(4) && reader->Read4(&sequence_number);
776 TrackFragmentHeader::TrackFragmentHeader()
777 : track_id(0),
778 sample_description_index(0),
779 default_sample_duration(0),
780 default_sample_size(0),
781 default_sample_flags(0),
782 has_default_sample_flags(false) {}
784 TrackFragmentHeader::~TrackFragmentHeader() {}
785 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
787 bool TrackFragmentHeader::Parse(BoxReader* reader) {
788 RCHECK(reader->ReadFullBoxHeader() && reader->Read4(&track_id));
790 // Media Source specific: reject tracks that set 'base-data-offset-present'.
791 // Although the Media Source requires that 'default-base-is-moof' (14496-12
792 // Amendment 2) be set, we omit this check as many otherwise-valid files in
793 // the wild don't set it.
795 // RCHECK((flags & 0x020000) && !(flags & 0x1));
796 RCHECK(!(reader->flags() & 0x1));
798 if (reader->flags() & 0x2) {
799 RCHECK(reader->Read4(&sample_description_index));
800 } else {
801 sample_description_index = 0;
804 if (reader->flags() & 0x8) {
805 RCHECK(reader->Read4(&default_sample_duration));
806 } else {
807 default_sample_duration = 0;
810 if (reader->flags() & 0x10) {
811 RCHECK(reader->Read4(&default_sample_size));
812 } else {
813 default_sample_size = 0;
816 if (reader->flags() & 0x20) {
817 RCHECK(reader->Read4(&default_sample_flags));
818 has_default_sample_flags = true;
819 } else {
820 has_default_sample_flags = false;
823 return true;
826 TrackFragmentRun::TrackFragmentRun()
827 : sample_count(0), data_offset(0) {}
828 TrackFragmentRun::~TrackFragmentRun() {}
829 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
831 bool TrackFragmentRun::Parse(BoxReader* reader) {
832 RCHECK(reader->ReadFullBoxHeader() &&
833 reader->Read4(&sample_count));
834 const uint32 flags = reader->flags();
836 bool data_offset_present = (flags & 0x1) != 0;
837 bool first_sample_flags_present = (flags & 0x4) != 0;
838 bool sample_duration_present = (flags & 0x100) != 0;
839 bool sample_size_present = (flags & 0x200) != 0;
840 bool sample_flags_present = (flags & 0x400) != 0;
841 bool sample_composition_time_offsets_present = (flags & 0x800) != 0;
843 if (data_offset_present) {
844 RCHECK(reader->Read4(&data_offset));
845 } else {
846 data_offset = 0;
849 uint32 first_sample_flags = 0;
850 if (first_sample_flags_present)
851 RCHECK(reader->Read4(&first_sample_flags));
853 int fields = sample_duration_present + sample_size_present +
854 sample_flags_present + sample_composition_time_offsets_present;
855 RCHECK(reader->HasBytes(fields * sample_count));
857 if (sample_duration_present)
858 sample_durations.resize(sample_count);
859 if (sample_size_present)
860 sample_sizes.resize(sample_count);
861 if (sample_flags_present)
862 sample_flags.resize(sample_count);
863 if (sample_composition_time_offsets_present)
864 sample_composition_time_offsets.resize(sample_count);
866 for (uint32 i = 0; i < sample_count; ++i) {
867 if (sample_duration_present)
868 RCHECK(reader->Read4(&sample_durations[i]));
869 if (sample_size_present)
870 RCHECK(reader->Read4(&sample_sizes[i]));
871 if (sample_flags_present)
872 RCHECK(reader->Read4(&sample_flags[i]));
873 if (sample_composition_time_offsets_present)
874 RCHECK(reader->Read4s(&sample_composition_time_offsets[i]));
877 if (first_sample_flags_present) {
878 if (sample_flags.size() == 0) {
879 sample_flags.push_back(first_sample_flags);
880 } else {
881 sample_flags[0] = first_sample_flags;
884 return true;
887 SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
888 SampleToGroup::~SampleToGroup() {}
889 FourCC SampleToGroup::BoxType() const { return FOURCC_SBGP; }
891 bool SampleToGroup::Parse(BoxReader* reader) {
892 RCHECK(reader->ReadFullBoxHeader() &&
893 reader->Read4(&grouping_type));
895 if (reader->version() == 1)
896 RCHECK(reader->Read4(&grouping_type_parameter));
898 if (grouping_type != FOURCC_SEIG) {
899 DLOG(WARNING) << "SampleToGroup box with grouping_type '" << grouping_type
900 << "' is not supported.";
901 return true;
904 uint32 count;
905 RCHECK(reader->Read4(&count));
906 entries.resize(count);
907 for (uint32 i = 0; i < count; ++i) {
908 RCHECK(reader->Read4(&entries[i].sample_count) &&
909 reader->Read4(&entries[i].group_description_index));
911 return true;
914 CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
915 : is_encrypted(false), iv_size(0) {}
916 CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {}
918 SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
919 SampleGroupDescription::~SampleGroupDescription() {}
920 FourCC SampleGroupDescription::BoxType() const { return FOURCC_SGPD; }
922 bool SampleGroupDescription::Parse(BoxReader* reader) {
923 RCHECK(reader->ReadFullBoxHeader() &&
924 reader->Read4(&grouping_type));
926 if (grouping_type != FOURCC_SEIG) {
927 DLOG(WARNING) << "SampleGroupDescription box with grouping_type '"
928 << grouping_type << "' is not supported.";
929 return true;
932 const uint8 version = reader->version();
934 const size_t kKeyIdSize = 16;
935 const size_t kEntrySize = sizeof(uint32) + kKeyIdSize;
936 uint32 default_length = 0;
937 if (version == 1) {
938 RCHECK(reader->Read4(&default_length));
939 RCHECK(default_length == 0 || default_length >= kEntrySize);
942 uint32 count;
943 RCHECK(reader->Read4(&count));
944 entries.resize(count);
945 for (uint32 i = 0; i < count; ++i) {
946 if (version == 1) {
947 if (default_length == 0) {
948 uint32 description_length = 0;
949 RCHECK(reader->Read4(&description_length));
950 RCHECK(description_length >= kEntrySize);
954 uint8 flag;
955 RCHECK(reader->SkipBytes(2) && // reserved.
956 reader->Read1(&flag) &&
957 reader->Read1(&entries[i].iv_size) &&
958 reader->ReadVec(&entries[i].key_id, kKeyIdSize));
960 entries[i].is_encrypted = (flag != 0);
961 if (entries[i].is_encrypted) {
962 RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
963 } else {
964 RCHECK(entries[i].iv_size == 0);
967 return true;
970 TrackFragment::TrackFragment() {}
971 TrackFragment::~TrackFragment() {}
972 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
974 bool TrackFragment::Parse(BoxReader* reader) {
975 RCHECK(reader->ScanChildren() &&
976 reader->ReadChild(&header) &&
977 // Media Source specific: 'tfdt' required
978 reader->ReadChild(&decode_time) &&
979 reader->MaybeReadChildren(&runs) &&
980 reader->MaybeReadChild(&auxiliary_offset) &&
981 reader->MaybeReadChild(&auxiliary_size) &&
982 reader->MaybeReadChild(&sdtp));
984 // There could be multiple SampleGroupDescription and SampleToGroup boxes with
985 // different grouping types. For common encryption, the relevant grouping type
986 // is 'seig'. Continue reading until 'seig' is found, or until running out of
987 // child boxes.
988 while (reader->HasChild(&sample_group_description)) {
989 RCHECK(reader->ReadChild(&sample_group_description));
990 if (sample_group_description.grouping_type == FOURCC_SEIG)
991 break;
992 sample_group_description.entries.clear();
994 while (reader->HasChild(&sample_to_group)) {
995 RCHECK(reader->ReadChild(&sample_to_group));
996 if (sample_to_group.grouping_type == FOURCC_SEIG)
997 break;
998 sample_to_group.entries.clear();
1000 return true;
1003 MovieFragment::MovieFragment() {}
1004 MovieFragment::~MovieFragment() {}
1005 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
1007 bool MovieFragment::Parse(BoxReader* reader) {
1008 RCHECK(reader->ScanChildren() &&
1009 reader->ReadChild(&header) &&
1010 reader->ReadChildren(&tracks) &&
1011 reader->MaybeReadChildren(&pssh));
1012 return true;
1015 IndependentAndDisposableSamples::IndependentAndDisposableSamples() {}
1016 IndependentAndDisposableSamples::~IndependentAndDisposableSamples() {}
1017 FourCC IndependentAndDisposableSamples::BoxType() const { return FOURCC_SDTP; }
1019 bool IndependentAndDisposableSamples::Parse(BoxReader* reader) {
1020 RCHECK(reader->ReadFullBoxHeader());
1021 RCHECK(reader->version() == 0);
1022 RCHECK(reader->flags() == 0);
1024 int sample_count = reader->size() - reader->pos();
1025 sample_depends_on_.resize(sample_count);
1026 for (int i = 0; i < sample_count; ++i) {
1027 uint8 sample_info;
1028 RCHECK(reader->Read1(&sample_info));
1030 sample_depends_on_[i] =
1031 static_cast<SampleDependsOn>((sample_info >> 4) & 0x3);
1033 RCHECK(sample_depends_on_[i] != kSampleDependsOnReserved);
1036 return true;
1039 SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
1040 size_t i) const {
1041 if (i >= sample_depends_on_.size())
1042 return kSampleDependsOnUnknown;
1044 return sample_depends_on_[i];
1047 } // namespace mp4
1048 } // namespace media