5 #include "packager/media/formats/mp4/box_definitions.h"
9 #include "packager/base/logging.h"
10 #include "packager/media/base/bit_reader.h"
11 #include "packager/media/formats/mp4/box_buffer.h"
12 #include "packager/media/formats/mp4/rcheck.h"
15 const uint32_t kFourCCSize = 4;
17 const uint32_t kBoxSize = kFourCCSize +
sizeof(uint32_t);
19 const uint32_t kFullBoxSize = kBoxSize + 4;
22 const uint32_t kCencKeyIdSize = 16;
25 const uint8_t kUnityMatrix[] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
27 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0};
30 const char kVideoHandlerName[] =
"VideoHandler";
31 const char kAudioHandlerName[] =
"SoundHandler";
34 const uint32_t kVideoResolution = 0x00480000;
35 const uint16_t kVideoFrameCount = 1;
36 const uint16_t kVideoDepth = 0x0018;
39 bool IsFitIn32Bits(uint64_t a) {
40 return a <= std::numeric_limits<uint32_t>::max();
43 bool IsFitIn32Bits(int64_t a) {
44 return a <= std::numeric_limits<int32_t>::max() &&
45 a >= std::numeric_limits<int32_t>::min();
48 template <
typename T1,
typename T2>
49 bool IsFitIn32Bits(T1 a1, T2 a2) {
50 return IsFitIn32Bits(a1) && IsFitIn32Bits(a2);
53 template <
typename T1,
typename T2,
typename T3>
54 bool IsFitIn32Bits(T1 a1, T2 a2, T3 a3) {
55 return IsFitIn32Bits(a1) && IsFitIn32Bits(a2) && IsFitIn32Bits(a3);
60 namespace edash_packager {
64 FileType::FileType() : major_brand(FOURCC_NULL), minor_version(0) {}
65 FileType::~FileType() {}
66 FourCC FileType::BoxType()
const {
return FOURCC_FTYP; }
70 buffer->ReadWriteFourCC(&major_brand) &&
71 buffer->ReadWriteUInt32(&minor_version));
74 num_brands = (buffer->
Size() - buffer->
Pos()) /
sizeof(FourCC);
75 compatible_brands.resize(num_brands);
77 num_brands = compatible_brands.size();
79 for (
size_t i = 0; i < num_brands; ++i)
80 RCHECK(buffer->ReadWriteFourCC(&compatible_brands[i]));
85 atom_size = kBoxSize + kFourCCSize +
sizeof(minor_version) +
86 kFourCCSize * compatible_brands.size();
90 SegmentType::SegmentType() {}
91 SegmentType::~SegmentType() {}
92 FourCC SegmentType::BoxType()
const {
return FOURCC_STYP; }
102 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
103 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
104 FourCC ProtectionSystemSpecificHeader::BoxType()
const {
return FOURCC_PSSH; }
107 if (!buffer->
Reading() && !raw_box.empty()) {
109 buffer->
writer()->AppendVector(raw_box);
113 uint32_t size = data.size();
115 buffer->ReadWriteVector(&system_id, 16) &&
116 buffer->ReadWriteUInt32(&size) &&
117 buffer->ReadWriteVector(&data, size));
122 DCHECK(raw_box.empty());
125 raw_box.assign(reader->data(), reader->data() + reader->size());
131 if (!raw_box.empty()) {
135 kFullBoxSize + system_id.size() +
sizeof(uint32_t) + data.size();
140 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
141 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
142 FourCC SampleAuxiliaryInformationOffset::BoxType()
const {
return FOURCC_SAIO; }
149 uint32_t count = offsets.size();
150 RCHECK(buffer->ReadWriteUInt32(&count));
151 offsets.resize(count);
153 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
154 for (uint32_t i = 0; i < count; ++i)
162 if (offsets.size() != 0) {
163 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
164 atom_size = kFullBoxSize +
sizeof(uint32_t) + num_bytes * offsets.size();
169 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
170 : default_sample_info_size(0), sample_count(0) {}
171 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
172 FourCC SampleAuxiliaryInformationSize::BoxType()
const {
return FOURCC_SAIZ; }
179 RCHECK(buffer->ReadWriteUInt8(&default_sample_info_size) &&
180 buffer->ReadWriteUInt32(&sample_count));
181 if (default_sample_info_size == 0)
182 RCHECK(buffer->ReadWriteVector(&sample_info_sizes, sample_count));
189 if (sample_count != 0) {
190 atom_size = kFullBoxSize +
sizeof(default_sample_info_size) +
191 sizeof(sample_count) +
192 (default_sample_info_size == 0 ? sample_info_sizes.size() : 0);
197 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
198 OriginalFormat::~OriginalFormat() {}
199 FourCC OriginalFormat::BoxType()
const {
return FOURCC_FRMA; }
202 return Box::ReadWrite(buffer) && buffer->ReadWriteFourCC(&format);
210 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
211 SchemeType::~SchemeType() {}
212 FourCC SchemeType::BoxType()
const {
return FOURCC_SCHM; }
216 buffer->ReadWriteFourCC(&type) &&
217 buffer->ReadWriteUInt32(&version));
222 atom_size = kFullBoxSize + kFourCCSize +
sizeof(version);
226 TrackEncryption::TrackEncryption()
227 : is_encrypted(false), default_iv_size(0), default_kid(16, 0) {}
228 TrackEncryption::~TrackEncryption() {}
229 FourCC TrackEncryption::BoxType()
const {
return FOURCC_TENC; }
233 if (default_kid.size() != kCencKeyIdSize) {
234 LOG(WARNING) <<
"CENC defines key id length of " << kCencKeyIdSize
235 <<
" bytes; got " << default_kid.size()
236 <<
". Resized accordingly.";
237 default_kid.resize(kCencKeyIdSize);
241 uint8_t flag = is_encrypted ? 1 : 0;
244 buffer->ReadWriteUInt8(&flag) &&
245 buffer->ReadWriteUInt8(&default_iv_size) &&
246 buffer->ReadWriteVector(&default_kid, kCencKeyIdSize));
248 is_encrypted = (flag != 0);
250 RCHECK(default_iv_size == 8 || default_iv_size == 16);
252 RCHECK(default_iv_size == 0);
259 atom_size = kFullBoxSize +
sizeof(uint32_t) + kCencKeyIdSize;
263 SchemeInfo::SchemeInfo() {}
264 SchemeInfo::~SchemeInfo() {}
265 FourCC SchemeInfo::BoxType()
const {
return FOURCC_SCHI; }
278 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
279 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
280 FourCC ProtectionSchemeInfo::BoxType()
const {
return FOURCC_SINF; }
287 if (type.type == FOURCC_CENC)
299 if (format.format != FOURCC_NULL) {
306 MovieHeader::MovieHeader()
308 modification_time(0),
314 MovieHeader::~MovieHeader() {}
315 FourCC MovieHeader::BoxType()
const {
return FOURCC_MVHD; }
320 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
323 buffer->ReadWriteUInt32(×cale) &&
326 std::vector<uint8_t> matrix(kUnityMatrix,
327 kUnityMatrix + arraysize(kUnityMatrix));
328 RCHECK(buffer->ReadWriteInt32(&rate) &&
329 buffer->ReadWriteInt16(&volume) &&
331 buffer->ReadWriteVector(&matrix, matrix.size()) &&
333 buffer->ReadWriteUInt32(&next_track_id));
338 version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
339 atom_size = kFullBoxSize +
sizeof(uint32_t) * (1 + version) * 3 +
340 sizeof(timescale) +
sizeof(rate) +
sizeof(volume) +
341 sizeof(next_track_id) +
sizeof(kUnityMatrix) + 10 +
346 TrackHeader::TrackHeader()
348 modification_time(0),
356 flags = kTrackEnabled | kTrackInMovie;
358 TrackHeader::~TrackHeader() {}
359 FourCC TrackHeader::BoxType()
const {
return FOURCC_TKHD; }
364 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
367 buffer->ReadWriteUInt32(&track_id) &&
374 volume = (width != 0 && height != 0) ? 0 : 0x100;
376 std::vector<uint8_t> matrix(kUnityMatrix,
377 kUnityMatrix + arraysize(kUnityMatrix));
379 buffer->ReadWriteInt16(&layer) &&
380 buffer->ReadWriteInt16(&alternate_group) &&
381 buffer->ReadWriteInt16(&volume) &&
383 buffer->ReadWriteVector(&matrix, matrix.size()) &&
384 buffer->ReadWriteUInt32(&width) &&
385 buffer->ReadWriteUInt32(&height));
390 version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
391 atom_size = kFullBoxSize +
sizeof(track_id) +
392 sizeof(uint32_t) * (1 + version) * 3 +
sizeof(layer) +
393 sizeof(alternate_group) +
sizeof(volume) +
sizeof(width) +
394 sizeof(height) +
sizeof(kUnityMatrix) + 14;
398 SampleDescription::SampleDescription() : type(kInvalid) {}
399 SampleDescription::~SampleDescription() {}
400 FourCC SampleDescription::BoxType()
const {
return FOURCC_STSD; }
405 count = video_entries.size();
407 count = audio_entries.size();
409 buffer->ReadWriteUInt32(&count));
414 video_entries.clear();
415 audio_entries.clear();
418 if (type == kVideo) {
420 RCHECK(video_entries.size() == count);
421 }
else if (type == kAudio) {
423 RCHECK(audio_entries.size() == count);
426 DCHECK_LT(0u, count);
427 if (type == kVideo) {
428 for (uint32_t i = 0; i < count; ++i)
429 RCHECK(video_entries[i].
ReadWrite(buffer));
430 }
else if (type == kAudio) {
431 for (uint32_t i = 0; i < count; ++i)
432 RCHECK(audio_entries[i].
ReadWrite(buffer));
441 atom_size = kFullBoxSize +
sizeof(uint32_t);
442 if (type == kVideo) {
443 for (uint32_t i = 0; i < video_entries.size(); ++i)
445 }
else if (type == kAudio) {
446 for (uint32_t i = 0; i < audio_entries.size(); ++i)
452 DecodingTimeToSample::DecodingTimeToSample() {}
453 DecodingTimeToSample::~DecodingTimeToSample() {}
454 FourCC DecodingTimeToSample::BoxType()
const {
return FOURCC_STTS; }
457 uint32_t count = decoding_time.size();
459 buffer->ReadWriteUInt32(&count));
461 decoding_time.resize(count);
462 for (uint32_t i = 0; i < count; ++i) {
463 RCHECK(buffer->ReadWriteUInt32(&decoding_time[i].sample_count) &&
464 buffer->ReadWriteUInt32(&decoding_time[i].sample_delta));
470 atom_size = kFullBoxSize +
sizeof(uint32_t) +
475 CompositionTimeToSample::CompositionTimeToSample() {}
476 CompositionTimeToSample::~CompositionTimeToSample() {}
477 FourCC CompositionTimeToSample::BoxType()
const {
return FOURCC_CTTS; }
480 uint32_t count = composition_offset.size();
486 for (uint32_t i = 0; i < count; ++i) {
487 if (composition_offset[i].sample_offset < 0) {
495 buffer->ReadWriteUInt32(&count));
497 composition_offset.resize(count);
498 for (uint32_t i = 0; i < count; ++i) {
499 RCHECK(buffer->ReadWriteUInt32(&composition_offset[i].sample_count));
502 uint32_t sample_offset = composition_offset[i].sample_offset;
503 RCHECK(buffer->ReadWriteUInt32(&sample_offset));
504 composition_offset[i].sample_offset = sample_offset;
506 int32_t sample_offset = composition_offset[i].sample_offset;
507 RCHECK(buffer->ReadWriteInt32(&sample_offset));
508 composition_offset[i].sample_offset = sample_offset;
517 if (!composition_offset.empty()) {
521 const uint32_t kCompositionOffsetSize =
sizeof(uint32_t) * 2;
522 atom_size = kFullBoxSize +
sizeof(uint32_t) +
523 kCompositionOffsetSize * composition_offset.size();
528 SampleToChunk::SampleToChunk() {}
529 SampleToChunk::~SampleToChunk() {}
530 FourCC SampleToChunk::BoxType()
const {
return FOURCC_STSC; }
533 uint32_t count = chunk_info.size();
535 buffer->ReadWriteUInt32(&count));
537 chunk_info.resize(count);
538 for (uint32_t i = 0; i < count; ++i) {
539 RCHECK(buffer->ReadWriteUInt32(&chunk_info[i].first_chunk) &&
540 buffer->ReadWriteUInt32(&chunk_info[i].samples_per_chunk) &&
541 buffer->ReadWriteUInt32(&chunk_info[i].sample_description_index));
543 RCHECK(i == 0 ? chunk_info[i].first_chunk == 1
544 : chunk_info[i].first_chunk > chunk_info[i - 1].first_chunk);
551 kFullBoxSize +
sizeof(uint32_t) +
sizeof(
ChunkInfo) * chunk_info.size();
555 SampleSize::SampleSize() : sample_size(0), sample_count(0) {}
556 SampleSize::~SampleSize() {}
557 FourCC SampleSize::BoxType()
const {
return FOURCC_STSZ; }
561 buffer->ReadWriteUInt32(&sample_size) &&
562 buffer->ReadWriteUInt32(&sample_count));
564 if (sample_size == 0) {
566 sizes.resize(sample_count);
568 DCHECK(sample_count == sizes.size());
569 for (uint32_t i = 0; i < sample_count; ++i)
570 RCHECK(buffer->ReadWriteUInt32(&sizes[i]));
576 atom_size = kFullBoxSize +
sizeof(sample_size) +
sizeof(sample_count) +
577 (sample_size == 0 ?
sizeof(uint32_t) * sizes.size() : 0);
581 CompactSampleSize::CompactSampleSize() : field_size(0) {}
582 CompactSampleSize::~CompactSampleSize() {}
583 FourCC CompactSampleSize::BoxType()
const {
return FOURCC_STZ2; }
586 uint32_t sample_count = sizes.size();
589 buffer->ReadWriteUInt8(&field_size) &&
590 buffer->ReadWriteUInt32(&sample_count));
593 sizes.resize(sample_count + (field_size == 4 ? 1 : 0), 0);
594 switch (field_size) {
596 for (uint32_t i = 0; i < sample_count; i += 2) {
599 RCHECK(buffer->ReadWriteUInt8(&size));
600 sizes[i] = size >> 4;
601 sizes[i + 1] = size & 0x0F;
603 DCHECK_LT(sizes[i], 16u);
604 DCHECK_LT(sizes[i + 1], 16u);
605 uint8_t size = (sizes[i] << 4) | sizes[i + 1];
606 RCHECK(buffer->ReadWriteUInt8(&size));
611 for (uint32_t i = 0; i < sample_count; ++i) {
612 uint8_t size = sizes[i];
613 RCHECK(buffer->ReadWriteUInt8(&size));
618 for (uint32_t i = 0; i < sample_count; ++i) {
619 uint16_t size = sizes[i];
620 RCHECK(buffer->ReadWriteUInt16(&size));
627 sizes.resize(sample_count);
632 atom_size = kFullBoxSize +
sizeof(uint32_t) +
sizeof(uint32_t) +
633 (field_size * sizes.size() + 7) / 8;
637 ChunkOffset::ChunkOffset() {}
638 ChunkOffset::~ChunkOffset() {}
639 FourCC ChunkOffset::BoxType()
const {
return FOURCC_STCO; }
642 uint32_t count = offsets.size();
644 buffer->ReadWriteUInt32(&count));
646 offsets.resize(count);
647 for (uint32_t i = 0; i < count; ++i)
654 kFullBoxSize +
sizeof(uint32_t) +
sizeof(uint32_t) * offsets.size();
658 ChunkLargeOffset::ChunkLargeOffset() {}
659 ChunkLargeOffset::~ChunkLargeOffset() {}
660 FourCC ChunkLargeOffset::BoxType()
const {
return FOURCC_CO64; }
663 uint32_t count = offsets.size();
667 if (count == 0 || IsFitIn32Bits(offsets[count - 1])) {
669 stco.offsets.swap(offsets);
672 stco.offsets.swap(offsets);
678 buffer->ReadWriteUInt32(&count));
680 offsets.resize(count);
681 for (uint32_t i = 0; i < count; ++i)
682 RCHECK(buffer->ReadWriteUInt64(&offsets[i]));
687 uint32_t count = offsets.size();
688 int use_large_offset =
689 (count > 0 && !IsFitIn32Bits(offsets[count - 1])) ? 1 : 0;
690 atom_size = kFullBoxSize +
sizeof(count) +
691 sizeof(uint32_t) * (1 + use_large_offset) * offsets.size();
695 SyncSample::SyncSample() {}
696 SyncSample::~SyncSample() {}
697 FourCC SyncSample::BoxType()
const {
return FOURCC_STSS; }
700 uint32_t count = sample_number.size();
702 buffer->ReadWriteUInt32(&count));
704 sample_number.resize(count);
705 for (uint32_t i = 0; i < count; ++i)
706 RCHECK(buffer->ReadWriteUInt32(&sample_number[i]));
713 if (!sample_number.empty()) {
714 atom_size = kFullBoxSize +
sizeof(uint32_t) +
715 sizeof(uint32_t) * sample_number.size();
720 SampleTable::SampleTable() {}
721 SampleTable::~SampleTable() {}
722 FourCC SampleTable::BoxType()
const {
return FOURCC_STBL; }
741 RCHECK(reader->
ReadChild(&compact_sample_size));
742 sample_size.sample_size = 0;
743 sample_size.sample_count = compact_sample_size.sizes.size();
744 sample_size.sizes.swap(compact_sample_size.sizes);
748 if (reader->
ChildExist(&chunk_large_offset)) {
749 RCHECK(reader->
ReadChild(&chunk_large_offset));
752 RCHECK(reader->
ReadChild(&chunk_offset));
753 chunk_large_offset.offsets.swap(chunk_offset.offsets);
772 EditList::EditList() {}
773 EditList::~EditList() {}
774 FourCC EditList::BoxType()
const {
return FOURCC_ELST; }
777 uint32_t count = edits.size();
781 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
782 for (uint32_t i = 0; i < count; ++i) {
785 buffer->ReadWriteInt64NBytes(&edits[i].media_time, num_bytes) &&
786 buffer->ReadWriteInt16(&edits[i].media_rate_integer) &&
787 buffer->ReadWriteInt16(&edits[i].media_rate_fraction));
799 for (uint32_t i = 0; i < edits.size(); ++i) {
800 if (!IsFitIn32Bits(edits[i].segment_duration, edits[i].media_time)) {
805 atom_size = kFullBoxSize +
sizeof(uint32_t) +
806 (
sizeof(uint32_t) * (1 + version) * 2 +
sizeof(int16_t) * 2) *
813 FourCC Edit::BoxType()
const {
return FOURCC_EDTS; }
824 if (!list.edits.empty())
829 HandlerReference::HandlerReference() : type(kInvalid) {}
830 HandlerReference::~HandlerReference() {}
831 FourCC HandlerReference::BoxType()
const {
return FOURCC_HDLR; }
834 FourCC hdlr_type = FOURCC_NULL;
835 std::vector<uint8_t> handler_name;
837 if (type == kVideo) {
838 hdlr_type = FOURCC_VIDE;
839 handler_name.assign(kVideoHandlerName,
840 kVideoHandlerName + arraysize(kVideoHandlerName));
841 }
else if (type == kAudio) {
842 hdlr_type = FOURCC_SOUN;
843 handler_name.assign(kAudioHandlerName,
844 kAudioHandlerName + arraysize(kAudioHandlerName));
852 buffer->ReadWriteFourCC(&hdlr_type));
855 if (hdlr_type == FOURCC_VIDE) {
857 }
else if (hdlr_type == FOURCC_SOUN) {
864 buffer->ReadWriteVector(&handler_name, handler_name.size()));
871 kFullBoxSize + kFourCCSize + 16 +
872 (type == kVideo ?
sizeof(kVideoHandlerName) :
sizeof(kAudioHandlerName));
876 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
878 profile_indication(0),
879 profile_compatibility(0),
883 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() {}
884 FourCC AVCDecoderConfigurationRecord::BoxType()
const {
return FOURCC_AVCC; }
889 RCHECK(buffer->ReadWriteVector(&data, buffer->
Size() - buffer->
Pos()));
891 return ParseData(&buffer_reader);
893 RCHECK(buffer->ReadWriteVector(&data, data.size()));
898 bool AVCDecoderConfigurationRecord::ParseData(
BufferReader* reader) {
899 RCHECK(reader->
Read1(&version) && version == 1 &&
900 reader->
Read1(&profile_indication) &&
901 reader->
Read1(&profile_compatibility) &&
902 reader->
Read1(&avc_level));
904 uint8_t length_size_minus_one;
905 RCHECK(reader->
Read1(&length_size_minus_one) &&
906 (length_size_minus_one & 0xfc) == 0xfc);
907 length_size = (length_size_minus_one & 0x3) + 1;
910 RCHECK(reader->
Read1(&num_sps) && (num_sps & 0xe0) == 0xe0);
913 sps_list.resize(num_sps);
914 for (
int i = 0; i < num_sps; i++) {
916 RCHECK(reader->Read2(&sps_length) &&
917 reader->ReadToVector(&sps_list[i], sps_length));
921 RCHECK(reader->
Read1(&num_pps));
923 pps_list.resize(num_pps);
924 for (
int i = 0; i < num_pps; i++) {
926 RCHECK(reader->Read2(&pps_length) &&
927 reader->ReadToVector(&pps_list[i], pps_length));
940 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(0), v_spacing(0) {}
941 PixelAspectRatioBox::~PixelAspectRatioBox() {}
942 FourCC PixelAspectRatioBox::BoxType()
const {
return FOURCC_PASP; }
946 buffer->ReadWriteUInt32(&h_spacing) &&
947 buffer->ReadWriteUInt32(&v_spacing));
954 if (h_spacing != 0 || v_spacing != 0) {
956 DCHECK(h_spacing != 0 && v_spacing != 0);
957 atom_size = kBoxSize +
sizeof(h_spacing) +
sizeof(v_spacing);
962 VideoSampleEntry::VideoSampleEntry()
963 : format(FOURCC_NULL), data_reference_index(1), width(0), height(0) {}
965 VideoSampleEntry::~VideoSampleEntry() {}
966 FourCC VideoSampleEntry::BoxType()
const {
967 LOG(ERROR) <<
"VideoSampleEntry should be parsed according to the "
968 <<
"handler type recovered in its Media ancestor.";
975 format = buffer->
reader()->type();
977 RCHECK(buffer->ReadWriteUInt32(&
atom_size) &&
978 buffer->ReadWriteFourCC(&format));
981 uint32_t video_resolution = kVideoResolution;
982 uint16_t video_frame_count = kVideoFrameCount;
983 uint16_t video_depth = kVideoDepth;
984 int16_t predefined = -1;
986 buffer->ReadWriteUInt16(&data_reference_index) &&
988 buffer->ReadWriteUInt16(&width) &&
989 buffer->ReadWriteUInt16(&height) &&
990 buffer->ReadWriteUInt32(&video_resolution) &&
991 buffer->ReadWriteUInt32(&video_resolution) &&
993 buffer->ReadWriteUInt16(&video_frame_count) &&
995 buffer->ReadWriteUInt16(&video_depth) &&
996 buffer->ReadWriteInt16(&predefined));
1000 if (format == FOURCC_ENCV) {
1004 while (sinf.type.type != FOURCC_CENC) {
1013 if (format == FOURCC_AVC1 ||
1014 (format == FOURCC_ENCV && sinf.format.format == FOURCC_AVC1)) {
1022 atom_size = kBoxSize +
sizeof(data_reference_index) +
sizeof(width) +
1023 sizeof(height) +
sizeof(kVideoResolution) * 2 +
1024 sizeof(kVideoFrameCount) +
sizeof(kVideoDepth) +
1031 ElementaryStreamDescriptor::ElementaryStreamDescriptor() {}
1032 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
1033 FourCC ElementaryStreamDescriptor::BoxType()
const {
return FOURCC_ESDS; }
1038 std::vector<uint8_t> data;
1039 RCHECK(buffer->ReadWriteVector(&data, buffer->
Size() - buffer->
Pos()));
1040 RCHECK(es_descriptor.Parse(data));
1041 if (es_descriptor.
IsAAC()) {
1042 RCHECK(aac_audio_specific_config.
Parse(
1043 es_descriptor.decoder_specific_info()));
1046 DCHECK(buffer->
writer());
1047 es_descriptor.Write(buffer->
writer());
1055 if (es_descriptor.object_type() != kForbidden)
1056 atom_size = kFullBoxSize + es_descriptor.ComputeSize();
1060 AudioSampleEntry::AudioSampleEntry()
1061 : format(FOURCC_NULL),
1062 data_reference_index(1),
1067 AudioSampleEntry::~AudioSampleEntry() {}
1069 FourCC AudioSampleEntry::BoxType()
const {
1070 LOG(ERROR) <<
"AudioSampleEntry should be parsed according to the "
1071 <<
"handler type recovered in its Media ancestor.";
1077 DCHECK(buffer->
reader());
1078 format = buffer->
reader()->type();
1080 RCHECK(buffer->ReadWriteUInt32(&
atom_size) &&
1081 buffer->ReadWriteFourCC(&format));
1087 buffer->ReadWriteUInt16(&data_reference_index) &&
1089 buffer->ReadWriteUInt16(&channelcount) &&
1090 buffer->ReadWriteUInt16(&samplesize) &&
1092 buffer->ReadWriteUInt32(&samplerate));
1097 if (format == FOURCC_ENCA) {
1101 while (sinf.type.type != FOURCC_CENC) {
1116 atom_size = kBoxSize +
sizeof(data_reference_index) +
sizeof(channelcount) +
1117 sizeof(samplesize) +
sizeof(samplerate) + sinf.
ComputeSize() +
1123 MediaHeader::MediaHeader()
1124 : creation_time(0), modification_time(0), timescale(0), duration(0) {
1127 MediaHeader::~MediaHeader() {}
1128 FourCC MediaHeader::BoxType()
const {
return FOURCC_MDHD; }
1133 uint8_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1136 buffer->ReadWriteUInt32(×cale) &&
1142 std::vector<uint8_t> temp;
1143 RCHECK(buffer->ReadWriteVector(&temp, 2));
1146 bit_reader.SkipBits(1);
1147 for (
int i = 0; i < 3; ++i) {
1148 CHECK(bit_reader.ReadBits(5, &language[i]));
1149 language[i] += 0x60;
1154 const char kUndefinedLanguage[] =
"und";
1155 if (language[0] == 0)
1156 strcpy(language, kUndefinedLanguage);
1160 for (
int i = 0; i < 3; ++i)
1161 lang |= (language[i] - 0x60) << ((2 - i) * 5);
1162 RCHECK(buffer->ReadWriteUInt16(&lang));
1170 version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
1171 atom_size = kFullBoxSize +
sizeof(timescale) +
1172 sizeof(uint32_t) * (1 + version) * 3 + 2 +
1177 VideoMediaHeader::VideoMediaHeader()
1178 : graphicsmode(0), opcolor_red(0), opcolor_green(0), opcolor_blue(0) {
1179 const uint32_t kVideoMediaHeaderFlags = 1;
1180 flags = kVideoMediaHeaderFlags;
1182 VideoMediaHeader::~VideoMediaHeader() {}
1183 FourCC VideoMediaHeader::BoxType()
const {
return FOURCC_VMHD; }
1186 buffer->ReadWriteUInt16(&graphicsmode) &&
1187 buffer->ReadWriteUInt16(&opcolor_red) &&
1188 buffer->ReadWriteUInt16(&opcolor_green) &&
1189 buffer->ReadWriteUInt16(&opcolor_blue));
1194 atom_size = kFullBoxSize +
sizeof(graphicsmode) +
sizeof(opcolor_red) +
1195 sizeof(opcolor_green) +
sizeof(opcolor_blue);
1199 SoundMediaHeader::SoundMediaHeader() : balance(0) {}
1200 SoundMediaHeader::~SoundMediaHeader() {}
1201 FourCC SoundMediaHeader::BoxType()
const {
return FOURCC_SMHD; }
1204 buffer->ReadWriteUInt16(&balance) &&
1210 atom_size = kFullBoxSize +
sizeof(balance) +
sizeof(uint16_t);
1214 DataEntryUrl::DataEntryUrl() {
1215 const uint32_t kDataEntryUrlFlags = 1;
1216 flags = kDataEntryUrlFlags;
1218 DataEntryUrl::~DataEntryUrl() {}
1219 FourCC DataEntryUrl::BoxType()
const {
return FOURCC_URL; }
1223 RCHECK(buffer->ReadWriteVector(&location, buffer->
Size() - buffer->
Pos()));
1225 RCHECK(buffer->ReadWriteVector(&location, location.size()));
1231 atom_size = kBoxSize +
sizeof(flags) + location.size();
1235 DataReference::DataReference() {
1237 data_entry.resize(1);
1239 DataReference::~DataReference() {}
1240 FourCC DataReference::BoxType()
const {
return FOURCC_DREF; }
1242 uint32_t entry_count = data_entry.size();
1244 buffer->ReadWriteUInt32(&entry_count));
1245 data_entry.resize(entry_count);
1247 for (uint32_t i = 0; i < entry_count; ++i)
1253 uint32_t count = data_entry.size();
1254 atom_size = kFullBoxSize +
sizeof(count);
1255 for (uint32_t i = 0; i < count; ++i)
1260 DataInformation::DataInformation() {}
1261 DataInformation::~DataInformation() {}
1262 FourCC DataInformation::BoxType()
const {
return FOURCC_DINF; }
1275 MediaInformation::MediaInformation() {}
1276 MediaInformation::~MediaInformation() {}
1277 FourCC MediaInformation::BoxType()
const {
return FOURCC_MINF; }
1284 if (sample_table.description.type == kVideo)
1286 else if (sample_table.description.type == kAudio)
1296 if (sample_table.description.type == kVideo)
1298 else if (sample_table.description.type == kAudio)
1305 FourCC Media::BoxType()
const {
return FOURCC_MDIA; }
1319 information.sample_table.description.type = handler.type;
1321 DCHECK_EQ(information.sample_table.description.type, handler.type);
1335 FourCC Track::BoxType()
const {
return FOURCC_TRAK; }
1352 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
1353 MovieExtendsHeader::~MovieExtendsHeader() {}
1354 FourCC MovieExtendsHeader::BoxType()
const {
return FOURCC_MEHD; }
1358 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1366 if (fragment_duration != 0) {
1367 version = IsFitIn32Bits(fragment_duration) ? 0 : 1;
1368 atom_size = kFullBoxSize +
sizeof(uint32_t) * (1 + version);
1373 TrackExtends::TrackExtends()
1375 default_sample_description_index(0),
1376 default_sample_duration(0),
1377 default_sample_size(0),
1378 default_sample_flags(0) {}
1379 TrackExtends::~TrackExtends() {}
1380 FourCC TrackExtends::BoxType()
const {
return FOURCC_TREX; }
1384 buffer->ReadWriteUInt32(&track_id) &&
1385 buffer->ReadWriteUInt32(&default_sample_description_index) &&
1386 buffer->ReadWriteUInt32(&default_sample_duration) &&
1387 buffer->ReadWriteUInt32(&default_sample_size) &&
1388 buffer->ReadWriteUInt32(&default_sample_flags));
1393 atom_size = kFullBoxSize +
sizeof(track_id) +
1394 sizeof(default_sample_description_index) +
1395 sizeof(default_sample_duration) +
sizeof(default_sample_size) +
1396 sizeof(default_sample_flags);
1400 MovieExtends::MovieExtends() {}
1401 MovieExtends::~MovieExtends() {}
1402 FourCC MovieExtends::BoxType()
const {
return FOURCC_MVEX; }
1409 DCHECK(buffer->
reader());
1412 for (uint32_t i = 0; i < tracks.size(); ++i)
1421 if (tracks.size() != 0) {
1423 for (uint32_t i = 0; i < tracks.size(); ++i)
1431 FourCC Movie::BoxType()
const {
return FOURCC_MOOV; }
1444 for (uint32_t i = 0; i < tracks.size(); ++i)
1446 for (uint32_t i = 0; i < pssh.size(); ++i)
1454 for (uint32_t i = 0; i < tracks.size(); ++i)
1456 for (uint32_t i = 0; i < pssh.size(); ++i)
1461 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
1462 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
1463 FourCC TrackFragmentDecodeTime::BoxType()
const {
return FOURCC_TFDT; }
1467 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1473 version = IsFitIn32Bits(decode_time) ? 0 : 1;
1474 atom_size = kFullBoxSize +
sizeof(uint32_t) * (1 + version);
1478 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
1479 MovieFragmentHeader::~MovieFragmentHeader() {}
1480 FourCC MovieFragmentHeader::BoxType()
const {
return FOURCC_MFHD; }
1484 buffer->ReadWriteUInt32(&sequence_number);
1488 atom_size = kFullBoxSize +
sizeof(sequence_number);
1492 TrackFragmentHeader::TrackFragmentHeader()
1494 sample_description_index(0),
1495 default_sample_duration(0),
1496 default_sample_size(0),
1497 default_sample_flags(0) {}
1499 TrackFragmentHeader::~TrackFragmentHeader() {}
1500 FourCC TrackFragmentHeader::BoxType()
const {
return FOURCC_TFHD; }
1504 buffer->ReadWriteUInt32(&track_id));
1506 if (flags & kBaseDataOffsetPresentMask) {
1511 uint64_t base_data_offset;
1512 RCHECK(buffer->ReadWriteUInt64(&base_data_offset));
1513 DLOG(WARNING) <<
"base-data-offset-present is not expected. Assumes "
1514 "default-base-is-moof.";
1517 if (flags & kSampleDescriptionIndexPresentMask) {
1518 RCHECK(buffer->ReadWriteUInt32(&sample_description_index));
1519 }
else if (buffer->
Reading()) {
1520 sample_description_index = 0;
1523 if (flags & kDefaultSampleDurationPresentMask) {
1524 RCHECK(buffer->ReadWriteUInt32(&default_sample_duration));
1525 }
else if (buffer->
Reading()) {
1526 default_sample_duration = 0;
1529 if (flags & kDefaultSampleSizePresentMask) {
1530 RCHECK(buffer->ReadWriteUInt32(&default_sample_size));
1531 }
else if (buffer->
Reading()) {
1532 default_sample_size = 0;
1535 if (flags & kDefaultSampleFlagsPresentMask)
1536 RCHECK(buffer->ReadWriteUInt32(&default_sample_flags));
1541 atom_size = kFullBoxSize +
sizeof(track_id);
1542 if (flags & kSampleDescriptionIndexPresentMask)
1543 atom_size +=
sizeof(sample_description_index);
1544 if (flags & kDefaultSampleDurationPresentMask)
1545 atom_size +=
sizeof(default_sample_duration);
1546 if (flags & kDefaultSampleSizePresentMask)
1547 atom_size +=
sizeof(default_sample_size);
1548 if (flags & kDefaultSampleFlagsPresentMask)
1549 atom_size +=
sizeof(default_sample_flags);
1553 TrackFragmentRun::TrackFragmentRun() : sample_count(0), data_offset(0) {}
1554 TrackFragmentRun::~TrackFragmentRun() {}
1555 FourCC TrackFragmentRun::BoxType()
const {
return FOURCC_TRUN; }
1563 if (flags & kSampleCompTimeOffsetsPresentMask) {
1564 for (uint32_t i = 0; i < sample_count; ++i) {
1565 if (sample_composition_time_offsets[i] < 0) {
1574 buffer->ReadWriteUInt32(&sample_count));
1576 bool data_offset_present = (flags & kDataOffsetPresentMask) != 0;
1577 bool first_sample_flags_present = (flags & kFirstSampleFlagsPresentMask) != 0;
1578 bool sample_duration_present = (flags & kSampleDurationPresentMask) != 0;
1579 bool sample_size_present = (flags & kSampleSizePresentMask) != 0;
1580 bool sample_flags_present = (flags & kSampleFlagsPresentMask) != 0;
1581 bool sample_composition_time_offsets_present =
1582 (flags & kSampleCompTimeOffsetsPresentMask) != 0;
1584 if (data_offset_present) {
1585 RCHECK(buffer->ReadWriteUInt32(&data_offset));
1596 uint32_t first_sample_flags;
1599 if (first_sample_flags_present)
1600 RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
1602 if (sample_duration_present)
1603 sample_durations.resize(sample_count);
1604 if (sample_size_present)
1605 sample_sizes.resize(sample_count);
1606 if (sample_flags_present)
1607 sample_flags.resize(sample_count);
1608 if (sample_composition_time_offsets_present)
1609 sample_composition_time_offsets.resize(sample_count);
1611 if (first_sample_flags_present) {
1612 first_sample_flags = sample_flags[0];
1613 DCHECK(sample_flags.size() == 1);
1614 RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
1617 if (sample_duration_present)
1618 DCHECK(sample_durations.size() == sample_count);
1619 if (sample_size_present)
1620 DCHECK(sample_sizes.size() == sample_count);
1621 if (sample_flags_present)
1622 DCHECK(sample_flags.size() == sample_count);
1623 if (sample_composition_time_offsets_present)
1624 DCHECK(sample_composition_time_offsets.size() == sample_count);
1627 for (uint32_t i = 0; i < sample_count; ++i) {
1628 if (sample_duration_present)
1629 RCHECK(buffer->ReadWriteUInt32(&sample_durations[i]));
1630 if (sample_size_present)
1631 RCHECK(buffer->ReadWriteUInt32(&sample_sizes[i]));
1632 if (sample_flags_present)
1633 RCHECK(buffer->ReadWriteUInt32(&sample_flags[i]));
1635 if (sample_composition_time_offsets_present) {
1637 uint32_t sample_offset = sample_composition_time_offsets[i];
1638 RCHECK(buffer->ReadWriteUInt32(&sample_offset));
1639 sample_composition_time_offsets[i] = sample_offset;
1641 int32_t sample_offset = sample_composition_time_offsets[i];
1642 RCHECK(buffer->ReadWriteInt32(&sample_offset));
1643 sample_composition_time_offsets[i] = sample_offset;
1649 if (first_sample_flags_present) {
1650 if (sample_flags.size() == 0) {
1651 sample_flags.push_back(first_sample_flags);
1653 sample_flags[0] = first_sample_flags;
1661 atom_size = kFullBoxSize +
sizeof(sample_count);
1662 if (flags & kDataOffsetPresentMask)
1664 if (flags & kFirstSampleFlagsPresentMask)
1666 uint32_t fields = (flags & kSampleDurationPresentMask ? 1 : 0) +
1667 (flags & kSampleSizePresentMask ? 1 : 0) +
1668 (flags & kSampleFlagsPresentMask ? 1 : 0) +
1669 (flags & kSampleCompTimeOffsetsPresentMask ? 1 : 0);
1670 atom_size += fields *
sizeof(uint32_t) * sample_count;
1674 SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
1675 SampleToGroup::~SampleToGroup() {}
1676 FourCC SampleToGroup::BoxType()
const {
return FOURCC_SBGP; }
1680 buffer->ReadWriteUInt32(&grouping_type));
1682 RCHECK(buffer->ReadWriteUInt32(&grouping_type_parameter));
1684 if (grouping_type != FOURCC_SEIG) {
1686 DLOG(WARNING) <<
"Sample group '" << grouping_type <<
"' is not supported.";
1690 uint32_t count = entries.size();
1691 RCHECK(buffer->ReadWriteUInt32(&count));
1692 entries.resize(count);
1693 for (uint32_t i = 0; i < count; ++i) {
1694 RCHECK(buffer->ReadWriteUInt32(&entries[i].sample_count) &&
1695 buffer->ReadWriteUInt32(&entries[i].group_description_index));
1703 if (!entries.empty()) {
1704 atom_size = kFullBoxSize +
sizeof(grouping_type) +
1705 (version == 1 ?
sizeof(grouping_type_parameter) : 0) +
1706 sizeof(uint32_t) + entries.size() *
sizeof(entries[0]);
1711 CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
1712 : is_encrypted(false), iv_size(0) {
1714 CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {};
1716 SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
1717 SampleGroupDescription::~SampleGroupDescription() {}
1718 FourCC SampleGroupDescription::BoxType()
const {
return FOURCC_SGPD; }
1722 buffer->ReadWriteUInt32(&grouping_type));
1724 if (grouping_type != FOURCC_SEIG) {
1726 DLOG(WARNING) <<
"Sample group '" << grouping_type <<
"' is not supported.";
1730 const size_t kEntrySize =
sizeof(uint32_t) + kCencKeyIdSize;
1731 uint32_t default_length = 0;
1734 RCHECK(buffer->ReadWriteUInt32(&default_length));
1735 RCHECK(default_length == 0 || default_length >= kEntrySize);
1737 default_length = kEntrySize;
1738 RCHECK(buffer->ReadWriteUInt32(&default_length));
1742 uint32_t count = entries.size();
1743 RCHECK(buffer->ReadWriteUInt32(&count));
1744 entries.resize(count);
1745 for (uint32_t i = 0; i < count; ++i) {
1747 if (buffer->
Reading() && default_length == 0) {
1748 uint32_t description_length = 0;
1749 RCHECK(buffer->ReadWriteUInt32(&description_length));
1750 RCHECK(description_length >= kEntrySize);
1755 if (entries[i].key_id.size() != kCencKeyIdSize) {
1756 LOG(WARNING) <<
"CENC defines key id length of " << kCencKeyIdSize
1757 <<
" bytes; got " << entries[i].key_id.size()
1758 <<
". Resized accordingly.";
1759 entries[i].key_id.resize(kCencKeyIdSize);
1763 uint8_t flag = entries[i].is_encrypted ? 1 : 0;
1765 buffer->ReadWriteUInt8(&flag) &&
1766 buffer->ReadWriteUInt8(&entries[i].iv_size) &&
1767 buffer->ReadWriteVector(&entries[i].key_id, kCencKeyIdSize));
1770 entries[i].is_encrypted = (flag != 0);
1771 if (entries[i].is_encrypted) {
1772 RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
1774 RCHECK(entries[i].iv_size == 0);
1786 if (!entries.empty()) {
1787 const size_t kEntrySize =
sizeof(uint32_t) + kCencKeyIdSize;
1788 atom_size = kFullBoxSize +
sizeof(grouping_type) +
1789 (version == 1 ?
sizeof(uint32_t) : 0) +
sizeof(uint32_t) +
1790 entries.size() * kEntrySize;
1795 TrackFragment::TrackFragment() : decode_time_absent(false) {}
1796 TrackFragment::~TrackFragment() {}
1797 FourCC TrackFragment::BoxType()
const {
return FOURCC_TRAF; }
1804 DCHECK(buffer->
reader());
1806 if (!decode_time_absent)
1814 while (sample_to_group.grouping_type != FOURCC_SEIG &&
1818 while (sample_group_description.grouping_type != FOURCC_SEIG &&
1823 if (!decode_time_absent)
1825 for (uint32_t i = 0; i < runs.size(); ++i)
1839 for (uint32_t i = 0; i < runs.size(); ++i)
1844 MovieFragment::MovieFragment() {}
1845 MovieFragment::~MovieFragment() {}
1846 FourCC MovieFragment::BoxType()
const {
return FOURCC_MOOF; }
1858 for (uint32_t i = 0; i < tracks.size(); ++i)
1860 for (uint32_t i = 0; i < pssh.size(); ++i)
1868 for (uint32_t i = 0; i < tracks.size(); ++i)
1870 for (uint32_t i = 0; i < pssh.size(); ++i)
1875 SegmentIndex::SegmentIndex()
1878 earliest_presentation_time(0),
1880 SegmentIndex::~SegmentIndex() {}
1881 FourCC SegmentIndex::BoxType()
const {
return FOURCC_SIDX; }
1885 buffer->ReadWriteUInt32(&reference_id) &&
1886 buffer->ReadWriteUInt32(×cale));
1888 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1893 uint16_t reference_count = references.size();
1895 buffer->ReadWriteUInt16(&reference_count));
1896 references.resize(reference_count);
1898 uint32_t reference_type_size;
1900 for (uint32_t i = 0; i < reference_count; ++i) {
1902 reference_type_size = references[i].referenced_size;
1903 if (references[i].reference_type)
1904 reference_type_size |= (1 << 31);
1905 sap = (references[i].sap_type << 28) | references[i].sap_delta_time;
1906 if (references[i].starts_with_sap)
1909 RCHECK(buffer->ReadWriteUInt32(&reference_type_size) &&
1910 buffer->ReadWriteUInt32(&references[i].subsegment_duration) &&
1911 buffer->ReadWriteUInt32(&sap));
1913 references[i].reference_type = (reference_type_size >> 31) ?
true :
false;
1914 references[i].referenced_size = reference_type_size & ~(1 << 31);
1915 references[i].starts_with_sap = (sap >> 31) ?
true :
false;
1916 references[i].sap_type =
1917 static_cast<SegmentReference::SAPType
>((sap >> 28) & 0x07);
1918 references[i].sap_delta_time = sap & ~(0xF << 28);
1925 version = IsFitIn32Bits(earliest_presentation_time, first_offset) ? 0 : 1;
1926 atom_size = kFullBoxSize +
sizeof(reference_id) +
sizeof(timescale) +
1927 sizeof(uint32_t) * (1 + version) * 2 + 2 *
sizeof(uint16_t) +
1928 3 *
sizeof(uint32_t) * references.size();
1932 MediaData::MediaData() : data_size(0) {}
1933 MediaData::~MediaData() {}
1934 FourCC MediaData::BoxType()
const {
return FOURCC_MDAT; }
1936 void MediaData::Write(BufferWriter* buffer) {
1937 buffer->AppendInt(ComputeSize());
1938 buffer->AppendInt(static_cast<uint32_t>(BoxType()));
1941 uint32_t MediaData::ComputeSize() {
1942 return kBoxSize + data_size;
bool ReadWrite(BoxBuffer *buffer) override
Read/write the mp4 box from/to BoxBuffer.
bool ReadWrite(BoxBuffer *buffer) override
Read/write the mp4 box from/to BoxBuffer.
uint32_t ComputeSize() override
uint32_t ComputeSize() override
uint32_t ComputeSize() override
bool ReadWrite(BoxBuffer *buffer) override
Read/write the mp4 box from/to BoxBuffer.