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;
38 const uint32_t kCompressorNameSize = 32u;
39 const char kAvcCompressorName[] =
"\012AVC Coding";
40 const char kVpcCompressorName[] =
"\012VPC Coding";
43 bool IsFitIn32Bits(uint64_t a) {
44 return a <= std::numeric_limits<uint32_t>::max();
47 bool IsFitIn32Bits(int64_t a) {
48 return a <= std::numeric_limits<int32_t>::max() &&
49 a >= std::numeric_limits<int32_t>::min();
52 template <
typename T1,
typename T2>
53 bool IsFitIn32Bits(T1 a1, T2 a2) {
54 return IsFitIn32Bits(a1) && IsFitIn32Bits(a2);
57 template <
typename T1,
typename T2,
typename T3>
58 bool IsFitIn32Bits(T1 a1, T2 a2, T3 a3) {
59 return IsFitIn32Bits(a1) && IsFitIn32Bits(a2) && IsFitIn32Bits(a3);
64 namespace edash_packager {
68 FileType::FileType() : major_brand(FOURCC_NULL), minor_version(0) {}
69 FileType::~FileType() {}
70 FourCC FileType::BoxType()
const {
return FOURCC_FTYP; }
74 buffer->ReadWriteFourCC(&major_brand) &&
75 buffer->ReadWriteUInt32(&minor_version));
78 num_brands = (buffer->
Size() - buffer->
Pos()) /
sizeof(FourCC);
79 compatible_brands.resize(num_brands);
81 num_brands = compatible_brands.size();
83 for (
size_t i = 0; i < num_brands; ++i)
84 RCHECK(buffer->ReadWriteFourCC(&compatible_brands[i]));
89 atom_size = kBoxSize + kFourCCSize +
sizeof(minor_version) +
90 kFourCCSize * compatible_brands.size();
94 SegmentType::SegmentType() {}
95 SegmentType::~SegmentType() {}
96 FourCC SegmentType::BoxType()
const {
return FOURCC_STYP; }
106 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
107 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
108 FourCC ProtectionSystemSpecificHeader::BoxType()
const {
return FOURCC_PSSH; }
111 if (!buffer->
Reading() && !raw_box.empty()) {
113 buffer->
writer()->AppendVector(raw_box);
117 uint32_t size = data.size();
119 buffer->ReadWriteVector(&system_id, 16) &&
120 buffer->ReadWriteUInt32(&size) &&
121 buffer->ReadWriteVector(&data, size));
126 DCHECK(raw_box.empty());
129 raw_box.assign(reader->data(), reader->data() + reader->size());
135 if (!raw_box.empty()) {
139 kFullBoxSize + system_id.size() +
sizeof(uint32_t) + data.size();
144 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
145 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
146 FourCC SampleAuxiliaryInformationOffset::BoxType()
const {
return FOURCC_SAIO; }
153 uint32_t count = offsets.size();
154 RCHECK(buffer->ReadWriteUInt32(&count));
155 offsets.resize(count);
157 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
158 for (uint32_t i = 0; i < count; ++i)
166 if (offsets.size() != 0) {
167 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
168 atom_size = kFullBoxSize +
sizeof(uint32_t) + num_bytes * offsets.size();
173 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
174 : default_sample_info_size(0), sample_count(0) {}
175 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
176 FourCC SampleAuxiliaryInformationSize::BoxType()
const {
return FOURCC_SAIZ; }
183 RCHECK(buffer->ReadWriteUInt8(&default_sample_info_size) &&
184 buffer->ReadWriteUInt32(&sample_count));
185 if (default_sample_info_size == 0)
186 RCHECK(buffer->ReadWriteVector(&sample_info_sizes, sample_count));
193 if (sample_count != 0) {
194 atom_size = kFullBoxSize +
sizeof(default_sample_info_size) +
195 sizeof(sample_count) +
196 (default_sample_info_size == 0 ? sample_info_sizes.size() : 0);
201 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
202 OriginalFormat::~OriginalFormat() {}
203 FourCC OriginalFormat::BoxType()
const {
return FOURCC_FRMA; }
206 return Box::ReadWrite(buffer) && buffer->ReadWriteFourCC(&format);
214 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
215 SchemeType::~SchemeType() {}
216 FourCC SchemeType::BoxType()
const {
return FOURCC_SCHM; }
220 buffer->ReadWriteFourCC(&type) &&
221 buffer->ReadWriteUInt32(&version));
226 atom_size = kFullBoxSize + kFourCCSize +
sizeof(version);
230 TrackEncryption::TrackEncryption()
231 : is_encrypted(false), default_iv_size(0), default_kid(16, 0) {}
232 TrackEncryption::~TrackEncryption() {}
233 FourCC TrackEncryption::BoxType()
const {
return FOURCC_TENC; }
237 if (default_kid.size() != kCencKeyIdSize) {
238 LOG(WARNING) <<
"CENC defines key id length of " << kCencKeyIdSize
239 <<
" bytes; got " << default_kid.size()
240 <<
". Resized accordingly.";
241 default_kid.resize(kCencKeyIdSize);
245 uint8_t flag = is_encrypted ? 1 : 0;
248 buffer->ReadWriteUInt8(&flag) &&
249 buffer->ReadWriteUInt8(&default_iv_size) &&
250 buffer->ReadWriteVector(&default_kid, kCencKeyIdSize));
252 is_encrypted = (flag != 0);
254 RCHECK(default_iv_size == 8 || default_iv_size == 16);
256 RCHECK(default_iv_size == 0);
263 atom_size = kFullBoxSize +
sizeof(uint32_t) + kCencKeyIdSize;
267 SchemeInfo::SchemeInfo() {}
268 SchemeInfo::~SchemeInfo() {}
269 FourCC SchemeInfo::BoxType()
const {
return FOURCC_SCHI; }
282 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
283 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
284 FourCC ProtectionSchemeInfo::BoxType()
const {
return FOURCC_SINF; }
291 if (type.type == FOURCC_CENC)
303 if (format.format != FOURCC_NULL) {
310 MovieHeader::MovieHeader()
312 modification_time(0),
318 MovieHeader::~MovieHeader() {}
319 FourCC MovieHeader::BoxType()
const {
return FOURCC_MVHD; }
324 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
327 buffer->ReadWriteUInt32(×cale) &&
330 std::vector<uint8_t> matrix(kUnityMatrix,
331 kUnityMatrix + arraysize(kUnityMatrix));
332 RCHECK(buffer->ReadWriteInt32(&rate) &&
333 buffer->ReadWriteInt16(&volume) &&
335 buffer->ReadWriteVector(&matrix, matrix.size()) &&
337 buffer->ReadWriteUInt32(&next_track_id));
342 version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
343 atom_size = kFullBoxSize +
sizeof(uint32_t) * (1 + version) * 3 +
344 sizeof(timescale) +
sizeof(rate) +
sizeof(volume) +
345 sizeof(next_track_id) +
sizeof(kUnityMatrix) + 10 +
350 TrackHeader::TrackHeader()
352 modification_time(0),
360 flags = kTrackEnabled | kTrackInMovie;
362 TrackHeader::~TrackHeader() {}
363 FourCC TrackHeader::BoxType()
const {
return FOURCC_TKHD; }
368 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
371 buffer->ReadWriteUInt32(&track_id) &&
378 volume = (width != 0 && height != 0) ? 0 : 0x100;
380 std::vector<uint8_t> matrix(kUnityMatrix,
381 kUnityMatrix + arraysize(kUnityMatrix));
383 buffer->ReadWriteInt16(&layer) &&
384 buffer->ReadWriteInt16(&alternate_group) &&
385 buffer->ReadWriteInt16(&volume) &&
387 buffer->ReadWriteVector(&matrix, matrix.size()) &&
388 buffer->ReadWriteUInt32(&width) &&
389 buffer->ReadWriteUInt32(&height));
394 version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
395 atom_size = kFullBoxSize +
sizeof(track_id) +
396 sizeof(uint32_t) * (1 + version) * 3 +
sizeof(layer) +
397 sizeof(alternate_group) +
sizeof(volume) +
sizeof(width) +
398 sizeof(height) +
sizeof(kUnityMatrix) + 14;
402 SampleDescription::SampleDescription() : type(kInvalid) {}
403 SampleDescription::~SampleDescription() {}
404 FourCC SampleDescription::BoxType()
const {
return FOURCC_STSD; }
409 count = video_entries.size();
411 count = audio_entries.size();
413 buffer->ReadWriteUInt32(&count));
418 video_entries.clear();
419 audio_entries.clear();
422 if (type == kVideo) {
424 RCHECK(video_entries.size() == count);
425 }
else if (type == kAudio) {
427 RCHECK(audio_entries.size() == count);
430 DCHECK_LT(0u, count);
431 if (type == kVideo) {
432 for (uint32_t i = 0; i < count; ++i)
433 RCHECK(video_entries[i].
ReadWrite(buffer));
434 }
else if (type == kAudio) {
435 for (uint32_t i = 0; i < count; ++i)
436 RCHECK(audio_entries[i].
ReadWrite(buffer));
445 atom_size = kFullBoxSize +
sizeof(uint32_t);
446 if (type == kVideo) {
447 for (uint32_t i = 0; i < video_entries.size(); ++i)
449 }
else if (type == kAudio) {
450 for (uint32_t i = 0; i < audio_entries.size(); ++i)
456 DecodingTimeToSample::DecodingTimeToSample() {}
457 DecodingTimeToSample::~DecodingTimeToSample() {}
458 FourCC DecodingTimeToSample::BoxType()
const {
return FOURCC_STTS; }
461 uint32_t count = decoding_time.size();
463 buffer->ReadWriteUInt32(&count));
465 decoding_time.resize(count);
466 for (uint32_t i = 0; i < count; ++i) {
467 RCHECK(buffer->ReadWriteUInt32(&decoding_time[i].sample_count) &&
468 buffer->ReadWriteUInt32(&decoding_time[i].sample_delta));
474 atom_size = kFullBoxSize +
sizeof(uint32_t) +
479 CompositionTimeToSample::CompositionTimeToSample() {}
480 CompositionTimeToSample::~CompositionTimeToSample() {}
481 FourCC CompositionTimeToSample::BoxType()
const {
return FOURCC_CTTS; }
484 uint32_t count = composition_offset.size();
490 for (uint32_t i = 0; i < count; ++i) {
491 if (composition_offset[i].sample_offset < 0) {
499 buffer->ReadWriteUInt32(&count));
501 composition_offset.resize(count);
502 for (uint32_t i = 0; i < count; ++i) {
503 RCHECK(buffer->ReadWriteUInt32(&composition_offset[i].sample_count));
506 uint32_t sample_offset = composition_offset[i].sample_offset;
507 RCHECK(buffer->ReadWriteUInt32(&sample_offset));
508 composition_offset[i].sample_offset = sample_offset;
510 int32_t sample_offset = composition_offset[i].sample_offset;
511 RCHECK(buffer->ReadWriteInt32(&sample_offset));
512 composition_offset[i].sample_offset = sample_offset;
521 if (!composition_offset.empty()) {
525 const uint32_t kCompositionOffsetSize =
sizeof(uint32_t) * 2;
526 atom_size = kFullBoxSize +
sizeof(uint32_t) +
527 kCompositionOffsetSize * composition_offset.size();
532 SampleToChunk::SampleToChunk() {}
533 SampleToChunk::~SampleToChunk() {}
534 FourCC SampleToChunk::BoxType()
const {
return FOURCC_STSC; }
537 uint32_t count = chunk_info.size();
539 buffer->ReadWriteUInt32(&count));
541 chunk_info.resize(count);
542 for (uint32_t i = 0; i < count; ++i) {
543 RCHECK(buffer->ReadWriteUInt32(&chunk_info[i].first_chunk) &&
544 buffer->ReadWriteUInt32(&chunk_info[i].samples_per_chunk) &&
545 buffer->ReadWriteUInt32(&chunk_info[i].sample_description_index));
547 RCHECK(i == 0 ? chunk_info[i].first_chunk == 1
548 : chunk_info[i].first_chunk > chunk_info[i - 1].first_chunk);
555 kFullBoxSize +
sizeof(uint32_t) +
sizeof(
ChunkInfo) * chunk_info.size();
559 SampleSize::SampleSize() : sample_size(0), sample_count(0) {}
560 SampleSize::~SampleSize() {}
561 FourCC SampleSize::BoxType()
const {
return FOURCC_STSZ; }
565 buffer->ReadWriteUInt32(&sample_size) &&
566 buffer->ReadWriteUInt32(&sample_count));
568 if (sample_size == 0) {
570 sizes.resize(sample_count);
572 DCHECK(sample_count == sizes.size());
573 for (uint32_t i = 0; i < sample_count; ++i)
574 RCHECK(buffer->ReadWriteUInt32(&sizes[i]));
580 atom_size = kFullBoxSize +
sizeof(sample_size) +
sizeof(sample_count) +
581 (sample_size == 0 ?
sizeof(uint32_t) * sizes.size() : 0);
585 CompactSampleSize::CompactSampleSize() : field_size(0) {}
586 CompactSampleSize::~CompactSampleSize() {}
587 FourCC CompactSampleSize::BoxType()
const {
return FOURCC_STZ2; }
590 uint32_t sample_count = sizes.size();
593 buffer->ReadWriteUInt8(&field_size) &&
594 buffer->ReadWriteUInt32(&sample_count));
597 sizes.resize(sample_count + (field_size == 4 ? 1 : 0), 0);
598 switch (field_size) {
600 for (uint32_t i = 0; i < sample_count; i += 2) {
603 RCHECK(buffer->ReadWriteUInt8(&size));
604 sizes[i] = size >> 4;
605 sizes[i + 1] = size & 0x0F;
607 DCHECK_LT(sizes[i], 16u);
608 DCHECK_LT(sizes[i + 1], 16u);
609 uint8_t size = (sizes[i] << 4) | sizes[i + 1];
610 RCHECK(buffer->ReadWriteUInt8(&size));
615 for (uint32_t i = 0; i < sample_count; ++i) {
616 uint8_t size = sizes[i];
617 RCHECK(buffer->ReadWriteUInt8(&size));
622 for (uint32_t i = 0; i < sample_count; ++i) {
623 uint16_t size = sizes[i];
624 RCHECK(buffer->ReadWriteUInt16(&size));
631 sizes.resize(sample_count);
636 atom_size = kFullBoxSize +
sizeof(uint32_t) +
sizeof(uint32_t) +
637 (field_size * sizes.size() + 7) / 8;
641 ChunkOffset::ChunkOffset() {}
642 ChunkOffset::~ChunkOffset() {}
643 FourCC ChunkOffset::BoxType()
const {
return FOURCC_STCO; }
646 uint32_t count = offsets.size();
648 buffer->ReadWriteUInt32(&count));
650 offsets.resize(count);
651 for (uint32_t i = 0; i < count; ++i)
658 kFullBoxSize +
sizeof(uint32_t) +
sizeof(uint32_t) * offsets.size();
662 ChunkLargeOffset::ChunkLargeOffset() {}
663 ChunkLargeOffset::~ChunkLargeOffset() {}
664 FourCC ChunkLargeOffset::BoxType()
const {
return FOURCC_CO64; }
667 uint32_t count = offsets.size();
671 if (count == 0 || IsFitIn32Bits(offsets[count - 1])) {
673 stco.offsets.swap(offsets);
676 stco.offsets.swap(offsets);
682 buffer->ReadWriteUInt32(&count));
684 offsets.resize(count);
685 for (uint32_t i = 0; i < count; ++i)
686 RCHECK(buffer->ReadWriteUInt64(&offsets[i]));
691 uint32_t count = offsets.size();
692 int use_large_offset =
693 (count > 0 && !IsFitIn32Bits(offsets[count - 1])) ? 1 : 0;
694 atom_size = kFullBoxSize +
sizeof(count) +
695 sizeof(uint32_t) * (1 + use_large_offset) * offsets.size();
699 SyncSample::SyncSample() {}
700 SyncSample::~SyncSample() {}
701 FourCC SyncSample::BoxType()
const {
return FOURCC_STSS; }
704 uint32_t count = sample_number.size();
706 buffer->ReadWriteUInt32(&count));
708 sample_number.resize(count);
709 for (uint32_t i = 0; i < count; ++i)
710 RCHECK(buffer->ReadWriteUInt32(&sample_number[i]));
717 if (!sample_number.empty()) {
718 atom_size = kFullBoxSize +
sizeof(uint32_t) +
719 sizeof(uint32_t) * sample_number.size();
724 SampleTable::SampleTable() {}
725 SampleTable::~SampleTable() {}
726 FourCC SampleTable::BoxType()
const {
return FOURCC_STBL; }
745 RCHECK(reader->
ReadChild(&compact_sample_size));
746 sample_size.sample_size = 0;
747 sample_size.sample_count = compact_sample_size.sizes.size();
748 sample_size.sizes.swap(compact_sample_size.sizes);
752 if (reader->
ChildExist(&chunk_large_offset)) {
753 RCHECK(reader->
ReadChild(&chunk_large_offset));
756 RCHECK(reader->
ReadChild(&chunk_offset));
757 chunk_large_offset.offsets.swap(chunk_offset.offsets);
776 EditList::EditList() {}
777 EditList::~EditList() {}
778 FourCC EditList::BoxType()
const {
return FOURCC_ELST; }
781 uint32_t count = edits.size();
785 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
786 for (uint32_t i = 0; i < count; ++i) {
789 buffer->ReadWriteInt64NBytes(&edits[i].media_time, num_bytes) &&
790 buffer->ReadWriteInt16(&edits[i].media_rate_integer) &&
791 buffer->ReadWriteInt16(&edits[i].media_rate_fraction));
803 for (uint32_t i = 0; i < edits.size(); ++i) {
804 if (!IsFitIn32Bits(edits[i].segment_duration, edits[i].media_time)) {
809 atom_size = kFullBoxSize +
sizeof(uint32_t) +
810 (
sizeof(uint32_t) * (1 + version) * 2 +
sizeof(int16_t) * 2) *
817 FourCC Edit::BoxType()
const {
return FOURCC_EDTS; }
828 if (!list.edits.empty())
833 HandlerReference::HandlerReference() : type(kInvalid) {}
834 HandlerReference::~HandlerReference() {}
835 FourCC HandlerReference::BoxType()
const {
return FOURCC_HDLR; }
838 FourCC hdlr_type = FOURCC_NULL;
839 std::vector<uint8_t> handler_name;
841 if (type == kVideo) {
842 hdlr_type = FOURCC_VIDE;
843 handler_name.assign(kVideoHandlerName,
844 kVideoHandlerName + arraysize(kVideoHandlerName));
845 }
else if (type == kAudio) {
846 hdlr_type = FOURCC_SOUN;
847 handler_name.assign(kAudioHandlerName,
848 kAudioHandlerName + arraysize(kAudioHandlerName));
856 buffer->ReadWriteFourCC(&hdlr_type));
859 if (hdlr_type == FOURCC_VIDE) {
861 }
else if (hdlr_type == FOURCC_SOUN) {
868 buffer->ReadWriteVector(&handler_name, handler_name.size()));
875 kFullBoxSize + kFourCCSize + 16 +
876 (type == kVideo ?
sizeof(kVideoHandlerName) :
sizeof(kAudioHandlerName));
880 CodecConfigurationRecord::CodecConfigurationRecord() : box_type(FOURCC_NULL) {}
881 CodecConfigurationRecord::~CodecConfigurationRecord() {}
882 FourCC CodecConfigurationRecord::BoxType()
const {
891 RCHECK(buffer->ReadWriteVector(&data, buffer->
Size() - buffer->
Pos()));
893 RCHECK(buffer->ReadWriteVector(&data, data.size()));
905 PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(0), v_spacing(0) {}
906 PixelAspectRatioBox::~PixelAspectRatioBox() {}
907 FourCC PixelAspectRatioBox::BoxType()
const {
return FOURCC_PASP; }
911 buffer->ReadWriteUInt32(&h_spacing) &&
912 buffer->ReadWriteUInt32(&v_spacing));
919 if (h_spacing != 0 || v_spacing != 0) {
921 DCHECK(h_spacing != 0 && v_spacing != 0);
922 atom_size = kBoxSize +
sizeof(h_spacing) +
sizeof(v_spacing);
927 VideoSampleEntry::VideoSampleEntry()
928 : format(FOURCC_NULL), data_reference_index(1), width(0), height(0) {}
930 VideoSampleEntry::~VideoSampleEntry() {}
931 FourCC VideoSampleEntry::BoxType()
const {
932 LOG(ERROR) <<
"VideoSampleEntry should be parsed according to the "
933 <<
"handler type recovered in its Media ancestor.";
938 std::vector<uint8_t> compressor_name;
941 format = buffer->
reader()->type();
943 RCHECK(buffer->ReadWriteUInt32(&
atom_size) &&
944 buffer->ReadWriteFourCC(&format));
946 const FourCC actual_format = GetActualFormat();
947 switch (actual_format) {
949 compressor_name.assign(
951 kAvcCompressorName + arraysize(kAvcCompressorName));
956 compressor_name.assign(
958 kVpcCompressorName + arraysize(kVpcCompressorName));
961 LOG(ERROR) << FourCCToString(actual_format) <<
" is not supported.";
964 compressor_name.resize(kCompressorNameSize);
967 uint32_t video_resolution = kVideoResolution;
968 uint16_t video_frame_count = kVideoFrameCount;
969 uint16_t video_depth = kVideoDepth;
970 int16_t predefined = -1;
972 buffer->ReadWriteUInt16(&data_reference_index) &&
974 buffer->ReadWriteUInt16(&width) &&
975 buffer->ReadWriteUInt16(&height) &&
976 buffer->ReadWriteUInt32(&video_resolution) &&
977 buffer->ReadWriteUInt32(&video_resolution) &&
979 buffer->ReadWriteUInt16(&video_frame_count) &&
980 buffer->ReadWriteVector(&compressor_name, kCompressorNameSize) &&
981 buffer->ReadWriteUInt16(&video_depth) &&
982 buffer->ReadWriteInt16(&predefined));
986 if (format == FOURCC_ENCV) {
990 while (sinf.type.type != FOURCC_CENC) {
999 const FourCC actual_format = GetActualFormat();
1000 switch (actual_format) {
1002 codec_config_record.box_type = FOURCC_AVCC;
1007 codec_config_record.box_type = FOURCC_VPCC;
1010 LOG(ERROR) << FourCCToString(actual_format) <<
" is not supported.";
1019 atom_size = kBoxSize +
sizeof(data_reference_index) +
sizeof(width) +
1020 sizeof(height) +
sizeof(kVideoResolution) * 2 +
1021 sizeof(kVideoFrameCount) +
sizeof(kVideoDepth) +
1023 codec_config_record.
ComputeSize() + kCompressorNameSize +
1028 ElementaryStreamDescriptor::ElementaryStreamDescriptor() {}
1029 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
1030 FourCC ElementaryStreamDescriptor::BoxType()
const {
return FOURCC_ESDS; }
1035 std::vector<uint8_t> data;
1036 RCHECK(buffer->ReadWriteVector(&data, buffer->
Size() - buffer->
Pos()));
1037 RCHECK(es_descriptor.Parse(data));
1038 if (es_descriptor.
IsAAC()) {
1039 RCHECK(aac_audio_specific_config.
Parse(
1040 es_descriptor.decoder_specific_info()));
1043 DCHECK(buffer->
writer());
1044 es_descriptor.Write(buffer->
writer());
1052 if (es_descriptor.object_type() != kForbidden)
1053 atom_size = kFullBoxSize + es_descriptor.ComputeSize();
1057 AudioSampleEntry::AudioSampleEntry()
1058 : format(FOURCC_NULL),
1059 data_reference_index(1),
1064 AudioSampleEntry::~AudioSampleEntry() {}
1066 FourCC AudioSampleEntry::BoxType()
const {
1067 LOG(ERROR) <<
"AudioSampleEntry should be parsed according to the "
1068 <<
"handler type recovered in its Media ancestor.";
1074 DCHECK(buffer->
reader());
1075 format = buffer->
reader()->type();
1077 RCHECK(buffer->ReadWriteUInt32(&
atom_size) &&
1078 buffer->ReadWriteFourCC(&format));
1084 buffer->ReadWriteUInt16(&data_reference_index) &&
1086 buffer->ReadWriteUInt16(&channelcount) &&
1087 buffer->ReadWriteUInt16(&samplesize) &&
1089 buffer->ReadWriteUInt32(&samplerate));
1094 if (format == FOURCC_ENCA) {
1098 while (sinf.type.type != FOURCC_CENC) {
1113 atom_size = kBoxSize +
sizeof(data_reference_index) +
sizeof(channelcount) +
1114 sizeof(samplesize) +
sizeof(samplerate) + sinf.
ComputeSize() +
1120 MediaHeader::MediaHeader()
1121 : creation_time(0), modification_time(0), timescale(0), duration(0) {
1124 MediaHeader::~MediaHeader() {}
1125 FourCC MediaHeader::BoxType()
const {
return FOURCC_MDHD; }
1130 uint8_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1133 buffer->ReadWriteUInt32(×cale) &&
1139 std::vector<uint8_t> temp;
1140 RCHECK(buffer->ReadWriteVector(&temp, 2));
1143 bit_reader.SkipBits(1);
1144 for (
int i = 0; i < 3; ++i) {
1145 CHECK(bit_reader.ReadBits(5, &language[i]));
1146 language[i] += 0x60;
1151 const char kUndefinedLanguage[] =
"und";
1152 if (language[0] == 0)
1153 strcpy(language, kUndefinedLanguage);
1157 for (
int i = 0; i < 3; ++i)
1158 lang |= (language[i] - 0x60) << ((2 - i) * 5);
1159 RCHECK(buffer->ReadWriteUInt16(&lang));
1167 version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
1168 atom_size = kFullBoxSize +
sizeof(timescale) +
1169 sizeof(uint32_t) * (1 + version) * 3 + 2 +
1174 VideoMediaHeader::VideoMediaHeader()
1175 : graphicsmode(0), opcolor_red(0), opcolor_green(0), opcolor_blue(0) {
1176 const uint32_t kVideoMediaHeaderFlags = 1;
1177 flags = kVideoMediaHeaderFlags;
1179 VideoMediaHeader::~VideoMediaHeader() {}
1180 FourCC VideoMediaHeader::BoxType()
const {
return FOURCC_VMHD; }
1183 buffer->ReadWriteUInt16(&graphicsmode) &&
1184 buffer->ReadWriteUInt16(&opcolor_red) &&
1185 buffer->ReadWriteUInt16(&opcolor_green) &&
1186 buffer->ReadWriteUInt16(&opcolor_blue));
1191 atom_size = kFullBoxSize +
sizeof(graphicsmode) +
sizeof(opcolor_red) +
1192 sizeof(opcolor_green) +
sizeof(opcolor_blue);
1196 SoundMediaHeader::SoundMediaHeader() : balance(0) {}
1197 SoundMediaHeader::~SoundMediaHeader() {}
1198 FourCC SoundMediaHeader::BoxType()
const {
return FOURCC_SMHD; }
1201 buffer->ReadWriteUInt16(&balance) &&
1207 atom_size = kFullBoxSize +
sizeof(balance) +
sizeof(uint16_t);
1211 DataEntryUrl::DataEntryUrl() {
1212 const uint32_t kDataEntryUrlFlags = 1;
1213 flags = kDataEntryUrlFlags;
1215 DataEntryUrl::~DataEntryUrl() {}
1216 FourCC DataEntryUrl::BoxType()
const {
return FOURCC_URL; }
1220 RCHECK(buffer->ReadWriteVector(&location, buffer->
Size() - buffer->
Pos()));
1222 RCHECK(buffer->ReadWriteVector(&location, location.size()));
1228 atom_size = kBoxSize +
sizeof(flags) + location.size();
1232 DataReference::DataReference() {
1234 data_entry.resize(1);
1236 DataReference::~DataReference() {}
1237 FourCC DataReference::BoxType()
const {
return FOURCC_DREF; }
1239 uint32_t entry_count = data_entry.size();
1241 buffer->ReadWriteUInt32(&entry_count));
1242 data_entry.resize(entry_count);
1244 for (uint32_t i = 0; i < entry_count; ++i)
1250 uint32_t count = data_entry.size();
1251 atom_size = kFullBoxSize +
sizeof(count);
1252 for (uint32_t i = 0; i < count; ++i)
1257 DataInformation::DataInformation() {}
1258 DataInformation::~DataInformation() {}
1259 FourCC DataInformation::BoxType()
const {
return FOURCC_DINF; }
1272 MediaInformation::MediaInformation() {}
1273 MediaInformation::~MediaInformation() {}
1274 FourCC MediaInformation::BoxType()
const {
return FOURCC_MINF; }
1281 if (sample_table.description.type == kVideo)
1283 else if (sample_table.description.type == kAudio)
1293 if (sample_table.description.type == kVideo)
1295 else if (sample_table.description.type == kAudio)
1302 FourCC Media::BoxType()
const {
return FOURCC_MDIA; }
1316 information.sample_table.description.type = handler.type;
1318 DCHECK_EQ(information.sample_table.description.type, handler.type);
1332 FourCC Track::BoxType()
const {
return FOURCC_TRAK; }
1349 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
1350 MovieExtendsHeader::~MovieExtendsHeader() {}
1351 FourCC MovieExtendsHeader::BoxType()
const {
return FOURCC_MEHD; }
1355 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1363 if (fragment_duration != 0) {
1364 version = IsFitIn32Bits(fragment_duration) ? 0 : 1;
1365 atom_size = kFullBoxSize +
sizeof(uint32_t) * (1 + version);
1370 TrackExtends::TrackExtends()
1372 default_sample_description_index(0),
1373 default_sample_duration(0),
1374 default_sample_size(0),
1375 default_sample_flags(0) {}
1376 TrackExtends::~TrackExtends() {}
1377 FourCC TrackExtends::BoxType()
const {
return FOURCC_TREX; }
1381 buffer->ReadWriteUInt32(&track_id) &&
1382 buffer->ReadWriteUInt32(&default_sample_description_index) &&
1383 buffer->ReadWriteUInt32(&default_sample_duration) &&
1384 buffer->ReadWriteUInt32(&default_sample_size) &&
1385 buffer->ReadWriteUInt32(&default_sample_flags));
1390 atom_size = kFullBoxSize +
sizeof(track_id) +
1391 sizeof(default_sample_description_index) +
1392 sizeof(default_sample_duration) +
sizeof(default_sample_size) +
1393 sizeof(default_sample_flags);
1397 MovieExtends::MovieExtends() {}
1398 MovieExtends::~MovieExtends() {}
1399 FourCC MovieExtends::BoxType()
const {
return FOURCC_MVEX; }
1406 DCHECK(buffer->
reader());
1409 for (uint32_t i = 0; i < tracks.size(); ++i)
1418 if (tracks.size() != 0) {
1420 for (uint32_t i = 0; i < tracks.size(); ++i)
1428 FourCC Movie::BoxType()
const {
return FOURCC_MOOV; }
1441 for (uint32_t i = 0; i < tracks.size(); ++i)
1443 for (uint32_t i = 0; i < pssh.size(); ++i)
1451 for (uint32_t i = 0; i < tracks.size(); ++i)
1453 for (uint32_t i = 0; i < pssh.size(); ++i)
1458 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
1459 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
1460 FourCC TrackFragmentDecodeTime::BoxType()
const {
return FOURCC_TFDT; }
1464 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1470 version = IsFitIn32Bits(decode_time) ? 0 : 1;
1471 atom_size = kFullBoxSize +
sizeof(uint32_t) * (1 + version);
1475 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
1476 MovieFragmentHeader::~MovieFragmentHeader() {}
1477 FourCC MovieFragmentHeader::BoxType()
const {
return FOURCC_MFHD; }
1481 buffer->ReadWriteUInt32(&sequence_number);
1485 atom_size = kFullBoxSize +
sizeof(sequence_number);
1489 TrackFragmentHeader::TrackFragmentHeader()
1491 sample_description_index(0),
1492 default_sample_duration(0),
1493 default_sample_size(0),
1494 default_sample_flags(0) {}
1496 TrackFragmentHeader::~TrackFragmentHeader() {}
1497 FourCC TrackFragmentHeader::BoxType()
const {
return FOURCC_TFHD; }
1501 buffer->ReadWriteUInt32(&track_id));
1503 if (flags & kBaseDataOffsetPresentMask) {
1508 uint64_t base_data_offset;
1509 RCHECK(buffer->ReadWriteUInt64(&base_data_offset));
1510 DLOG(WARNING) <<
"base-data-offset-present is not expected. Assumes "
1511 "default-base-is-moof.";
1514 if (flags & kSampleDescriptionIndexPresentMask) {
1515 RCHECK(buffer->ReadWriteUInt32(&sample_description_index));
1516 }
else if (buffer->
Reading()) {
1517 sample_description_index = 0;
1520 if (flags & kDefaultSampleDurationPresentMask) {
1521 RCHECK(buffer->ReadWriteUInt32(&default_sample_duration));
1522 }
else if (buffer->
Reading()) {
1523 default_sample_duration = 0;
1526 if (flags & kDefaultSampleSizePresentMask) {
1527 RCHECK(buffer->ReadWriteUInt32(&default_sample_size));
1528 }
else if (buffer->
Reading()) {
1529 default_sample_size = 0;
1532 if (flags & kDefaultSampleFlagsPresentMask)
1533 RCHECK(buffer->ReadWriteUInt32(&default_sample_flags));
1538 atom_size = kFullBoxSize +
sizeof(track_id);
1539 if (flags & kSampleDescriptionIndexPresentMask)
1540 atom_size +=
sizeof(sample_description_index);
1541 if (flags & kDefaultSampleDurationPresentMask)
1542 atom_size +=
sizeof(default_sample_duration);
1543 if (flags & kDefaultSampleSizePresentMask)
1544 atom_size +=
sizeof(default_sample_size);
1545 if (flags & kDefaultSampleFlagsPresentMask)
1546 atom_size +=
sizeof(default_sample_flags);
1550 TrackFragmentRun::TrackFragmentRun() : sample_count(0), data_offset(0) {}
1551 TrackFragmentRun::~TrackFragmentRun() {}
1552 FourCC TrackFragmentRun::BoxType()
const {
return FOURCC_TRUN; }
1560 if (flags & kSampleCompTimeOffsetsPresentMask) {
1561 for (uint32_t i = 0; i < sample_count; ++i) {
1562 if (sample_composition_time_offsets[i] < 0) {
1571 buffer->ReadWriteUInt32(&sample_count));
1573 bool data_offset_present = (flags & kDataOffsetPresentMask) != 0;
1574 bool first_sample_flags_present = (flags & kFirstSampleFlagsPresentMask) != 0;
1575 bool sample_duration_present = (flags & kSampleDurationPresentMask) != 0;
1576 bool sample_size_present = (flags & kSampleSizePresentMask) != 0;
1577 bool sample_flags_present = (flags & kSampleFlagsPresentMask) != 0;
1578 bool sample_composition_time_offsets_present =
1579 (flags & kSampleCompTimeOffsetsPresentMask) != 0;
1581 if (data_offset_present) {
1582 RCHECK(buffer->ReadWriteUInt32(&data_offset));
1593 uint32_t first_sample_flags;
1596 if (first_sample_flags_present)
1597 RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
1599 if (sample_duration_present)
1600 sample_durations.resize(sample_count);
1601 if (sample_size_present)
1602 sample_sizes.resize(sample_count);
1603 if (sample_flags_present)
1604 sample_flags.resize(sample_count);
1605 if (sample_composition_time_offsets_present)
1606 sample_composition_time_offsets.resize(sample_count);
1608 if (first_sample_flags_present) {
1609 first_sample_flags = sample_flags[0];
1610 DCHECK(sample_flags.size() == 1);
1611 RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
1614 if (sample_duration_present)
1615 DCHECK(sample_durations.size() == sample_count);
1616 if (sample_size_present)
1617 DCHECK(sample_sizes.size() == sample_count);
1618 if (sample_flags_present)
1619 DCHECK(sample_flags.size() == sample_count);
1620 if (sample_composition_time_offsets_present)
1621 DCHECK(sample_composition_time_offsets.size() == sample_count);
1624 for (uint32_t i = 0; i < sample_count; ++i) {
1625 if (sample_duration_present)
1626 RCHECK(buffer->ReadWriteUInt32(&sample_durations[i]));
1627 if (sample_size_present)
1628 RCHECK(buffer->ReadWriteUInt32(&sample_sizes[i]));
1629 if (sample_flags_present)
1630 RCHECK(buffer->ReadWriteUInt32(&sample_flags[i]));
1632 if (sample_composition_time_offsets_present) {
1634 uint32_t sample_offset = sample_composition_time_offsets[i];
1635 RCHECK(buffer->ReadWriteUInt32(&sample_offset));
1636 sample_composition_time_offsets[i] = sample_offset;
1638 int32_t sample_offset = sample_composition_time_offsets[i];
1639 RCHECK(buffer->ReadWriteInt32(&sample_offset));
1640 sample_composition_time_offsets[i] = sample_offset;
1646 if (first_sample_flags_present) {
1647 if (sample_flags.size() == 0) {
1648 sample_flags.push_back(first_sample_flags);
1650 sample_flags[0] = first_sample_flags;
1658 atom_size = kFullBoxSize +
sizeof(sample_count);
1659 if (flags & kDataOffsetPresentMask)
1661 if (flags & kFirstSampleFlagsPresentMask)
1663 uint32_t fields = (flags & kSampleDurationPresentMask ? 1 : 0) +
1664 (flags & kSampleSizePresentMask ? 1 : 0) +
1665 (flags & kSampleFlagsPresentMask ? 1 : 0) +
1666 (flags & kSampleCompTimeOffsetsPresentMask ? 1 : 0);
1667 atom_size += fields *
sizeof(uint32_t) * sample_count;
1671 SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
1672 SampleToGroup::~SampleToGroup() {}
1673 FourCC SampleToGroup::BoxType()
const {
return FOURCC_SBGP; }
1677 buffer->ReadWriteUInt32(&grouping_type));
1679 RCHECK(buffer->ReadWriteUInt32(&grouping_type_parameter));
1681 if (grouping_type != FOURCC_SEIG) {
1683 DLOG(WARNING) <<
"Sample group '" << grouping_type <<
"' is not supported.";
1687 uint32_t count = entries.size();
1688 RCHECK(buffer->ReadWriteUInt32(&count));
1689 entries.resize(count);
1690 for (uint32_t i = 0; i < count; ++i) {
1691 RCHECK(buffer->ReadWriteUInt32(&entries[i].sample_count) &&
1692 buffer->ReadWriteUInt32(&entries[i].group_description_index));
1700 if (!entries.empty()) {
1701 atom_size = kFullBoxSize +
sizeof(grouping_type) +
1702 (version == 1 ?
sizeof(grouping_type_parameter) : 0) +
1703 sizeof(uint32_t) + entries.size() *
sizeof(entries[0]);
1708 CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
1709 : is_encrypted(false), iv_size(0) {
1711 CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {};
1713 SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
1714 SampleGroupDescription::~SampleGroupDescription() {}
1715 FourCC SampleGroupDescription::BoxType()
const {
return FOURCC_SGPD; }
1719 buffer->ReadWriteUInt32(&grouping_type));
1721 if (grouping_type != FOURCC_SEIG) {
1723 DLOG(WARNING) <<
"Sample group '" << grouping_type <<
"' is not supported.";
1727 const size_t kEntrySize =
sizeof(uint32_t) + kCencKeyIdSize;
1728 uint32_t default_length = 0;
1731 RCHECK(buffer->ReadWriteUInt32(&default_length));
1732 RCHECK(default_length == 0 || default_length >= kEntrySize);
1734 default_length = kEntrySize;
1735 RCHECK(buffer->ReadWriteUInt32(&default_length));
1739 uint32_t count = entries.size();
1740 RCHECK(buffer->ReadWriteUInt32(&count));
1741 entries.resize(count);
1742 for (uint32_t i = 0; i < count; ++i) {
1744 if (buffer->
Reading() && default_length == 0) {
1745 uint32_t description_length = 0;
1746 RCHECK(buffer->ReadWriteUInt32(&description_length));
1747 RCHECK(description_length >= kEntrySize);
1752 if (entries[i].key_id.size() != kCencKeyIdSize) {
1753 LOG(WARNING) <<
"CENC defines key id length of " << kCencKeyIdSize
1754 <<
" bytes; got " << entries[i].key_id.size()
1755 <<
". Resized accordingly.";
1756 entries[i].key_id.resize(kCencKeyIdSize);
1760 uint8_t flag = entries[i].is_encrypted ? 1 : 0;
1762 buffer->ReadWriteUInt8(&flag) &&
1763 buffer->ReadWriteUInt8(&entries[i].iv_size) &&
1764 buffer->ReadWriteVector(&entries[i].key_id, kCencKeyIdSize));
1767 entries[i].is_encrypted = (flag != 0);
1768 if (entries[i].is_encrypted) {
1769 RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
1771 RCHECK(entries[i].iv_size == 0);
1783 if (!entries.empty()) {
1784 const size_t kEntrySize =
sizeof(uint32_t) + kCencKeyIdSize;
1785 atom_size = kFullBoxSize +
sizeof(grouping_type) +
1786 (version == 1 ?
sizeof(uint32_t) : 0) +
sizeof(uint32_t) +
1787 entries.size() * kEntrySize;
1792 TrackFragment::TrackFragment() : decode_time_absent(false) {}
1793 TrackFragment::~TrackFragment() {}
1794 FourCC TrackFragment::BoxType()
const {
return FOURCC_TRAF; }
1801 DCHECK(buffer->
reader());
1803 if (!decode_time_absent)
1811 while (sample_to_group.grouping_type != FOURCC_SEIG &&
1815 while (sample_group_description.grouping_type != FOURCC_SEIG &&
1820 if (!decode_time_absent)
1822 for (uint32_t i = 0; i < runs.size(); ++i)
1836 for (uint32_t i = 0; i < runs.size(); ++i)
1841 MovieFragment::MovieFragment() {}
1842 MovieFragment::~MovieFragment() {}
1843 FourCC MovieFragment::BoxType()
const {
return FOURCC_MOOF; }
1855 for (uint32_t i = 0; i < tracks.size(); ++i)
1857 for (uint32_t i = 0; i < pssh.size(); ++i)
1865 for (uint32_t i = 0; i < tracks.size(); ++i)
1867 for (uint32_t i = 0; i < pssh.size(); ++i)
1872 SegmentIndex::SegmentIndex()
1875 earliest_presentation_time(0),
1877 SegmentIndex::~SegmentIndex() {}
1878 FourCC SegmentIndex::BoxType()
const {
return FOURCC_SIDX; }
1882 buffer->ReadWriteUInt32(&reference_id) &&
1883 buffer->ReadWriteUInt32(×cale));
1885 size_t num_bytes = (version == 1) ?
sizeof(uint64_t) :
sizeof(uint32_t);
1890 uint16_t reference_count = references.size();
1892 buffer->ReadWriteUInt16(&reference_count));
1893 references.resize(reference_count);
1895 uint32_t reference_type_size;
1897 for (uint32_t i = 0; i < reference_count; ++i) {
1899 reference_type_size = references[i].referenced_size;
1900 if (references[i].reference_type)
1901 reference_type_size |= (1 << 31);
1902 sap = (references[i].sap_type << 28) | references[i].sap_delta_time;
1903 if (references[i].starts_with_sap)
1906 RCHECK(buffer->ReadWriteUInt32(&reference_type_size) &&
1907 buffer->ReadWriteUInt32(&references[i].subsegment_duration) &&
1908 buffer->ReadWriteUInt32(&sap));
1910 references[i].reference_type = (reference_type_size >> 31) ?
true :
false;
1911 references[i].referenced_size = reference_type_size & ~(1 << 31);
1912 references[i].starts_with_sap = (sap >> 31) ?
true :
false;
1913 references[i].sap_type =
1914 static_cast<SegmentReference::SAPType
>((sap >> 28) & 0x07);
1915 references[i].sap_delta_time = sap & ~(0xF << 28);
1922 version = IsFitIn32Bits(earliest_presentation_time, first_offset) ? 0 : 1;
1923 atom_size = kFullBoxSize +
sizeof(reference_id) +
sizeof(timescale) +
1924 sizeof(uint32_t) * (1 + version) * 2 + 2 *
sizeof(uint16_t) +
1925 3 *
sizeof(uint32_t) * references.size();
1929 MediaData::MediaData() : data_size(0) {}
1930 MediaData::~MediaData() {}
1931 FourCC MediaData::BoxType()
const {
return FOURCC_MDAT; }
1933 void MediaData::Write(BufferWriter* buffer) {
1934 buffer->AppendInt(ComputeSize());
1935 buffer->AppendInt(static_cast<uint32_t>(BoxType()));
1938 uint32_t MediaData::ComputeSize() {
1939 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.