Shaka Packager SDK
box_definitions.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <packager/media/formats/mp4/box_definitions.h>
6 
7 #include <algorithm>
8 #include <limits>
9 
10 #include <absl/flags/flag.h>
11 #include <absl/log/check.h>
12 #include <absl/log/log.h>
13 
14 #include <packager/macros/logging.h>
15 #include <packager/media/base/bit_reader.h>
16 #include <packager/media/base/rcheck.h>
17 #include <packager/media/formats/mp4/box_buffer.h>
18 
19 ABSL_FLAG(bool,
20  mvex_before_trak,
21  false,
22  "Android MediaExtractor requires mvex to be written before trak. "
23  "Set the flag to true to comply with the requirement.");
24 
25 namespace {
26 const uint32_t kFourCCSize = 4;
27 
28 // Key Id size as defined in CENC spec.
29 const uint32_t kCencKeyIdSize = 16;
30 
31 // 9 uint32_t in big endian formatted array.
32 const uint8_t kUnityMatrix[] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33  0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
34  0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0};
35 
36 // Default entries for HandlerReference box.
37 const char kVideoHandlerName[] = "VideoHandler";
38 const char kAudioHandlerName[] = "SoundHandler";
39 const char kTextHandlerName[] = "TextHandler";
40 const char kSubtitleHandlerName[] = "SubtitleHandler";
41 
42 // Default values for VideoSampleEntry box.
43 const uint32_t kVideoResolution = 0x00480000; // 72 dpi.
44 const uint16_t kVideoFrameCount = 1;
45 const uint16_t kVideoDepth = 0x0018;
46 
47 const uint32_t kCompressorNameSize = 32u;
48 const char kAv1CompressorName[] = "\012AOM Coding";
49 const char kAvcCompressorName[] = "\012AVC Coding";
50 const char kDolbyVisionCompressorName[] = "\013DOVI Coding";
51 const char kHevcCompressorName[] = "\013HEVC Coding";
52 const char kVpcCompressorName[] = "\012VPC Coding";
53 
54 // According to ISO/IEC FDIS 23001-7: CENC spec, IV should be either
55 // 64-bit (8-byte) or 128-bit (16-byte).
56 // |per_sample_iv_size| of 0 means constant_iv is used.
57 bool IsIvSizeValid(uint8_t per_sample_iv_size) {
58  return per_sample_iv_size == 0 || per_sample_iv_size == 8 ||
59  per_sample_iv_size == 16;
60 }
61 
62 // Default values to construct the following fields in ddts box. Values are set
63 // according to FFMPEG.
64 // bit(2) FrameDuration; // 3 = 4096
65 // bit(5) StreamConstruction; // 18
66 // bit(1) CoreLFEPresent; // 0 = none
67 // bit(6) CoreLayout; // 31 = ignore core layout
68 // bit(14) CoreSize; // 0
69 // bit(1) StereoDownmix // 0 = none
70 // bit(3) RepresentationType; // 4
71 // bit(16) ChannelLayout; // 0xf = 5.1 channel layout.
72 // bit(1) MultiAssetFlag // 0 = single asset
73 // bit(1) LBRDurationMod // 0 = ignore
74 // bit(1) ReservedBoxPresent // 0 = none
75 // bit(5) Reserved // 0
76 const uint8_t kDdtsExtraData[] = {0xe4, 0x7c, 0, 4, 0, 0x0f, 0};
77 
78 // Utility functions to check if the 64bit integers can fit in 32bit integer.
79 bool IsFitIn32Bits(uint64_t a) {
80  return a <= std::numeric_limits<uint32_t>::max();
81 }
82 
83 bool IsFitIn32Bits(int64_t a) {
84  return a <= std::numeric_limits<int32_t>::max() &&
85  a >= std::numeric_limits<int32_t>::min();
86 }
87 
88 template <typename T1, typename T2>
89 bool IsFitIn32Bits(T1 a1, T2 a2) {
90  return IsFitIn32Bits(a1) && IsFitIn32Bits(a2);
91 }
92 
93 template <typename T1, typename T2, typename T3>
94 bool IsFitIn32Bits(T1 a1, T2 a2, T3 a3) {
95  return IsFitIn32Bits(a1) && IsFitIn32Bits(a2) && IsFitIn32Bits(a3);
96 }
97 
98 } // namespace
99 
100 namespace shaka {
101 namespace media {
102 namespace mp4 {
103 
104 namespace {
105 
106 TrackType FourCCToTrackType(FourCC fourcc) {
107  switch (fourcc) {
108  case FOURCC_vide:
109  return kVideo;
110  case FOURCC_soun:
111  return kAudio;
112  case FOURCC_text:
113  return kText;
114  case FOURCC_subt:
115  return kSubtitle;
116  default:
117  return kInvalid;
118  }
119 }
120 
121 FourCC TrackTypeToFourCC(TrackType track_type) {
122  switch (track_type) {
123  case kVideo:
124  return FOURCC_vide;
125  case kAudio:
126  return FOURCC_soun;
127  case kText:
128  return FOURCC_text;
129  case kSubtitle:
130  return FOURCC_subt;
131  default:
132  return FOURCC_NULL;
133  }
134 }
135 
136 bool IsProtectionSchemeSupported(FourCC scheme) {
137  return scheme == FOURCC_cenc || scheme == FOURCC_cens ||
138  scheme == FOURCC_cbc1 || scheme == FOURCC_cbcs;
139 }
140 
141 } // namespace
142 
143 FileType::FileType() = default;
144 FileType::~FileType() = default;
145 
146 FourCC FileType::BoxType() const {
147  return FOURCC_ftyp;
148 }
149 
150 bool FileType::ReadWriteInternal(BoxBuffer* buffer) {
151  RCHECK(ReadWriteHeaderInternal(buffer) &&
152  buffer->ReadWriteFourCC(&major_brand) &&
153  buffer->ReadWriteUInt32(&minor_version));
154  size_t num_brands;
155  if (buffer->Reading()) {
156  RCHECK(buffer->BytesLeft() % sizeof(FourCC) == 0);
157  num_brands = buffer->BytesLeft() / sizeof(FourCC);
158  compatible_brands.resize(num_brands);
159  } else {
160  num_brands = compatible_brands.size();
161  }
162  for (size_t i = 0; i < num_brands; ++i)
163  RCHECK(buffer->ReadWriteFourCC(&compatible_brands[i]));
164  return true;
165 }
166 
167 size_t FileType::ComputeSizeInternal() {
168  return HeaderSize() + kFourCCSize + sizeof(minor_version) +
169  kFourCCSize * compatible_brands.size();
170 }
171 
172 FourCC SegmentType::BoxType() const {
173  return FOURCC_styp;
174 }
175 
176 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() = default;
177 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() = default;
178 
180  return FOURCC_pssh;
181 }
182 
183 bool ProtectionSystemSpecificHeader::ReadWriteInternal(BoxBuffer* buffer) {
184  if (buffer->Reading()) {
185  BoxReader* reader = buffer->reader();
186  DCHECK(reader);
187  raw_box.assign(reader->data(), reader->data() + reader->size());
188  } else {
189  DCHECK(!raw_box.empty());
190  buffer->writer()->AppendVector(raw_box);
191  }
192 
193  return true;
194 }
195 
196 size_t ProtectionSystemSpecificHeader::ComputeSizeInternal() {
197  return raw_box.size();
198 }
199 
200 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() = default;
201 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() = default;
202 
204  return FOURCC_saio;
205 }
206 
207 bool SampleAuxiliaryInformationOffset::ReadWriteInternal(BoxBuffer* buffer) {
208  RCHECK(ReadWriteHeaderInternal(buffer));
209  if (flags & 1)
210  RCHECK(buffer->IgnoreBytes(8)); // aux_info_type and parameter.
211 
212  uint32_t count = static_cast<uint32_t>(offsets.size());
213  RCHECK(buffer->ReadWriteUInt32(&count));
214  offsets.resize(count);
215 
216  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
217  for (uint32_t i = 0; i < count; ++i)
218  RCHECK(buffer->ReadWriteUInt64NBytes(&offsets[i], num_bytes));
219  return true;
220 }
221 
222 size_t SampleAuxiliaryInformationOffset::ComputeSizeInternal() {
223  // This box is optional. Skip it if it is empty.
224  if (offsets.size() == 0)
225  return 0;
226  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
227  return HeaderSize() + sizeof(uint32_t) + num_bytes * offsets.size();
228 }
229 
230 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize() = default;
231 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() = default;
232 
234  return FOURCC_saiz;
235 }
236 
237 bool SampleAuxiliaryInformationSize::ReadWriteInternal(BoxBuffer* buffer) {
238  RCHECK(ReadWriteHeaderInternal(buffer));
239  if (flags & 1)
240  RCHECK(buffer->IgnoreBytes(8));
241 
242  RCHECK(buffer->ReadWriteUInt8(&default_sample_info_size) &&
243  buffer->ReadWriteUInt32(&sample_count));
244  if (default_sample_info_size == 0)
245  RCHECK(buffer->ReadWriteVector(&sample_info_sizes, sample_count));
246  return true;
247 }
248 
249 size_t SampleAuxiliaryInformationSize::ComputeSizeInternal() {
250  // This box is optional. Skip it if it is empty.
251  if (sample_count == 0)
252  return 0;
253  return HeaderSize() + sizeof(default_sample_info_size) +
254  sizeof(sample_count) +
255  (default_sample_info_size == 0 ? sample_info_sizes.size() : 0);
256 }
257 
258 bool SampleEncryptionEntry::ReadWrite(uint8_t iv_size,
259  bool has_subsamples,
260  BoxBuffer* buffer) {
261  DCHECK(IsIvSizeValid(iv_size));
262  DCHECK(buffer);
263 
264  RCHECK(buffer->ReadWriteVector(&initialization_vector, iv_size));
265 
266  if (!has_subsamples) {
267  subsamples.clear();
268  return true;
269  }
270 
271  uint16_t subsample_count = static_cast<uint16_t>(subsamples.size());
272  RCHECK(buffer->ReadWriteUInt16(&subsample_count));
273  RCHECK(subsample_count > 0);
274  subsamples.resize(subsample_count);
275  for (auto& subsample : subsamples) {
276  RCHECK(buffer->ReadWriteUInt16(&subsample.clear_bytes) &&
277  buffer->ReadWriteUInt32(&subsample.cipher_bytes));
278  }
279  return true;
280 }
281 
283  bool has_subsamples,
284  BufferReader* reader) {
285  DCHECK(IsIvSizeValid(iv_size));
286  DCHECK(reader);
287 
288  initialization_vector.resize(iv_size);
289  RCHECK(reader->ReadToVector(&initialization_vector, iv_size));
290 
291  if (!has_subsamples) {
292  subsamples.clear();
293  return true;
294  }
295 
296  uint16_t subsample_count;
297  RCHECK(reader->Read2(&subsample_count));
298  RCHECK(subsample_count > 0);
299  subsamples.resize(subsample_count);
300  for (auto& subsample : subsamples) {
301  RCHECK(reader->Read2(&subsample.clear_bytes) &&
302  reader->Read4(&subsample.cipher_bytes));
303  }
304  return true;
305 }
306 
308  const uint32_t subsample_entry_size = sizeof(uint16_t) + sizeof(uint32_t);
309  const uint16_t subsample_count = static_cast<uint16_t>(subsamples.size());
310  return static_cast<uint32_t>(
311  initialization_vector.size() +
312  (subsample_count > 0
313  ? (sizeof(subsample_count) + subsample_entry_size * subsample_count)
314  : 0));
315 }
316 
318  uint32_t size = 0;
319  for (uint32_t i = 0; i < subsamples.size(); ++i)
320  size += subsamples[i].clear_bytes + subsamples[i].cipher_bytes;
321  return size;
322 }
323 
324 SampleEncryption::SampleEncryption() = default;
325 SampleEncryption::~SampleEncryption() = default;
326 
328  return FOURCC_senc;
329 }
330 
331 bool SampleEncryption::ReadWriteInternal(BoxBuffer* buffer) {
332  RCHECK(ReadWriteHeaderInternal(buffer));
333 
334  // If we don't know |iv_size|, store sample encryption data to parse later
335  // after we know iv_size.
336  if (buffer->Reading() && iv_size == SampleEncryption::kInvalidIvSize) {
337  RCHECK(
338  buffer->ReadWriteVector(&sample_encryption_data, buffer->BytesLeft()));
339  return true;
340  }
341 
342  if (!IsIvSizeValid(iv_size)) {
343  LOG(ERROR)
344  << "IV_size can only be 8 or 16 or 0 for constant iv, but seeing "
345  << iv_size;
346  return false;
347  }
348 
349  uint32_t sample_count =
350  static_cast<uint32_t>(sample_encryption_entries.size());
351  RCHECK(buffer->ReadWriteUInt32(&sample_count));
352 
353  sample_encryption_entries.resize(sample_count);
354  for (auto& sample_encryption_entry : sample_encryption_entries) {
355  RCHECK(sample_encryption_entry.ReadWrite(
356  iv_size, (flags & kUseSubsampleEncryption) != 0, buffer) != 0);
357  }
358  return true;
359 }
360 
361 size_t SampleEncryption::ComputeSizeInternal() {
362  const uint32_t sample_count =
363  static_cast<uint32_t>(sample_encryption_entries.size());
364  if (sample_count == 0) {
365  // Sample encryption box is optional. Skip it if it is empty.
366  return 0;
367  }
368 
369  DCHECK(IsIvSizeValid(iv_size));
370  size_t box_size = HeaderSize() + sizeof(sample_count);
371  if (flags & kUseSubsampleEncryption) {
372  for (const SampleEncryptionEntry& sample_encryption_entry :
373  sample_encryption_entries) {
374  box_size += sample_encryption_entry.ComputeSize();
375  }
376  } else {
377  box_size += sample_count * iv_size;
378  }
379  return box_size;
380 }
381 
383  uint8_t l_iv_size,
384  std::vector<SampleEncryptionEntry>* l_sample_encryption_entries) const {
385  DCHECK(IsIvSizeValid(l_iv_size));
386 
387  BufferReader reader(sample_encryption_data.data(),
388  sample_encryption_data.size());
389  uint32_t sample_count = 0;
390  RCHECK(reader.Read4(&sample_count));
391 
392  l_sample_encryption_entries->resize(sample_count);
393  for (auto& sample_encryption_entry : *l_sample_encryption_entries) {
394  RCHECK(sample_encryption_entry.ParseFromBuffer(
395  l_iv_size, (flags & kUseSubsampleEncryption) != 0, &reader) !=
396  0);
397  }
398  return true;
399 }
400 
401 OriginalFormat::OriginalFormat() = default;
402 OriginalFormat::~OriginalFormat() = default;
403 
404 FourCC OriginalFormat::BoxType() const {
405  return FOURCC_frma;
406 }
407 
408 bool OriginalFormat::ReadWriteInternal(BoxBuffer* buffer) {
409  return ReadWriteHeaderInternal(buffer) && buffer->ReadWriteFourCC(&format);
410 }
411 
412 size_t OriginalFormat::ComputeSizeInternal() {
413  return HeaderSize() + kFourCCSize;
414 }
415 
416 SchemeType::SchemeType() = default;
417 SchemeType::~SchemeType() = default;
418 
419 FourCC SchemeType::BoxType() const {
420  return FOURCC_schm;
421 }
422 
423 bool SchemeType::ReadWriteInternal(BoxBuffer* buffer) {
424  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteFourCC(&type) &&
425  buffer->ReadWriteUInt32(&version));
426  return true;
427 }
428 
429 size_t SchemeType::ComputeSizeInternal() {
430  return HeaderSize() + kFourCCSize + sizeof(version);
431 }
432 
433 TrackEncryption::TrackEncryption() = default;
434 TrackEncryption::~TrackEncryption() = default;
435 
436 FourCC TrackEncryption::BoxType() const {
437  return FOURCC_tenc;
438 }
439 
440 bool TrackEncryption::ReadWriteInternal(BoxBuffer* buffer) {
441  if (!buffer->Reading()) {
442  if (default_kid.size() != kCencKeyIdSize) {
443  LOG(WARNING) << "CENC defines key id length of " << kCencKeyIdSize
444  << " bytes; got " << default_kid.size()
445  << ". Resized accordingly.";
446  default_kid.resize(kCencKeyIdSize);
447  }
448  RCHECK(default_crypt_byte_block < 16 && default_skip_byte_block < 16);
449  if (default_crypt_byte_block != 0 && default_skip_byte_block != 0) {
450  // Version 1 box is needed for pattern-based encryption.
451  version = 1;
452  }
453  }
454 
455  RCHECK(ReadWriteHeaderInternal(buffer) &&
456  buffer->IgnoreBytes(1)); // reserved.
457 
458  uint8_t pattern = default_crypt_byte_block << 4 | default_skip_byte_block;
459  RCHECK(buffer->ReadWriteUInt8(&pattern));
460  default_crypt_byte_block = pattern >> 4;
461  default_skip_byte_block = pattern & 0x0F;
462 
463  RCHECK(buffer->ReadWriteUInt8(&default_is_protected) &&
464  buffer->ReadWriteUInt8(&default_per_sample_iv_size) &&
465  buffer->ReadWriteVector(&default_kid, kCencKeyIdSize));
466 
467  if (default_is_protected == 1) {
468  if (default_per_sample_iv_size == 0) { // For constant iv.
469  uint8_t default_constant_iv_size =
470  static_cast<uint8_t>(default_constant_iv.size());
471  RCHECK(buffer->ReadWriteUInt8(&default_constant_iv_size));
472  RCHECK(default_constant_iv_size == 8 || default_constant_iv_size == 16);
473  RCHECK(buffer->ReadWriteVector(&default_constant_iv,
474  default_constant_iv_size));
475  } else {
476  RCHECK(default_per_sample_iv_size == 8 ||
477  default_per_sample_iv_size == 16);
478  RCHECK(default_constant_iv.empty());
479  }
480  } else {
481  // Expect |default_is_protected| to be 0, i.e. not protected. Other values
482  // of |default_is_protected| is not supported.
483  RCHECK(default_is_protected == 0);
484  RCHECK(default_per_sample_iv_size == 0);
485  RCHECK(default_constant_iv.empty());
486  }
487  return true;
488 }
489 
490 size_t TrackEncryption::ComputeSizeInternal() {
491  return HeaderSize() + sizeof(uint32_t) + kCencKeyIdSize +
492  (default_constant_iv.empty()
493  ? 0
494  : (sizeof(uint8_t) + default_constant_iv.size()));
495 }
496 
497 SchemeInfo::SchemeInfo() = default;
498 SchemeInfo::~SchemeInfo() = default;
499 
500 FourCC SchemeInfo::BoxType() const {
501  return FOURCC_schi;
502 }
503 
504 bool SchemeInfo::ReadWriteInternal(BoxBuffer* buffer) {
505  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
506  buffer->ReadWriteChild(&track_encryption));
507  return true;
508 }
509 
510 size_t SchemeInfo::ComputeSizeInternal() {
511  return HeaderSize() + track_encryption.ComputeSize();
512 }
513 
514 ProtectionSchemeInfo::ProtectionSchemeInfo() = default;
515 ProtectionSchemeInfo::~ProtectionSchemeInfo() = default;
516 
518  return FOURCC_sinf;
519 }
520 
521 bool ProtectionSchemeInfo::ReadWriteInternal(BoxBuffer* buffer) {
522  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
523  buffer->ReadWriteChild(&format) && buffer->ReadWriteChild(&type));
524  if (IsProtectionSchemeSupported(type.type)) {
525  RCHECK(buffer->ReadWriteChild(&info));
526  } else {
527  DLOG(WARNING) << "Ignore unsupported protection scheme: "
528  << FourCCToString(type.type);
529  }
530  // Other protection schemes are silently ignored. Since the protection scheme
531  // type can't be determined until this box is opened, we return 'true' for
532  // non-CENC protection scheme types. It is the parent box's responsibility to
533  // ensure that this scheme type is a supported one.
534  return true;
535 }
536 
537 size_t ProtectionSchemeInfo::ComputeSizeInternal() {
538  // Skip sinf box if it is not initialized.
539  if (format.format == FOURCC_NULL)
540  return 0;
541  return HeaderSize() + format.ComputeSize() + type.ComputeSize() +
542  info.ComputeSize();
543 }
544 
545 MovieHeader::MovieHeader() = default;
546 MovieHeader::~MovieHeader() = default;
547 
548 FourCC MovieHeader::BoxType() const {
549  return FOURCC_mvhd;
550 }
551 
552 bool MovieHeader::ReadWriteInternal(BoxBuffer* buffer) {
553  RCHECK(ReadWriteHeaderInternal(buffer));
554 
555  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
556  RCHECK(buffer->ReadWriteUInt64NBytes(&creation_time, num_bytes) &&
557  buffer->ReadWriteUInt64NBytes(&modification_time, num_bytes) &&
558  buffer->ReadWriteUInt32(&timescale) &&
559  buffer->ReadWriteUInt64NBytes(&duration, num_bytes));
560 
561  std::vector<uint8_t> matrix(kUnityMatrix,
562  kUnityMatrix + std::size(kUnityMatrix));
563  RCHECK(buffer->ReadWriteInt32(&rate) && buffer->ReadWriteInt16(&volume) &&
564  buffer->IgnoreBytes(10) && // reserved
565  buffer->ReadWriteVector(&matrix, matrix.size()) &&
566  buffer->IgnoreBytes(24) && // predefined zero
567  buffer->ReadWriteUInt32(&next_track_id));
568  return true;
569 }
570 
571 size_t MovieHeader::ComputeSizeInternal() {
572  version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
573  return HeaderSize() + sizeof(uint32_t) * (1 + version) * 3 +
574  sizeof(timescale) + sizeof(rate) + sizeof(volume) +
575  sizeof(next_track_id) + sizeof(kUnityMatrix) + 10 +
576  24; // 10 bytes reserved, 24 bytes predefined.
577 }
578 
579 TrackHeader::TrackHeader() {
580  flags = kTrackEnabled | kTrackInMovie | kTrackInPreview;
581 }
582 
583 TrackHeader::~TrackHeader() = default;
584 
585 FourCC TrackHeader::BoxType() const {
586  return FOURCC_tkhd;
587 }
588 
589 bool TrackHeader::ReadWriteInternal(BoxBuffer* buffer) {
590  RCHECK(ReadWriteHeaderInternal(buffer));
591 
592  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
593  RCHECK(buffer->ReadWriteUInt64NBytes(&creation_time, num_bytes) &&
594  buffer->ReadWriteUInt64NBytes(&modification_time, num_bytes) &&
595  buffer->ReadWriteUInt32(&track_id) &&
596  buffer->IgnoreBytes(4) && // reserved
597  buffer->ReadWriteUInt64NBytes(&duration, num_bytes));
598 
599  if (!buffer->Reading()) {
600  // Set default value for volume, if track is audio, 0x100 else 0.
601  if (volume == -1)
602  volume = (width != 0 && height != 0) ? 0 : 0x100;
603  }
604  std::vector<uint8_t> matrix(kUnityMatrix,
605  kUnityMatrix + std::size(kUnityMatrix));
606  RCHECK(buffer->IgnoreBytes(8) && // reserved
607  buffer->ReadWriteInt16(&layer) &&
608  buffer->ReadWriteInt16(&alternate_group) &&
609  buffer->ReadWriteInt16(&volume) &&
610  buffer->IgnoreBytes(2) && // reserved
611  buffer->ReadWriteVector(&matrix, matrix.size()) &&
612  buffer->ReadWriteUInt32(&width) && buffer->ReadWriteUInt32(&height));
613  return true;
614 }
615 
616 size_t TrackHeader::ComputeSizeInternal() {
617  version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
618  return HeaderSize() + sizeof(track_id) +
619  sizeof(uint32_t) * (1 + version) * 3 + sizeof(layer) +
620  sizeof(alternate_group) + sizeof(volume) + sizeof(width) +
621  sizeof(height) + sizeof(kUnityMatrix) + 14; // 14 bytes reserved.
622 }
623 
624 SampleDescription::SampleDescription() = default;
625 SampleDescription::~SampleDescription() = default;
626 
628  return FOURCC_stsd;
629 }
630 
631 bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
632  uint32_t count = 0;
633  switch (type) {
634  case kVideo:
635  count = static_cast<uint32_t>(video_entries.size());
636  break;
637  case kAudio:
638  count = static_cast<uint32_t>(audio_entries.size());
639  break;
640  case kText:
641  case kSubtitle:
642  count = static_cast<uint32_t>(text_entries.size());
643  break;
644  default:
645  NOTIMPLEMENTED() << "SampleDecryption type " << type
646  << " is not handled. Skipping.";
647  }
648  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
649 
650  if (buffer->Reading()) {
651  BoxReader* reader = buffer->reader();
652  DCHECK(reader);
653  video_entries.clear();
654  audio_entries.clear();
655  // Note: this value is preset before scanning begins. See comments in the
656  // Parse(Media*) function.
657  if (type == kVideo) {
658  RCHECK(reader->ReadAllChildren(&video_entries));
659  RCHECK(video_entries.size() == count);
660  } else if (type == kAudio) {
661  RCHECK(reader->ReadAllChildren(&audio_entries));
662  RCHECK(audio_entries.size() == count);
663  } else if (type == kText || type == kSubtitle) {
664  RCHECK(reader->ReadAllChildren(&text_entries));
665  RCHECK(text_entries.size() == count);
666  }
667  } else {
668  DCHECK_LT(0u, count);
669  if (type == kVideo) {
670  for (uint32_t i = 0; i < count; ++i)
671  RCHECK(buffer->ReadWriteChild(&video_entries[i]));
672  } else if (type == kAudio) {
673  for (uint32_t i = 0; i < count; ++i)
674  RCHECK(buffer->ReadWriteChild(&audio_entries[i]));
675  } else if (type == kText || type == kSubtitle) {
676  for (uint32_t i = 0; i < count; ++i)
677  RCHECK(buffer->ReadWriteChild(&text_entries[i]));
678  } else {
679  NOTIMPLEMENTED();
680  }
681  }
682  return true;
683 }
684 
685 size_t SampleDescription::ComputeSizeInternal() {
686  size_t box_size = HeaderSize() + sizeof(uint32_t);
687  if (type == kVideo) {
688  for (uint32_t i = 0; i < video_entries.size(); ++i)
689  box_size += video_entries[i].ComputeSize();
690  } else if (type == kAudio) {
691  for (uint32_t i = 0; i < audio_entries.size(); ++i)
692  box_size += audio_entries[i].ComputeSize();
693  } else if (type == kText || type == kSubtitle) {
694  for (uint32_t i = 0; i < text_entries.size(); ++i)
695  box_size += text_entries[i].ComputeSize();
696  }
697  return box_size;
698 }
699 
700 DecodingTimeToSample::DecodingTimeToSample() = default;
701 DecodingTimeToSample::~DecodingTimeToSample() = default;
702 
704  return FOURCC_stts;
705 }
706 
707 bool DecodingTimeToSample::ReadWriteInternal(BoxBuffer* buffer) {
708  uint32_t count = static_cast<uint32_t>(decoding_time.size());
709  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
710 
711  decoding_time.resize(count);
712  for (uint32_t i = 0; i < count; ++i) {
713  RCHECK(buffer->ReadWriteUInt32(&decoding_time[i].sample_count) &&
714  buffer->ReadWriteUInt32(&decoding_time[i].sample_delta));
715  }
716  return true;
717 }
718 
719 size_t DecodingTimeToSample::ComputeSizeInternal() {
720  return HeaderSize() + sizeof(uint32_t) +
721  sizeof(DecodingTime) * decoding_time.size();
722 }
723 
724 CompositionTimeToSample::CompositionTimeToSample() = default;
725 CompositionTimeToSample::~CompositionTimeToSample() = default;
726 
728  return FOURCC_ctts;
729 }
730 
731 bool CompositionTimeToSample::ReadWriteInternal(BoxBuffer* buffer) {
732  uint32_t count = static_cast<uint32_t>(composition_offset.size());
733  if (!buffer->Reading()) {
734  // Determine whether version 0 or version 1 should be used.
735  // Use version 0 if possible, use version 1 if there is a negative
736  // sample_offset value.
737  version = 0;
738  for (uint32_t i = 0; i < count; ++i) {
739  if (composition_offset[i].sample_offset < 0) {
740  version = 1;
741  break;
742  }
743  }
744  }
745 
746  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
747 
748  composition_offset.resize(count);
749  for (uint32_t i = 0; i < count; ++i) {
750  RCHECK(buffer->ReadWriteUInt32(&composition_offset[i].sample_count));
751 
752  if (version == 0) {
753  uint32_t sample_offset = composition_offset[i].sample_offset;
754  RCHECK(buffer->ReadWriteUInt32(&sample_offset));
755  composition_offset[i].sample_offset = sample_offset;
756  } else {
757  int32_t sample_offset = composition_offset[i].sample_offset;
758  RCHECK(buffer->ReadWriteInt32(&sample_offset));
759  composition_offset[i].sample_offset = sample_offset;
760  }
761  }
762  return true;
763 }
764 
765 size_t CompositionTimeToSample::ComputeSizeInternal() {
766  // This box is optional. Skip it if it is empty.
767  if (composition_offset.empty())
768  return 0;
769  // Structure CompositionOffset contains |sample_offset| (uint32_t) and
770  // |sample_offset| (int64_t). The actual size of |sample_offset| is
771  // 4 bytes (uint32_t for version 0 and int32_t for version 1).
772  const size_t kCompositionOffsetSize = sizeof(uint32_t) * 2;
773  return HeaderSize() + sizeof(uint32_t) +
774  kCompositionOffsetSize * composition_offset.size();
775 }
776 
777 SampleToChunk::SampleToChunk() = default;
778 SampleToChunk::~SampleToChunk() = default;
779 
780 FourCC SampleToChunk::BoxType() const {
781  return FOURCC_stsc;
782 }
783 
784 bool SampleToChunk::ReadWriteInternal(BoxBuffer* buffer) {
785  uint32_t count = static_cast<uint32_t>(chunk_info.size());
786  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
787 
788  chunk_info.resize(count);
789  for (uint32_t i = 0; i < count; ++i) {
790  RCHECK(buffer->ReadWriteUInt32(&chunk_info[i].first_chunk) &&
791  buffer->ReadWriteUInt32(&chunk_info[i].samples_per_chunk) &&
792  buffer->ReadWriteUInt32(&chunk_info[i].sample_description_index));
793  // first_chunk values are always increasing.
794  RCHECK(i == 0 ? chunk_info[i].first_chunk == 1
795  : chunk_info[i].first_chunk > chunk_info[i - 1].first_chunk);
796  }
797  return true;
798 }
799 
800 size_t SampleToChunk::ComputeSizeInternal() {
801  return HeaderSize() + sizeof(uint32_t) +
802  sizeof(ChunkInfo) * chunk_info.size();
803 }
804 
805 SampleSize::SampleSize() = default;
806 SampleSize::~SampleSize() = default;
807 
808 FourCC SampleSize::BoxType() const {
809  return FOURCC_stsz;
810 }
811 
812 bool SampleSize::ReadWriteInternal(BoxBuffer* buffer) {
813  RCHECK(ReadWriteHeaderInternal(buffer) &&
814  buffer->ReadWriteUInt32(&sample_size) &&
815  buffer->ReadWriteUInt32(&sample_count));
816 
817  if (sample_size == 0) {
818  if (buffer->Reading())
819  sizes.resize(sample_count);
820  else
821  DCHECK(sample_count == sizes.size());
822  for (uint32_t i = 0; i < sample_count; ++i)
823  RCHECK(buffer->ReadWriteUInt32(&sizes[i]));
824  }
825  return true;
826 }
827 
828 size_t SampleSize::ComputeSizeInternal() {
829  return HeaderSize() + sizeof(sample_size) + sizeof(sample_count) +
830  (sample_size == 0 ? sizeof(uint32_t) * sizes.size() : 0);
831 }
832 
833 CompactSampleSize::CompactSampleSize() = default;
834 CompactSampleSize::~CompactSampleSize() = default;
835 
837  return FOURCC_stz2;
838 }
839 
840 bool CompactSampleSize::ReadWriteInternal(BoxBuffer* buffer) {
841  uint32_t sample_count = static_cast<uint32_t>(sizes.size());
842  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->IgnoreBytes(3) &&
843  buffer->ReadWriteUInt8(&field_size) &&
844  buffer->ReadWriteUInt32(&sample_count));
845 
846  // Reserve one more entry if field size is 4 bits.
847  sizes.resize(sample_count + (field_size == 4 ? 1 : 0), 0);
848  switch (field_size) {
849  case 4:
850  for (uint32_t i = 0; i < sample_count; i += 2) {
851  if (buffer->Reading()) {
852  uint8_t size = 0;
853  RCHECK(buffer->ReadWriteUInt8(&size));
854  sizes[i] = size >> 4;
855  sizes[i + 1] = size & 0x0F;
856  } else {
857  DCHECK_LT(sizes[i], 16u);
858  DCHECK_LT(sizes[i + 1], 16u);
859  uint8_t size = (sizes[i] << 4) | sizes[i + 1];
860  RCHECK(buffer->ReadWriteUInt8(&size));
861  }
862  }
863  break;
864  case 8:
865  for (uint32_t i = 0; i < sample_count; ++i) {
866  uint8_t size = sizes[i];
867  RCHECK(buffer->ReadWriteUInt8(&size));
868  sizes[i] = size;
869  }
870  break;
871  case 16:
872  for (uint32_t i = 0; i < sample_count; ++i) {
873  uint16_t size = sizes[i];
874  RCHECK(buffer->ReadWriteUInt16(&size));
875  sizes[i] = size;
876  }
877  break;
878  default:
879  RCHECK(false);
880  }
881  sizes.resize(sample_count);
882  return true;
883 }
884 
885 size_t CompactSampleSize::ComputeSizeInternal() {
886  return HeaderSize() + sizeof(uint32_t) + sizeof(uint32_t) +
887  (field_size * sizes.size() + 7) / 8;
888 }
889 
890 ChunkOffset::ChunkOffset() = default;
891 ChunkOffset::~ChunkOffset() = default;
892 
893 FourCC ChunkOffset::BoxType() const {
894  return FOURCC_stco;
895 }
896 
897 bool ChunkOffset::ReadWriteInternal(BoxBuffer* buffer) {
898  uint32_t count = static_cast<uint32_t>(offsets.size());
899  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
900 
901  offsets.resize(count);
902  for (uint32_t i = 0; i < count; ++i)
903  RCHECK(buffer->ReadWriteUInt64NBytes(&offsets[i], sizeof(uint32_t)));
904  return true;
905 }
906 
907 size_t ChunkOffset::ComputeSizeInternal() {
908  return HeaderSize() + sizeof(uint32_t) + sizeof(uint32_t) * offsets.size();
909 }
910 
911 ChunkLargeOffset::ChunkLargeOffset() = default;
912 ChunkLargeOffset::~ChunkLargeOffset() = default;
913 
915  return FOURCC_co64;
916 }
917 
918 bool ChunkLargeOffset::ReadWriteInternal(BoxBuffer* buffer) {
919  uint32_t count = static_cast<uint32_t>(offsets.size());
920 
921  if (!buffer->Reading()) {
922  // Switch to ChunkOffset box if it is able to fit in 32 bits offset.
923  if (count == 0 || IsFitIn32Bits(offsets[count - 1])) {
924  ChunkOffset stco;
925  stco.offsets.swap(offsets);
926  DCHECK(buffer->writer());
927  stco.Write(buffer->writer());
928  stco.offsets.swap(offsets);
929  return true;
930  }
931  }
932 
933  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
934 
935  offsets.resize(count);
936  for (uint32_t i = 0; i < count; ++i)
937  RCHECK(buffer->ReadWriteUInt64(&offsets[i]));
938  return true;
939 }
940 
941 size_t ChunkLargeOffset::ComputeSizeInternal() {
942  uint32_t count = static_cast<uint32_t>(offsets.size());
943  int use_large_offset =
944  (count > 0 && !IsFitIn32Bits(offsets[count - 1])) ? 1 : 0;
945  return HeaderSize() + sizeof(count) +
946  sizeof(uint32_t) * (1 + use_large_offset) * offsets.size();
947 }
948 
949 SyncSample::SyncSample() = default;
950 SyncSample::~SyncSample() = default;
951 
952 FourCC SyncSample::BoxType() const {
953  return FOURCC_stss;
954 }
955 
956 bool SyncSample::ReadWriteInternal(BoxBuffer* buffer) {
957  uint32_t count = static_cast<uint32_t>(sample_number.size());
958  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
959 
960  sample_number.resize(count);
961  for (uint32_t i = 0; i < count; ++i)
962  RCHECK(buffer->ReadWriteUInt32(&sample_number[i]));
963  return true;
964 }
965 
966 size_t SyncSample::ComputeSizeInternal() {
967  // Sync sample box is optional. Skip it if it is empty.
968  if (sample_number.empty())
969  return 0;
970  return HeaderSize() + sizeof(uint32_t) +
971  sizeof(uint32_t) * sample_number.size();
972 }
973 
974 bool CencSampleEncryptionInfoEntry::ReadWrite(BoxBuffer* buffer) {
975  if (!buffer->Reading()) {
976  if (key_id.size() != kCencKeyIdSize) {
977  LOG(WARNING) << "CENC defines key id length of " << kCencKeyIdSize
978  << " bytes; got " << key_id.size()
979  << ". Resized accordingly.";
980  key_id.resize(kCencKeyIdSize);
981  }
982  RCHECK(crypt_byte_block < 16 && skip_byte_block < 16);
983  }
984 
985  RCHECK(buffer->IgnoreBytes(1)); // reserved.
986 
987  uint8_t pattern = crypt_byte_block << 4 | skip_byte_block;
988  RCHECK(buffer->ReadWriteUInt8(&pattern));
989  crypt_byte_block = pattern >> 4;
990  skip_byte_block = pattern & 0x0F;
991 
992  RCHECK(buffer->ReadWriteUInt8(&is_protected) &&
993  buffer->ReadWriteUInt8(&per_sample_iv_size) &&
994  buffer->ReadWriteVector(&key_id, kCencKeyIdSize));
995 
996  if (is_protected == 1) {
997  if (per_sample_iv_size == 0) { // For constant iv.
998  uint8_t constant_iv_size = static_cast<uint8_t>(constant_iv.size());
999  RCHECK(buffer->ReadWriteUInt8(&constant_iv_size));
1000  RCHECK(constant_iv_size == 8 || constant_iv_size == 16);
1001  RCHECK(buffer->ReadWriteVector(&constant_iv, constant_iv_size));
1002  } else {
1003  RCHECK(per_sample_iv_size == 8 || per_sample_iv_size == 16);
1004  DCHECK(constant_iv.empty());
1005  }
1006  } else {
1007  // Expect |is_protected| to be 0, i.e. not protected. Other values of
1008  // |is_protected| is not supported.
1009  RCHECK(is_protected == 0);
1010  RCHECK(per_sample_iv_size == 0);
1011  }
1012  return true;
1013 }
1014 
1015 uint32_t CencSampleEncryptionInfoEntry::ComputeSize() const {
1016  return static_cast<uint32_t>(
1017  sizeof(uint32_t) + kCencKeyIdSize +
1018  (constant_iv.empty() ? 0 : (sizeof(uint8_t) + constant_iv.size())));
1019 }
1020 
1021 bool AudioRollRecoveryEntry::ReadWrite(BoxBuffer* buffer) {
1022  RCHECK(buffer->ReadWriteInt16(&roll_distance));
1023  return true;
1024 }
1025 
1026 uint32_t AudioRollRecoveryEntry::ComputeSize() const {
1027  return sizeof(roll_distance);
1028 }
1029 
1030 SampleGroupDescription::SampleGroupDescription() = default;
1031 SampleGroupDescription::~SampleGroupDescription() = default;
1032 
1034  return FOURCC_sgpd;
1035 }
1036 
1037 bool SampleGroupDescription::ReadWriteInternal(BoxBuffer* buffer) {
1038  RCHECK(ReadWriteHeaderInternal(buffer) &&
1039  buffer->ReadWriteUInt32(&grouping_type));
1040 
1041  switch (grouping_type) {
1042  case FOURCC_seig:
1043  return ReadWriteEntries(buffer, &cenc_sample_encryption_info_entries);
1044  case FOURCC_roll:
1045  return ReadWriteEntries(buffer, &audio_roll_recovery_entries);
1046  default:
1047  DCHECK(buffer->Reading());
1048  DLOG(WARNING) << "Ignore unsupported sample group: "
1049  << FourCCToString(static_cast<FourCC>(grouping_type));
1050  return true;
1051  }
1052 }
1053 
1054 template <typename T>
1055 bool SampleGroupDescription::ReadWriteEntries(BoxBuffer* buffer,
1056  std::vector<T>* entries) {
1057  uint32_t default_length = 0;
1058  if (!buffer->Reading()) {
1059  DCHECK(!entries->empty());
1060  default_length = (*entries)[0].ComputeSize();
1061  DCHECK_NE(default_length, 0u);
1062  }
1063  if (version == 1)
1064  RCHECK(buffer->ReadWriteUInt32(&default_length));
1065  if (version >= 2) {
1066  NOTIMPLEMENTED() << "Unsupported SampleGroupDescriptionBox 'sgpd' version "
1067  << static_cast<int>(version);
1068  return false;
1069  }
1070 
1071  uint32_t count = static_cast<uint32_t>(entries->size());
1072  RCHECK(buffer->ReadWriteUInt32(&count));
1073  if (buffer->Reading()) {
1074  if (count == 0)
1075  return true;
1076  } else {
1077  RCHECK(count != 0);
1078  }
1079  entries->resize(count);
1080 
1081  for (T& entry : *entries) {
1082  if (version == 1) {
1083  uint32_t description_length = default_length;
1084  if (buffer->Reading() && default_length == 0)
1085  RCHECK(buffer->ReadWriteUInt32(&description_length));
1086  RCHECK(entry.ReadWrite(buffer));
1087  RCHECK(entry.ComputeSize() == description_length);
1088  } else {
1089  RCHECK(entry.ReadWrite(buffer));
1090  }
1091  }
1092  return true;
1093 }
1094 
1095 size_t SampleGroupDescription::ComputeSizeInternal() {
1096  // Version 0 is obsoleted, so always generate version 1 box.
1097  version = 1;
1098  size_t entries_size = 0;
1099  switch (grouping_type) {
1100  case FOURCC_seig:
1101  for (const auto& entry : cenc_sample_encryption_info_entries)
1102  entries_size += entry.ComputeSize();
1103  break;
1104  case FOURCC_roll:
1105  for (const auto& entry : audio_roll_recovery_entries)
1106  entries_size += entry.ComputeSize();
1107  break;
1108  }
1109  // This box is optional. Skip it if it is not used.
1110  if (entries_size == 0)
1111  return 0;
1112  return HeaderSize() + sizeof(grouping_type) +
1113  (version == 1 ? sizeof(uint32_t) : 0) + sizeof(uint32_t) +
1114  entries_size;
1115 }
1116 
1117 SampleToGroup::SampleToGroup() = default;
1118 SampleToGroup::~SampleToGroup() = default;
1119 
1120 FourCC SampleToGroup::BoxType() const {
1121  return FOURCC_sbgp;
1122 }
1123 
1124 bool SampleToGroup::ReadWriteInternal(BoxBuffer* buffer) {
1125  RCHECK(ReadWriteHeaderInternal(buffer) &&
1126  buffer->ReadWriteUInt32(&grouping_type));
1127  if (version == 1)
1128  RCHECK(buffer->ReadWriteUInt32(&grouping_type_parameter));
1129 
1130  if (grouping_type != FOURCC_seig && grouping_type != FOURCC_roll) {
1131  DCHECK(buffer->Reading());
1132  DLOG(WARNING) << "Ignore unsupported sample group: "
1133  << FourCCToString(static_cast<FourCC>(grouping_type));
1134  return true;
1135  }
1136 
1137  uint32_t count = static_cast<uint32_t>(entries.size());
1138  RCHECK(buffer->ReadWriteUInt32(&count));
1139  entries.resize(count);
1140  for (uint32_t i = 0; i < count; ++i) {
1141  RCHECK(buffer->ReadWriteUInt32(&entries[i].sample_count) &&
1142  buffer->ReadWriteUInt32(&entries[i].group_description_index));
1143  }
1144  return true;
1145 }
1146 
1147 size_t SampleToGroup::ComputeSizeInternal() {
1148  // This box is optional. Skip it if it is not used.
1149  if (entries.empty())
1150  return 0;
1151  return HeaderSize() + sizeof(grouping_type) +
1152  (version == 1 ? sizeof(grouping_type_parameter) : 0) +
1153  sizeof(uint32_t) + entries.size() * sizeof(entries[0]);
1154 }
1155 
1156 SampleTable::SampleTable() = default;
1157 SampleTable::~SampleTable() = default;
1158 
1159 FourCC SampleTable::BoxType() const {
1160  return FOURCC_stbl;
1161 }
1162 
1163 bool SampleTable::ReadWriteInternal(BoxBuffer* buffer) {
1164  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
1165  buffer->ReadWriteChild(&description) &&
1166  buffer->ReadWriteChild(&decoding_time_to_sample) &&
1167  buffer->TryReadWriteChild(&composition_time_to_sample) &&
1168  buffer->ReadWriteChild(&sample_to_chunk));
1169 
1170  if (buffer->Reading()) {
1171  BoxReader* reader = buffer->reader();
1172  DCHECK(reader);
1173 
1174  // Either SampleSize or CompactSampleSize must present.
1175  if (reader->ChildExist(&sample_size)) {
1176  RCHECK(reader->ReadChild(&sample_size));
1177  } else {
1178  CompactSampleSize compact_sample_size;
1179  RCHECK(reader->ReadChild(&compact_sample_size));
1180  sample_size.sample_size = 0;
1181  sample_size.sample_count =
1182  static_cast<uint32_t>(compact_sample_size.sizes.size());
1183  sample_size.sizes.swap(compact_sample_size.sizes);
1184  }
1185 
1186  // Either ChunkOffset or ChunkLargeOffset must present.
1187  if (reader->ChildExist(&chunk_large_offset)) {
1188  RCHECK(reader->ReadChild(&chunk_large_offset));
1189  } else {
1190  ChunkOffset chunk_offset;
1191  RCHECK(reader->ReadChild(&chunk_offset));
1192  chunk_large_offset.offsets.swap(chunk_offset.offsets);
1193  }
1194  } else {
1195  RCHECK(buffer->ReadWriteChild(&sample_size) &&
1196  buffer->ReadWriteChild(&chunk_large_offset));
1197  }
1198  RCHECK(buffer->TryReadWriteChild(&sync_sample));
1199  if (buffer->Reading()) {
1200  RCHECK(buffer->reader()->TryReadChildren(&sample_group_descriptions) &&
1201  buffer->reader()->TryReadChildren(&sample_to_groups));
1202  } else {
1203  for (auto& sample_group_description : sample_group_descriptions)
1204  RCHECK(buffer->ReadWriteChild(&sample_group_description));
1205  for (auto& sample_to_group : sample_to_groups)
1206  RCHECK(buffer->ReadWriteChild(&sample_to_group));
1207  }
1208  return true;
1209 }
1210 
1211 size_t SampleTable::ComputeSizeInternal() {
1212  size_t box_size = HeaderSize() + description.ComputeSize() +
1213  decoding_time_to_sample.ComputeSize() +
1214  composition_time_to_sample.ComputeSize() +
1215  sample_to_chunk.ComputeSize() + sample_size.ComputeSize() +
1216  chunk_large_offset.ComputeSize() +
1217  sync_sample.ComputeSize();
1218  for (auto& sample_group_description : sample_group_descriptions)
1219  box_size += sample_group_description.ComputeSize();
1220  for (auto& sample_to_group : sample_to_groups)
1221  box_size += sample_to_group.ComputeSize();
1222  return box_size;
1223 }
1224 
1225 EditList::EditList() = default;
1226 EditList::~EditList() = default;
1227 
1228 FourCC EditList::BoxType() const {
1229  return FOURCC_elst;
1230 }
1231 
1232 bool EditList::ReadWriteInternal(BoxBuffer* buffer) {
1233  uint32_t count = static_cast<uint32_t>(edits.size());
1234  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
1235  edits.resize(count);
1236 
1237  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
1238  for (uint32_t i = 0; i < count; ++i) {
1239  RCHECK(
1240  buffer->ReadWriteUInt64NBytes(&edits[i].segment_duration, num_bytes) &&
1241  buffer->ReadWriteInt64NBytes(&edits[i].media_time, num_bytes) &&
1242  buffer->ReadWriteInt16(&edits[i].media_rate_integer) &&
1243  buffer->ReadWriteInt16(&edits[i].media_rate_fraction));
1244  }
1245  return true;
1246 }
1247 
1248 size_t EditList::ComputeSizeInternal() {
1249  // EditList box is optional. Skip it if it is empty.
1250  if (edits.empty())
1251  return 0;
1252 
1253  version = 0;
1254  for (uint32_t i = 0; i < edits.size(); ++i) {
1255  if (!IsFitIn32Bits(edits[i].segment_duration, edits[i].media_time)) {
1256  version = 1;
1257  break;
1258  }
1259  }
1260  return HeaderSize() + sizeof(uint32_t) +
1261  (sizeof(uint32_t) * (1 + version) * 2 + sizeof(int16_t) * 2) *
1262  edits.size();
1263 }
1264 
1265 Edit::Edit() = default;
1266 Edit::~Edit() = default;
1267 
1268 FourCC Edit::BoxType() const {
1269  return FOURCC_edts;
1270 }
1271 
1272 bool Edit::ReadWriteInternal(BoxBuffer* buffer) {
1273  return ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
1274  buffer->ReadWriteChild(&list);
1275 }
1276 
1277 size_t Edit::ComputeSizeInternal() {
1278  // Edit box is optional. Skip it if it is empty.
1279  if (list.edits.empty())
1280  return 0;
1281  return HeaderSize() + list.ComputeSize();
1282 }
1283 
1284 HandlerReference::HandlerReference() = default;
1285 HandlerReference::~HandlerReference() = default;
1286 
1288  return FOURCC_hdlr;
1289 }
1290 
1291 bool HandlerReference::ReadWriteInternal(BoxBuffer* buffer) {
1292  std::vector<uint8_t> handler_name;
1293  if (!buffer->Reading()) {
1294  switch (handler_type) {
1295  case FOURCC_vide:
1296  handler_name.assign(kVideoHandlerName,
1297  kVideoHandlerName + std::size(kVideoHandlerName));
1298  break;
1299  case FOURCC_soun:
1300  handler_name.assign(kAudioHandlerName,
1301  kAudioHandlerName + std::size(kAudioHandlerName));
1302  break;
1303  case FOURCC_text:
1304  handler_name.assign(kTextHandlerName,
1305  kTextHandlerName + std::size(kTextHandlerName));
1306  break;
1307  case FOURCC_subt:
1308  handler_name.assign(
1309  kSubtitleHandlerName,
1310  kSubtitleHandlerName + std::size(kSubtitleHandlerName));
1311  break;
1312  case FOURCC_ID32:
1313  break;
1314  default:
1315  NOTIMPLEMENTED();
1316  return false;
1317  }
1318  }
1319  RCHECK(ReadWriteHeaderInternal(buffer) &&
1320  buffer->IgnoreBytes(4) && // predefined.
1321  buffer->ReadWriteFourCC(&handler_type));
1322  if (!buffer->Reading()) {
1323  RCHECK(buffer->IgnoreBytes(12) && // reserved.
1324  buffer->ReadWriteVector(&handler_name, handler_name.size()));
1325  }
1326  return true;
1327 }
1328 
1329 size_t HandlerReference::ComputeSizeInternal() {
1330  size_t box_size = HeaderSize() + kFourCCSize + 16; // 16 bytes Reserved
1331  switch (handler_type) {
1332  case FOURCC_vide:
1333  box_size += sizeof(kVideoHandlerName);
1334  break;
1335  case FOURCC_soun:
1336  box_size += sizeof(kAudioHandlerName);
1337  break;
1338  case FOURCC_text:
1339  box_size += sizeof(kTextHandlerName);
1340  break;
1341  case FOURCC_subt:
1342  box_size += sizeof(kSubtitleHandlerName);
1343  break;
1344  case FOURCC_ID32:
1345  break;
1346  default:
1347  NOTIMPLEMENTED();
1348  }
1349  return box_size;
1350 }
1351 
1352 bool Language::ReadWrite(BoxBuffer* buffer) {
1353  if (buffer->Reading()) {
1354  // Read language codes into temp first then use BitReader to read the
1355  // values. ISO-639-2/T language code: unsigned int(5)[3] language (2 bytes).
1356  std::vector<uint8_t> temp;
1357  RCHECK(buffer->ReadWriteVector(&temp, 2));
1358 
1359  BitReader bit_reader(&temp[0], 2);
1360  bit_reader.SkipBits(1);
1361  char language[3];
1362  for (int i = 0; i < 3; ++i) {
1363  CHECK(bit_reader.ReadBits(5, &language[i]));
1364  language[i] += 0x60;
1365  }
1366  code.assign(language, 3);
1367  } else {
1368  // Set up default language if it is not set.
1369  const char kUndefinedLanguage[] = "und";
1370  if (code.empty())
1371  code = kUndefinedLanguage;
1372  DCHECK_EQ(code.size(), 3u);
1373 
1374  // Lang format: bit(1) pad, unsigned int(5)[3] language.
1375  uint16_t lang = 0;
1376  for (int i = 0; i < 3; ++i)
1377  lang |= (code[i] - 0x60) << ((2 - i) * 5);
1378  RCHECK(buffer->ReadWriteUInt16(&lang));
1379  }
1380  return true;
1381 }
1382 
1383 uint32_t Language::ComputeSize() const {
1384  // ISO-639-2/T language code: unsigned int(5)[3] language (2 bytes).
1385  return 2;
1386 }
1387 
1388 ID3v2::ID3v2() = default;
1389 ID3v2::~ID3v2() = default;
1390 
1391 FourCC ID3v2::BoxType() const {
1392  return FOURCC_ID32;
1393 }
1394 
1395 bool ID3v2::ReadWriteInternal(BoxBuffer* buffer) {
1396  RCHECK(ReadWriteHeaderInternal(buffer) && language.ReadWrite(buffer) &&
1397  buffer->ReadWriteVector(&id3v2_data, buffer->Reading()
1398  ? buffer->BytesLeft()
1399  : id3v2_data.size()));
1400  return true;
1401 }
1402 
1403 size_t ID3v2::ComputeSizeInternal() {
1404  // Skip ID3v2 box generation if there is no id3 data.
1405  return id3v2_data.size() == 0
1406  ? 0
1407  : HeaderSize() + language.ComputeSize() + id3v2_data.size();
1408 }
1409 
1410 Metadata::Metadata() = default;
1411 Metadata::~Metadata() = default;
1412 
1413 FourCC Metadata::BoxType() const {
1414  return FOURCC_meta;
1415 }
1416 
1417 bool Metadata::ReadWriteInternal(BoxBuffer* buffer) {
1418  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
1419  buffer->ReadWriteChild(&handler) && buffer->TryReadWriteChild(&id3v2));
1420  return true;
1421 }
1422 
1423 size_t Metadata::ComputeSizeInternal() {
1424  size_t id3v2_size = id3v2.ComputeSize();
1425  // Skip metadata box generation if there is no metadata box.
1426  return id3v2_size == 0 ? 0
1427  : HeaderSize() + handler.ComputeSize() + id3v2_size;
1428 }
1429 
1430 CodecConfiguration::CodecConfiguration() = default;
1431 CodecConfiguration::~CodecConfiguration() = default;
1432 
1434  // CodecConfiguration box should be parsed according to format recovered in
1435  // VideoSampleEntry. |box_type| is determined dynamically there.
1436  return box_type;
1437 }
1438 
1439 bool CodecConfiguration::ReadWriteInternal(BoxBuffer* buffer) {
1440  DCHECK_NE(box_type, FOURCC_NULL);
1441  RCHECK(ReadWriteHeaderInternal(buffer));
1442 
1443  // VPCodecConfiguration box inherits from FullBox instead of Box. The extra 4
1444  // bytes are handled here.
1445  if (box_type == FOURCC_vpcC) {
1446  // Only version 1 box is supported.
1447  uint8_t vpcc_version = 1;
1448  uint32_t version_flags = vpcc_version << 24;
1449  RCHECK(buffer->ReadWriteUInt32(&version_flags));
1450  vpcc_version = version_flags >> 24;
1451  RCHECK(vpcc_version == 1);
1452  }
1453 
1454  if (buffer->Reading()) {
1455  RCHECK(buffer->ReadWriteVector(&data, buffer->BytesLeft()));
1456  } else {
1457  RCHECK(buffer->ReadWriteVector(&data, data.size()));
1458  }
1459  return true;
1460 }
1461 
1462 size_t CodecConfiguration::ComputeSizeInternal() {
1463  if (data.empty())
1464  return 0;
1465  DCHECK_NE(box_type, FOURCC_NULL);
1466  return HeaderSize() + (box_type == FOURCC_vpcC ? 4 : 0) + data.size();
1467 }
1468 
1469 ColorParameters::ColorParameters() = default;
1470 ColorParameters::~ColorParameters() = default;
1471 
1473  return FOURCC_colr;
1474 }
1475 
1476 bool ColorParameters::ReadWriteInternal(BoxBuffer* buffer) {
1477  if (buffer->Reading()) {
1478  BoxReader* reader = buffer->reader();
1479  DCHECK(reader);
1480 
1481  // Parse and store the raw box for colr atom preservation in the output mp4.
1482  raw_box.assign(reader->data(), reader->data() + reader->size());
1483 
1484  // Parse individual parameters for full codec string formation.
1485  RCHECK(reader->ReadFourCC(&color_parameter_type) &&
1486  reader->Read2(&color_primaries) &&
1487  reader->Read2(&transfer_characteristics) &&
1488  reader->Read2(&matrix_coefficients));
1489  // Type nclc does not contain video_full_range_flag data, and thus, it has 1
1490  // less byte than nclx. Only extract video_full_range_flag if of type nclx.
1491  if (color_parameter_type == FOURCC_nclx) {
1492  RCHECK(reader->Read1(&video_full_range_flag));
1493  }
1494  } else {
1495  // When writing, only need to write the raw_box.
1496  DCHECK(!raw_box.empty());
1497  buffer->writer()->AppendVector(raw_box);
1498  }
1499  return true;
1500 }
1501 
1502 size_t ColorParameters::ComputeSizeInternal() {
1503  return raw_box.size();
1504 }
1505 
1506 PixelAspectRatio::PixelAspectRatio() = default;
1507 PixelAspectRatio::~PixelAspectRatio() = default;
1508 
1510  return FOURCC_pasp;
1511 }
1512 
1513 bool PixelAspectRatio::ReadWriteInternal(BoxBuffer* buffer) {
1514  RCHECK(ReadWriteHeaderInternal(buffer) &&
1515  buffer->ReadWriteUInt32(&h_spacing) &&
1516  buffer->ReadWriteUInt32(&v_spacing));
1517  return true;
1518 }
1519 
1520 size_t PixelAspectRatio::ComputeSizeInternal() {
1521  // This box is optional. Skip it if it is not initialized.
1522  if (h_spacing == 0 && v_spacing == 0)
1523  return 0;
1524  // Both values must be positive.
1525  DCHECK(h_spacing != 0 && v_spacing != 0);
1526  return HeaderSize() + sizeof(h_spacing) + sizeof(v_spacing);
1527 }
1528 
1529 VideoSampleEntry::VideoSampleEntry() = default;
1530 VideoSampleEntry::~VideoSampleEntry() = default;
1531 
1533  if (format == FOURCC_NULL) {
1534  LOG(ERROR) << "VideoSampleEntry should be parsed according to the "
1535  << "handler type recovered in its Media ancestor.";
1536  }
1537  return format;
1538 }
1539 
1540 bool VideoSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
1541  std::vector<uint8_t> compressor_name;
1542  if (buffer->Reading()) {
1543  DCHECK(buffer->reader());
1544  format = buffer->reader()->type();
1545  } else {
1546  RCHECK(ReadWriteHeaderInternal(buffer));
1547 
1548  const FourCC actual_format = GetActualFormat();
1549  switch (actual_format) {
1550  case FOURCC_av01:
1551  compressor_name.assign(std::begin(kAv1CompressorName),
1552  std::end(kAv1CompressorName));
1553  break;
1554  case FOURCC_avc1:
1555  case FOURCC_avc3:
1556  compressor_name.assign(std::begin(kAvcCompressorName),
1557  std::end(kAvcCompressorName));
1558  break;
1559  case FOURCC_dvh1:
1560  case FOURCC_dvhe:
1561  compressor_name.assign(std::begin(kDolbyVisionCompressorName),
1562  std::end(kDolbyVisionCompressorName));
1563  break;
1564  case FOURCC_hev1:
1565  case FOURCC_hvc1:
1566  compressor_name.assign(std::begin(kHevcCompressorName),
1567  std::end(kHevcCompressorName));
1568  break;
1569  case FOURCC_vp08:
1570  case FOURCC_vp09:
1571  compressor_name.assign(std::begin(kVpcCompressorName),
1572  std::end(kVpcCompressorName));
1573  break;
1574  default:
1575  LOG(ERROR) << FourCCToString(actual_format) << " is not supported.";
1576  return false;
1577  }
1578  compressor_name.resize(kCompressorNameSize);
1579  }
1580 
1581  uint32_t video_resolution = kVideoResolution;
1582  uint16_t video_frame_count = kVideoFrameCount;
1583  uint16_t video_depth = kVideoDepth;
1584  int16_t predefined = -1;
1585  RCHECK(buffer->IgnoreBytes(6) && // reserved.
1586  buffer->ReadWriteUInt16(&data_reference_index) &&
1587  buffer->IgnoreBytes(16) && // predefined 0.
1588  buffer->ReadWriteUInt16(&width) && buffer->ReadWriteUInt16(&height) &&
1589  buffer->ReadWriteUInt32(&video_resolution) &&
1590  buffer->ReadWriteUInt32(&video_resolution) &&
1591  buffer->IgnoreBytes(4) && // reserved.
1592  buffer->ReadWriteUInt16(&video_frame_count) &&
1593  buffer->ReadWriteVector(&compressor_name, kCompressorNameSize) &&
1594  buffer->ReadWriteUInt16(&video_depth) &&
1595  buffer->ReadWriteInt16(&predefined));
1596 
1597  RCHECK(buffer->PrepareChildren());
1598 
1599  // This has to happen before reading codec configuration box as the actual
1600  // format is read from sinf.format.format, which is needed to parse the codec
1601  // configuration box.
1602  if (format == FOURCC_encv && buffer->Reading()) {
1603  // Continue scanning until a supported protection scheme is found, or
1604  // until we run out of protection schemes.
1605  while (!IsProtectionSchemeSupported(sinf.type.type))
1606  RCHECK(buffer->ReadWriteChild(&sinf));
1607  }
1608 
1609  const FourCC actual_format = GetActualFormat();
1610  if (buffer->Reading()) {
1611  codec_configuration.box_type = GetCodecConfigurationBoxType(actual_format);
1612  } else {
1613  DCHECK_EQ(codec_configuration.box_type,
1614  GetCodecConfigurationBoxType(actual_format));
1615  }
1616  if (codec_configuration.box_type == FOURCC_NULL)
1617  return false;
1618 
1619  RCHECK(buffer->ReadWriteChild(&codec_configuration));
1620 
1621  if (buffer->Reading()) {
1622  extra_codec_configs.clear();
1623  // Handle Dolby Vision boxes.
1624  const bool is_hevc =
1625  actual_format == FOURCC_dvhe || actual_format == FOURCC_dvh1 ||
1626  actual_format == FOURCC_hev1 || actual_format == FOURCC_hvc1;
1627  if (is_hevc) {
1628  for (FourCC fourcc : {FOURCC_dvcC, FOURCC_dvvC, FOURCC_hvcE}) {
1629  CodecConfiguration dv_box;
1630  dv_box.box_type = fourcc;
1631  RCHECK(buffer->TryReadWriteChild(&dv_box));
1632  if (!dv_box.data.empty())
1633  extra_codec_configs.push_back(std::move(dv_box));
1634  }
1635  }
1636  const bool is_av1 = actual_format == FOURCC_av01;
1637  if (is_av1) {
1638  for (FourCC fourcc : {FOURCC_dvvC}) {
1639  CodecConfiguration dv_box;
1640  dv_box.box_type = fourcc;
1641  RCHECK(buffer->TryReadWriteChild(&dv_box));
1642  if (!dv_box.data.empty())
1643  extra_codec_configs.push_back(std::move(dv_box));
1644  }
1645  }
1646  } else {
1647  for (CodecConfiguration& extra_codec_config : extra_codec_configs)
1648  RCHECK(buffer->ReadWriteChild(&extra_codec_config));
1649  }
1650 
1651  RCHECK(buffer->TryReadWriteChild(&colr));
1652  RCHECK(buffer->TryReadWriteChild(&pixel_aspect));
1653 
1654  // Somehow Edge does not support having sinf box before codec_configuration,
1655  // box, so just do it in the end of VideoSampleEntry. See
1656  // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12658991/
1657  if (format == FOURCC_encv && !buffer->Reading()) {
1658  DCHECK(IsProtectionSchemeSupported(sinf.type.type));
1659  RCHECK(buffer->ReadWriteChild(&sinf));
1660  }
1661  return true;
1662 }
1663 
1664 size_t VideoSampleEntry::ComputeSizeInternal() {
1665  const FourCC actual_format = GetActualFormat();
1666  if (actual_format == FOURCC_NULL)
1667  return 0;
1668  codec_configuration.box_type = GetCodecConfigurationBoxType(actual_format);
1669  DCHECK_NE(codec_configuration.box_type, FOURCC_NULL);
1670  size_t size = HeaderSize() + sizeof(data_reference_index) + sizeof(width) +
1671  sizeof(height) + sizeof(kVideoResolution) * 2 +
1672  sizeof(kVideoFrameCount) + sizeof(kVideoDepth) +
1673  colr.ComputeSize() + pixel_aspect.ComputeSize() +
1674  sinf.ComputeSize() + codec_configuration.ComputeSize() +
1675  kCompressorNameSize + 6 + 4 + 16 +
1676  2; // 6 + 4 bytes reserved, 16 + 2 bytes predefined.
1677  for (CodecConfiguration& codec_config : extra_codec_configs)
1678  size += codec_config.ComputeSize();
1679  return size;
1680 }
1681 
1682 FourCC VideoSampleEntry::GetCodecConfigurationBoxType(FourCC l_format) const {
1683  switch (l_format) {
1684  case FOURCC_av01:
1685  return FOURCC_av1C;
1686  case FOURCC_avc1:
1687  case FOURCC_avc3:
1688  return FOURCC_avcC;
1689  case FOURCC_dvh1:
1690  case FOURCC_dvhe:
1691  case FOURCC_hev1:
1692  case FOURCC_hvc1:
1693  return FOURCC_hvcC;
1694  case FOURCC_vp08:
1695  case FOURCC_vp09:
1696  return FOURCC_vpcC;
1697  default:
1698  LOG(ERROR) << FourCCToString(l_format) << " is not supported.";
1699  return FOURCC_NULL;
1700  }
1701 }
1702 
1703 std::vector<uint8_t> VideoSampleEntry::ExtraCodecConfigsAsVector() const {
1704  BufferWriter buffer;
1705  for (CodecConfiguration codec_config : extra_codec_configs)
1706  codec_config.Write(&buffer);
1707  return std::vector<uint8_t>(buffer.Buffer(), buffer.Buffer() + buffer.Size());
1708 }
1709 
1710 bool VideoSampleEntry::ParseExtraCodecConfigsVector(
1711  const std::vector<uint8_t>& data) {
1712  extra_codec_configs.clear();
1713  size_t pos = 0;
1714  while (pos < data.size()) {
1715  bool err = false;
1716  std::unique_ptr<BoxReader> box_reader(
1717  BoxReader::ReadBox(data.data() + pos, data.size() - pos, &err));
1718  RCHECK(!err && box_reader);
1719 
1720  CodecConfiguration codec_config;
1721  codec_config.box_type = box_reader->type();
1722  RCHECK(codec_config.Parse(box_reader.get()));
1723  extra_codec_configs.push_back(std::move(codec_config));
1724 
1725  pos += box_reader->pos();
1726  }
1727  return true;
1728 }
1729 
1730 ElementaryStreamDescriptor::ElementaryStreamDescriptor() = default;
1731 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() = default;
1732 
1734  return FOURCC_esds;
1735 }
1736 
1737 bool ElementaryStreamDescriptor::ReadWriteInternal(BoxBuffer* buffer) {
1738  RCHECK(ReadWriteHeaderInternal(buffer));
1739  if (buffer->Reading()) {
1740  std::vector<uint8_t> data;
1741  RCHECK(buffer->ReadWriteVector(&data, buffer->BytesLeft()));
1742  RCHECK(es_descriptor.Parse(data));
1743  if (es_descriptor.decoder_config_descriptor().IsAAC()) {
1744  RCHECK(aac_audio_specific_config.Parse(
1745  es_descriptor.decoder_config_descriptor()
1746  .decoder_specific_info_descriptor()
1747  .data()));
1748  }
1749  } else {
1750  DCHECK(buffer->writer());
1751  es_descriptor.Write(buffer->writer());
1752  }
1753  return true;
1754 }
1755 
1756 size_t ElementaryStreamDescriptor::ComputeSizeInternal() {
1757  // This box is optional. Skip it if not initialized.
1758  if (es_descriptor.decoder_config_descriptor().object_type() ==
1759  ObjectType::kForbidden) {
1760  return 0;
1761  }
1762  return HeaderSize() + es_descriptor.ComputeSize();
1763 }
1764 
1765 MHAConfiguration::MHAConfiguration() = default;
1766 MHAConfiguration::~MHAConfiguration() = default;
1767 
1769  return FOURCC_mhaC;
1770 }
1771 
1772 bool MHAConfiguration::ReadWriteInternal(BoxBuffer* buffer) {
1773  RCHECK(ReadWriteHeaderInternal(buffer) &&
1774  buffer->ReadWriteVector(
1775  &data, buffer->Reading() ? buffer->BytesLeft() : data.size()));
1776  RCHECK(data.size() > 1);
1777  mpeg_h_3da_profile_level_indication = data[1];
1778  return true;
1779 }
1780 
1781 size_t MHAConfiguration::ComputeSizeInternal() {
1782  // This box is optional. Skip it if not initialized.
1783  if (data.empty())
1784  return 0;
1785  return HeaderSize() + data.size();
1786 }
1787 
1788 DTSSpecific::DTSSpecific() = default;
1789 DTSSpecific::~DTSSpecific() = default;
1790 ;
1791 
1792 FourCC DTSSpecific::BoxType() const {
1793  return FOURCC_ddts;
1794 }
1795 
1796 bool DTSSpecific::ReadWriteInternal(BoxBuffer* buffer) {
1797  RCHECK(ReadWriteHeaderInternal(buffer) &&
1798  buffer->ReadWriteUInt32(&sampling_frequency) &&
1799  buffer->ReadWriteUInt32(&max_bitrate) &&
1800  buffer->ReadWriteUInt32(&avg_bitrate) &&
1801  buffer->ReadWriteUInt8(&pcm_sample_depth));
1802 
1803  if (buffer->Reading()) {
1804  RCHECK(buffer->ReadWriteVector(&extra_data, buffer->BytesLeft()));
1805  } else {
1806  if (extra_data.empty()) {
1807  extra_data.assign(kDdtsExtraData,
1808  kDdtsExtraData + sizeof(kDdtsExtraData));
1809  }
1810  RCHECK(buffer->ReadWriteVector(&extra_data, extra_data.size()));
1811  }
1812  return true;
1813 }
1814 
1815 size_t DTSSpecific::ComputeSizeInternal() {
1816  // This box is optional. Skip it if not initialized.
1817  if (sampling_frequency == 0)
1818  return 0;
1819  return HeaderSize() + sizeof(sampling_frequency) + sizeof(max_bitrate) +
1820  sizeof(avg_bitrate) + sizeof(pcm_sample_depth) +
1821  sizeof(kDdtsExtraData);
1822 }
1823 
1824 UDTSSpecific::UDTSSpecific() = default;
1825 UDTSSpecific::~UDTSSpecific() = default;
1826 
1827 FourCC UDTSSpecific::BoxType() const {
1828  return FOURCC_udts;
1829 }
1830 
1831 bool UDTSSpecific::ReadWriteInternal(BoxBuffer* buffer) {
1832  RCHECK(ReadWriteHeaderInternal(buffer) &&
1833  buffer->ReadWriteVector(
1834  &data, buffer->Reading() ? buffer->BytesLeft() : data.size()));
1835  return true;
1836 }
1837 
1838 size_t UDTSSpecific::ComputeSizeInternal() {
1839  // This box is optional. Skip it if not initialized.
1840  if (data.empty())
1841  return 0;
1842  return HeaderSize() + data.size();
1843 }
1844 
1845 AC3Specific::AC3Specific() = default;
1846 AC3Specific::~AC3Specific() = default;
1847 
1848 FourCC AC3Specific::BoxType() const {
1849  return FOURCC_dac3;
1850 }
1851 
1852 bool AC3Specific::ReadWriteInternal(BoxBuffer* buffer) {
1853  RCHECK(ReadWriteHeaderInternal(buffer) &&
1854  buffer->ReadWriteVector(
1855  &data, buffer->Reading() ? buffer->BytesLeft() : data.size()));
1856  return true;
1857 }
1858 
1859 size_t AC3Specific::ComputeSizeInternal() {
1860  // This box is optional. Skip it if not initialized.
1861  if (data.empty())
1862  return 0;
1863  return HeaderSize() + data.size();
1864 }
1865 
1866 EC3Specific::EC3Specific() = default;
1867 EC3Specific::~EC3Specific() = default;
1868 
1869 FourCC EC3Specific::BoxType() const {
1870  return FOURCC_dec3;
1871 }
1872 
1873 bool EC3Specific::ReadWriteInternal(BoxBuffer* buffer) {
1874  RCHECK(ReadWriteHeaderInternal(buffer));
1875  size_t size = buffer->Reading() ? buffer->BytesLeft() : data.size();
1876  RCHECK(buffer->ReadWriteVector(&data, size));
1877  return true;
1878 }
1879 
1880 size_t EC3Specific::ComputeSizeInternal() {
1881  // This box is optional. Skip it if not initialized.
1882  if (data.empty())
1883  return 0;
1884  return HeaderSize() + data.size();
1885 }
1886 
1887 AC4Specific::AC4Specific() = default;
1888 AC4Specific::~AC4Specific() = default;
1889 
1890 FourCC AC4Specific::BoxType() const {
1891  return FOURCC_dac4;
1892 }
1893 
1894 bool AC4Specific::ReadWriteInternal(BoxBuffer* buffer) {
1895  RCHECK(ReadWriteHeaderInternal(buffer));
1896  size_t size = buffer->Reading() ? buffer->BytesLeft() : data.size();
1897  RCHECK(buffer->ReadWriteVector(&data, size));
1898  return true;
1899 }
1900 
1901 size_t AC4Specific::ComputeSizeInternal() {
1902  // This box is optional. Skip it if not initialized.
1903  if (data.empty())
1904  return 0;
1905  return HeaderSize() + data.size();
1906 }
1907 
1908 OpusSpecific::OpusSpecific() = default;
1909 OpusSpecific::~OpusSpecific() = default;
1910 
1911 FourCC OpusSpecific::BoxType() const {
1912  return FOURCC_dOps;
1913 }
1914 
1915 bool OpusSpecific::ReadWriteInternal(BoxBuffer* buffer) {
1916  RCHECK(ReadWriteHeaderInternal(buffer));
1917  if (buffer->Reading()) {
1918  std::vector<uint8_t> data;
1919  const int kMinOpusSpecificBoxDataSize = 11;
1920  RCHECK(buffer->BytesLeft() >= kMinOpusSpecificBoxDataSize);
1921  RCHECK(buffer->ReadWriteVector(&data, buffer->BytesLeft()));
1922  preskip = data[2] + (data[3] << 8);
1923 
1924  // https://tools.ietf.org/html/draft-ietf-codec-oggopus-06#section-5
1925  BufferWriter writer;
1926  writer.AppendInt(FOURCC_Opus);
1927  writer.AppendInt(FOURCC_Head);
1928  // The version must always be 1.
1929  const uint8_t kOpusIdentificationHeaderVersion = 1;
1930  data[0] = kOpusIdentificationHeaderVersion;
1931  writer.AppendVector(data);
1932  writer.SwapBuffer(&opus_identification_header);
1933  } else {
1934  // https://tools.ietf.org/html/draft-ietf-codec-oggopus-06#section-5
1935  // The first 8 bytes is "magic signature".
1936  const size_t kOpusMagicSignatureSize = 8u;
1937  DCHECK_GT(opus_identification_header.size(), kOpusMagicSignatureSize);
1938  // https://www.opus-codec.org/docs/opus_in_isobmff.html
1939  // The version field shall be set to 0.
1940  const uint8_t kOpusSpecificBoxVersion = 0;
1941  buffer->writer()->AppendInt(kOpusSpecificBoxVersion);
1942  buffer->writer()->AppendArray(
1943  &opus_identification_header[kOpusMagicSignatureSize + 1],
1944  opus_identification_header.size() - kOpusMagicSignatureSize - 1);
1945  }
1946  return true;
1947 }
1948 
1949 size_t OpusSpecific::ComputeSizeInternal() {
1950  // This box is optional. Skip it if not initialized.
1951  if (opus_identification_header.empty())
1952  return 0;
1953  // https://tools.ietf.org/html/draft-ietf-codec-oggopus-06#section-5
1954  // The first 8 bytes is "magic signature".
1955  const size_t kOpusMagicSignatureSize = 8u;
1956  DCHECK_GT(opus_identification_header.size(), kOpusMagicSignatureSize);
1957  return HeaderSize() + opus_identification_header.size() -
1958  kOpusMagicSignatureSize;
1959 }
1960 
1961 IAMFSpecific::IAMFSpecific() = default;
1962 IAMFSpecific::~IAMFSpecific() = default;
1963 
1964 FourCC IAMFSpecific::BoxType() const {
1965  return FOURCC_iacb;
1966 }
1967 
1968 bool IAMFSpecific::ReadWriteInternal(BoxBuffer* buffer) {
1969  RCHECK(ReadWriteHeaderInternal(buffer));
1970  size_t size = buffer->Reading() ? buffer->BytesLeft() : data.size();
1971  RCHECK(buffer->ReadWriteVector(&data, size));
1972  return true;
1973 }
1974 
1975 size_t IAMFSpecific::ComputeSizeInternal() {
1976  // This box is optional. Skip it if not initialized.
1977  if (data.empty())
1978  return 0;
1979  return HeaderSize() + data.size();
1980 }
1981 
1982 FlacSpecific::FlacSpecific() = default;
1983 FlacSpecific::~FlacSpecific() = default;
1984 
1985 FourCC FlacSpecific::BoxType() const {
1986  return FOURCC_dfLa;
1987 }
1988 
1989 bool FlacSpecific::ReadWriteInternal(BoxBuffer* buffer) {
1990  RCHECK(ReadWriteHeaderInternal(buffer));
1991  size_t size = buffer->Reading() ? buffer->BytesLeft() : data.size();
1992  RCHECK(buffer->ReadWriteVector(&data, size));
1993  return true;
1994 }
1995 
1996 size_t FlacSpecific::ComputeSizeInternal() {
1997  // This box is optional. Skip it if not initialized.
1998  if (data.empty())
1999  return 0;
2000  return HeaderSize() + data.size();
2001 }
2002 
2003 ALACSpecific::ALACSpecific() = default;
2004 ALACSpecific::~ALACSpecific() = default;
2005 
2006 FourCC ALACSpecific::BoxType() const {
2007  return FOURCC_alac;
2008 }
2009 
2010 bool ALACSpecific::ReadWriteInternal(BoxBuffer* buffer) {
2011  RCHECK(ReadWriteHeaderInternal(buffer));
2012  size_t size = buffer->Reading() ? buffer->BytesLeft() : data.size();
2013  RCHECK(buffer->ReadWriteVector(&data, size));
2014  return true;
2015 }
2016 
2017 size_t ALACSpecific::ComputeSizeInternal() {
2018  // This box is optional. Skip it if not initialized.
2019  if (data.empty())
2020  return 0;
2021  return HeaderSize() + data.size();
2022 }
2023 
2024 AudioSampleEntry::AudioSampleEntry() = default;
2025 AudioSampleEntry::~AudioSampleEntry() = default;
2026 
2028  if (format == FOURCC_NULL) {
2029  LOG(ERROR) << "AudioSampleEntry should be parsed according to the "
2030  << "handler type recovered in its Media ancestor.";
2031  }
2032  return format;
2033 }
2034 
2035 bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
2036  if (buffer->Reading()) {
2037  DCHECK(buffer->reader());
2038  format = buffer->reader()->type();
2039  } else {
2040  RCHECK(ReadWriteHeaderInternal(buffer));
2041  }
2042 
2043  // Convert from integer to 16.16 fixed point for writing.
2044  samplerate <<= 16;
2045  RCHECK(buffer->IgnoreBytes(6) && // reserved.
2046  buffer->ReadWriteUInt16(&data_reference_index) &&
2047  buffer->IgnoreBytes(8) && // reserved.
2048  buffer->ReadWriteUInt16(&channelcount) &&
2049  buffer->ReadWriteUInt16(&samplesize) &&
2050  buffer->IgnoreBytes(4) && // predefined.
2051  buffer->ReadWriteUInt32(&samplerate));
2052  // Convert from 16.16 fixed point to integer.
2053  samplerate >>= 16;
2054 
2055  RCHECK(buffer->PrepareChildren());
2056 
2057  RCHECK(buffer->TryReadWriteChild(&esds));
2058  RCHECK(buffer->TryReadWriteChild(&ddts));
2059  RCHECK(buffer->TryReadWriteChild(&udts));
2060  RCHECK(buffer->TryReadWriteChild(&dac3));
2061  RCHECK(buffer->TryReadWriteChild(&dec3));
2062  RCHECK(buffer->TryReadWriteChild(&dac4));
2063  RCHECK(buffer->TryReadWriteChild(&dops));
2064  RCHECK(buffer->TryReadWriteChild(&iacb));
2065  RCHECK(buffer->TryReadWriteChild(&dfla));
2066  RCHECK(buffer->TryReadWriteChild(&mhac));
2067  RCHECK(buffer->TryReadWriteChild(&alac));
2068 
2069  // Somehow Edge does not support having sinf box before codec_configuration,
2070  // box, so just do it in the end of AudioSampleEntry. See
2071  // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12658991/
2072  if (format == FOURCC_enca) {
2073  if (buffer->Reading()) {
2074  // Continue scanning until a supported protection scheme is found, or
2075  // until we run out of protection schemes.
2076  while (!IsProtectionSchemeSupported(sinf.type.type))
2077  RCHECK(buffer->ReadWriteChild(&sinf));
2078  } else {
2079  DCHECK(IsProtectionSchemeSupported(sinf.type.type));
2080  RCHECK(buffer->ReadWriteChild(&sinf));
2081  }
2082  }
2083  return true;
2084 }
2085 
2086 size_t AudioSampleEntry::ComputeSizeInternal() {
2087  if (GetActualFormat() == FOURCC_NULL)
2088  return 0;
2089  return HeaderSize() + sizeof(data_reference_index) + sizeof(channelcount) +
2090  sizeof(samplesize) + sizeof(samplerate) + sinf.ComputeSize() +
2091  esds.ComputeSize() + ddts.ComputeSize() + dac3.ComputeSize() +
2092  dec3.ComputeSize() + dops.ComputeSize() + dfla.ComputeSize() +
2093  dac4.ComputeSize() + mhac.ComputeSize() + udts.ComputeSize() +
2094  alac.ComputeSize() + iacb.ComputeSize() +
2095  // Reserved and predefined bytes.
2096  6 + 8 + // 6 + 8 bytes reserved.
2097  4; // 4 bytes predefined.
2098 }
2099 
2100 WebVTTConfigurationBox::WebVTTConfigurationBox() = default;
2101 WebVTTConfigurationBox::~WebVTTConfigurationBox() = default;
2102 
2104  return FOURCC_vttC;
2105 }
2106 
2107 bool WebVTTConfigurationBox::ReadWriteInternal(BoxBuffer* buffer) {
2108  RCHECK(ReadWriteHeaderInternal(buffer));
2109  return buffer->ReadWriteString(
2110  &config, buffer->Reading() ? buffer->BytesLeft() : config.size());
2111 }
2112 
2113 size_t WebVTTConfigurationBox::ComputeSizeInternal() {
2114  return HeaderSize() + config.size();
2115 }
2116 
2117 WebVTTSourceLabelBox::WebVTTSourceLabelBox() = default;
2118 WebVTTSourceLabelBox::~WebVTTSourceLabelBox() = default;
2119 
2121  return FOURCC_vlab;
2122 }
2123 
2124 bool WebVTTSourceLabelBox::ReadWriteInternal(BoxBuffer* buffer) {
2125  RCHECK(ReadWriteHeaderInternal(buffer));
2126  return buffer->ReadWriteString(&source_label, buffer->Reading()
2127  ? buffer->BytesLeft()
2128  : source_label.size());
2129 }
2130 
2131 size_t WebVTTSourceLabelBox::ComputeSizeInternal() {
2132  if (source_label.empty())
2133  return 0;
2134  return HeaderSize() + source_label.size();
2135 }
2136 
2137 TextSampleEntry::TextSampleEntry() = default;
2138 TextSampleEntry::~TextSampleEntry() = default;
2139 
2141  if (format == FOURCC_NULL) {
2142  LOG(ERROR) << "TextSampleEntry should be parsed according to the "
2143  << "handler type recovered in its Media ancestor.";
2144  }
2145  return format;
2146 }
2147 
2148 bool TextSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
2149  if (buffer->Reading()) {
2150  DCHECK(buffer->reader());
2151  format = buffer->reader()->type();
2152  } else {
2153  RCHECK(ReadWriteHeaderInternal(buffer));
2154  }
2155  RCHECK(buffer->IgnoreBytes(6) && // reserved for SampleEntry.
2156  buffer->ReadWriteUInt16(&data_reference_index));
2157 
2158  if (format == FOURCC_wvtt) {
2159  // TODO(rkuroiwa): Handle the optional MPEG4BitRateBox.
2160  RCHECK(buffer->PrepareChildren() && buffer->ReadWriteChild(&config) &&
2161  buffer->ReadWriteChild(&label));
2162  } else if (format == FOURCC_stpp) {
2163  // These are marked as "optional"; but they should still have the
2164  // null-terminator, so this should still work.
2165  RCHECK(buffer->ReadWriteCString(&namespace_) &&
2166  buffer->ReadWriteCString(&schema_location));
2167  }
2168  return true;
2169 }
2170 
2171 size_t TextSampleEntry::ComputeSizeInternal() {
2172  // 6 for the (anonymous) reserved bytes for SampleEntry class.
2173  size_t ret = HeaderSize() + 6 + sizeof(data_reference_index);
2174  if (format == FOURCC_wvtt) {
2175  ret += config.ComputeSize() + label.ComputeSize();
2176  } else if (format == FOURCC_stpp) {
2177  // +2 for the two null terminators for these strings.
2178  ret += namespace_.size() + schema_location.size() + 2;
2179  }
2180  return ret;
2181 }
2182 
2183 MediaHeader::MediaHeader() = default;
2184 MediaHeader::~MediaHeader() = default;
2185 
2186 FourCC MediaHeader::BoxType() const {
2187  return FOURCC_mdhd;
2188 }
2189 
2190 bool MediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
2191  RCHECK(ReadWriteHeaderInternal(buffer));
2192 
2193  uint8_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
2194  RCHECK(buffer->ReadWriteUInt64NBytes(&creation_time, num_bytes) &&
2195  buffer->ReadWriteUInt64NBytes(&modification_time, num_bytes) &&
2196  buffer->ReadWriteUInt32(&timescale) &&
2197  buffer->ReadWriteUInt64NBytes(&duration, num_bytes) &&
2198  language.ReadWrite(buffer) &&
2199  // predefined.
2200  buffer->IgnoreBytes(2));
2201  return true;
2202 }
2203 
2204 size_t MediaHeader::ComputeSizeInternal() {
2205  version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
2206  return HeaderSize() + sizeof(timescale) +
2207  sizeof(uint32_t) * (1 + version) * 3 + language.ComputeSize() +
2208  2; // 2 bytes predefined.
2209 }
2210 
2211 VideoMediaHeader::VideoMediaHeader() {
2212  const uint32_t kVideoMediaHeaderFlags = 1;
2213  flags = kVideoMediaHeaderFlags;
2214 }
2215 
2216 VideoMediaHeader::~VideoMediaHeader() = default;
2217 
2219  return FOURCC_vmhd;
2220 }
2221 bool VideoMediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
2222  RCHECK(ReadWriteHeaderInternal(buffer) &&
2223  buffer->ReadWriteUInt16(&graphicsmode) &&
2224  buffer->ReadWriteUInt16(&opcolor_red) &&
2225  buffer->ReadWriteUInt16(&opcolor_green) &&
2226  buffer->ReadWriteUInt16(&opcolor_blue));
2227  return true;
2228 }
2229 
2230 size_t VideoMediaHeader::ComputeSizeInternal() {
2231  return HeaderSize() + sizeof(graphicsmode) + sizeof(opcolor_red) +
2232  sizeof(opcolor_green) + sizeof(opcolor_blue);
2233 }
2234 
2235 SoundMediaHeader::SoundMediaHeader() = default;
2236 SoundMediaHeader::~SoundMediaHeader() = default;
2237 
2239  return FOURCC_smhd;
2240 }
2241 
2242 bool SoundMediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
2243  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt16(&balance) &&
2244  buffer->IgnoreBytes(2)); // reserved.
2245  return true;
2246 }
2247 
2248 size_t SoundMediaHeader::ComputeSizeInternal() {
2249  return HeaderSize() + sizeof(balance) + sizeof(uint16_t);
2250 }
2251 
2252 NullMediaHeader::NullMediaHeader() = default;
2253 NullMediaHeader::~NullMediaHeader() = default;
2254 
2256  return FOURCC_nmhd;
2257 }
2258 
2259 bool NullMediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
2260  return ReadWriteHeaderInternal(buffer);
2261 }
2262 
2263 size_t NullMediaHeader::ComputeSizeInternal() {
2264  return HeaderSize();
2265 }
2266 
2267 SubtitleMediaHeader::SubtitleMediaHeader() = default;
2268 SubtitleMediaHeader::~SubtitleMediaHeader() = default;
2269 
2271  return FOURCC_sthd;
2272 }
2273 
2274 bool SubtitleMediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
2275  return ReadWriteHeaderInternal(buffer);
2276 }
2277 
2278 size_t SubtitleMediaHeader::ComputeSizeInternal() {
2279  return HeaderSize();
2280 }
2281 
2282 DataEntryUrl::DataEntryUrl() {
2283  const uint32_t kDataEntryUrlFlags = 1;
2284  flags = kDataEntryUrlFlags;
2285 }
2286 
2287 DataEntryUrl::~DataEntryUrl() = default;
2288 
2289 FourCC DataEntryUrl::BoxType() const {
2290  return FOURCC_url;
2291 }
2292 bool DataEntryUrl::ReadWriteInternal(BoxBuffer* buffer) {
2293  RCHECK(ReadWriteHeaderInternal(buffer));
2294  if (buffer->Reading()) {
2295  RCHECK(buffer->ReadWriteVector(&location, buffer->BytesLeft()));
2296  } else {
2297  RCHECK(buffer->ReadWriteVector(&location, location.size()));
2298  }
2299  return true;
2300 }
2301 
2302 size_t DataEntryUrl::ComputeSizeInternal() {
2303  return HeaderSize() + location.size();
2304 }
2305 
2306 DataReference::DataReference() = default;
2307 DataReference::~DataReference() = default;
2308 
2309 FourCC DataReference::BoxType() const {
2310  return FOURCC_dref;
2311 }
2312 bool DataReference::ReadWriteInternal(BoxBuffer* buffer) {
2313  uint32_t entry_count = static_cast<uint32_t>(data_entry.size());
2314  RCHECK(ReadWriteHeaderInternal(buffer) &&
2315  buffer->ReadWriteUInt32(&entry_count));
2316  data_entry.resize(entry_count);
2317  RCHECK(buffer->PrepareChildren());
2318  for (uint32_t i = 0; i < entry_count; ++i)
2319  RCHECK(buffer->ReadWriteChild(&data_entry[i]));
2320  return true;
2321 }
2322 
2323 size_t DataReference::ComputeSizeInternal() {
2324  uint32_t count = static_cast<uint32_t>(data_entry.size());
2325  size_t box_size = HeaderSize() + sizeof(count);
2326  for (uint32_t i = 0; i < count; ++i)
2327  box_size += data_entry[i].ComputeSize();
2328  return box_size;
2329 }
2330 
2331 DataInformation::DataInformation() = default;
2332 DataInformation::~DataInformation() = default;
2333 
2335  return FOURCC_dinf;
2336 }
2337 
2338 bool DataInformation::ReadWriteInternal(BoxBuffer* buffer) {
2339  return ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2340  buffer->ReadWriteChild(&dref);
2341 }
2342 
2343 size_t DataInformation::ComputeSizeInternal() {
2344  return HeaderSize() + dref.ComputeSize();
2345 }
2346 
2347 MediaInformation::MediaInformation() = default;
2348 MediaInformation::~MediaInformation() = default;
2349 
2351  return FOURCC_minf;
2352 }
2353 
2354 bool MediaInformation::ReadWriteInternal(BoxBuffer* buffer) {
2355  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2356  buffer->ReadWriteChild(&dinf) &&
2357  buffer->ReadWriteChild(&sample_table));
2358  switch (sample_table.description.type) {
2359  case kVideo:
2360  RCHECK(buffer->ReadWriteChild(&vmhd));
2361  break;
2362  case kAudio:
2363  RCHECK(buffer->ReadWriteChild(&smhd));
2364  break;
2365  case kText:
2366  RCHECK(buffer->TryReadWriteChild(&nmhd));
2367  break;
2368  case kSubtitle:
2369  RCHECK(buffer->TryReadWriteChild(&sthd));
2370  break;
2371  default:
2372  NOTIMPLEMENTED();
2373  }
2374  // Hint is not supported for now.
2375  return true;
2376 }
2377 
2378 size_t MediaInformation::ComputeSizeInternal() {
2379  size_t box_size =
2380  HeaderSize() + dinf.ComputeSize() + sample_table.ComputeSize();
2381  switch (sample_table.description.type) {
2382  case kVideo:
2383  box_size += vmhd.ComputeSize();
2384  break;
2385  case kAudio:
2386  box_size += smhd.ComputeSize();
2387  break;
2388  case kText:
2389  box_size += nmhd.ComputeSize();
2390  break;
2391  case kSubtitle:
2392  box_size += sthd.ComputeSize();
2393  break;
2394  default:
2395  NOTIMPLEMENTED();
2396  }
2397  return box_size;
2398 }
2399 
2400 Media::Media() = default;
2401 Media::~Media() = default;
2402 
2403 FourCC Media::BoxType() const {
2404  return FOURCC_mdia;
2405 }
2406 
2407 bool Media::ReadWriteInternal(BoxBuffer* buffer) {
2408  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2409  buffer->ReadWriteChild(&header));
2410  if (buffer->Reading()) {
2411  RCHECK(buffer->ReadWriteChild(&handler));
2412  // Maddeningly, the HandlerReference box specifies how to parse the
2413  // SampleDescription box, making the latter the only box (of those that we
2414  // support) which cannot be parsed correctly on its own (or even with
2415  // information from its strict ancestor tree). We thus copy the handler type
2416  // to the sample description box *before* parsing it to provide this
2417  // information while parsing.
2418  information.sample_table.description.type =
2419  FourCCToTrackType(handler.handler_type);
2420  } else {
2421  handler.handler_type =
2422  TrackTypeToFourCC(information.sample_table.description.type);
2423  RCHECK(handler.handler_type != FOURCC_NULL);
2424  RCHECK(buffer->ReadWriteChild(&handler));
2425  }
2426  RCHECK(buffer->ReadWriteChild(&information));
2427  return true;
2428 }
2429 
2430 size_t Media::ComputeSizeInternal() {
2431  handler.handler_type =
2432  TrackTypeToFourCC(information.sample_table.description.type);
2433  return HeaderSize() + header.ComputeSize() + handler.ComputeSize() +
2434  information.ComputeSize();
2435 }
2436 
2437 Track::Track() = default;
2438 Track::~Track() = default;
2439 
2440 FourCC Track::BoxType() const {
2441  return FOURCC_trak;
2442 }
2443 
2444 bool Track::ReadWriteInternal(BoxBuffer* buffer) {
2445  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2446  buffer->ReadWriteChild(&header) && buffer->ReadWriteChild(&media) &&
2447  buffer->TryReadWriteChild(&edit) &&
2448  buffer->TryReadWriteChild(&sample_encryption));
2449  return true;
2450 }
2451 
2452 size_t Track::ComputeSizeInternal() {
2453  return HeaderSize() + header.ComputeSize() + media.ComputeSize() +
2454  edit.ComputeSize();
2455 }
2456 
2457 MovieExtendsHeader::MovieExtendsHeader() = default;
2458 MovieExtendsHeader::~MovieExtendsHeader() = default;
2459 
2461  return FOURCC_mehd;
2462 }
2463 
2464 bool MovieExtendsHeader::ReadWriteInternal(BoxBuffer* buffer) {
2465  RCHECK(ReadWriteHeaderInternal(buffer));
2466  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
2467  RCHECK(buffer->ReadWriteUInt64NBytes(&fragment_duration, num_bytes));
2468  return true;
2469 }
2470 
2471 size_t MovieExtendsHeader::ComputeSizeInternal() {
2472  // This box is optional. Skip it if it is not used.
2473  if (fragment_duration == 0)
2474  return 0;
2475  version = IsFitIn32Bits(fragment_duration) ? 0 : 1;
2476  return HeaderSize() + sizeof(uint32_t) * (1 + version);
2477 }
2478 
2479 TrackExtends::TrackExtends() = default;
2480 TrackExtends::~TrackExtends() = default;
2481 
2482 FourCC TrackExtends::BoxType() const {
2483  return FOURCC_trex;
2484 }
2485 
2486 bool TrackExtends::ReadWriteInternal(BoxBuffer* buffer) {
2487  RCHECK(ReadWriteHeaderInternal(buffer) &&
2488  buffer->ReadWriteUInt32(&track_id) &&
2489  buffer->ReadWriteUInt32(&default_sample_description_index) &&
2490  buffer->ReadWriteUInt32(&default_sample_duration) &&
2491  buffer->ReadWriteUInt32(&default_sample_size) &&
2492  buffer->ReadWriteUInt32(&default_sample_flags));
2493  return true;
2494 }
2495 
2496 size_t TrackExtends::ComputeSizeInternal() {
2497  return HeaderSize() + sizeof(track_id) +
2498  sizeof(default_sample_description_index) +
2499  sizeof(default_sample_duration) + sizeof(default_sample_size) +
2500  sizeof(default_sample_flags);
2501 }
2502 
2503 MovieExtends::MovieExtends() = default;
2504 MovieExtends::~MovieExtends() = default;
2505 
2506 FourCC MovieExtends::BoxType() const {
2507  return FOURCC_mvex;
2508 }
2509 
2510 bool MovieExtends::ReadWriteInternal(BoxBuffer* buffer) {
2511  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2512  buffer->TryReadWriteChild(&header));
2513  if (buffer->Reading()) {
2514  DCHECK(buffer->reader());
2515  RCHECK(buffer->reader()->ReadChildren(&tracks));
2516  } else {
2517  for (uint32_t i = 0; i < tracks.size(); ++i)
2518  RCHECK(buffer->ReadWriteChild(&tracks[i]));
2519  }
2520  return true;
2521 }
2522 
2523 size_t MovieExtends::ComputeSizeInternal() {
2524  // This box is optional. Skip it if it does not contain any track.
2525  if (tracks.size() == 0)
2526  return 0;
2527  size_t box_size = HeaderSize() + header.ComputeSize();
2528  for (uint32_t i = 0; i < tracks.size(); ++i)
2529  box_size += tracks[i].ComputeSize();
2530  return box_size;
2531 }
2532 
2533 Movie::Movie() = default;
2534 Movie::~Movie() = default;
2535 
2536 FourCC Movie::BoxType() const {
2537  return FOURCC_moov;
2538 }
2539 
2540 bool Movie::ReadWriteInternal(BoxBuffer* buffer) {
2541  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2542  buffer->ReadWriteChild(&header));
2543  if (buffer->Reading()) {
2544  BoxReader* reader = buffer->reader();
2545  DCHECK(reader);
2546  RCHECK(reader->ReadChildren(&tracks) && reader->TryReadChild(&extends) &&
2547  reader->TryReadChildren(&pssh));
2548  } else {
2549  // The 'meta' box is not well formed in the video captured by Android's
2550  // default camera app: spec indicates that it is a FullBox but it is written
2551  // as a Box. This results in the box failed to be parsed. See
2552  // https://github.com/shaka-project/shaka-packager/issues/319 for details.
2553  // We do not care the content of metadata box in the source content, so just
2554  // skip reading the box.
2555  RCHECK(buffer->TryReadWriteChild(&metadata));
2556  if (absl::GetFlag(FLAGS_mvex_before_trak)) {
2557  // |extends| has to be written before |tracks| to workaround Android
2558  // MediaExtractor bug which requires |mvex| to be placed before |trak|.
2559  // See https://github.com/shaka-project/shaka-packager/issues/711 for
2560  // details.
2561  RCHECK(buffer->TryReadWriteChild(&extends));
2562  }
2563  for (uint32_t i = 0; i < tracks.size(); ++i)
2564  RCHECK(buffer->ReadWriteChild(&tracks[i]));
2565  if (!absl::GetFlag(FLAGS_mvex_before_trak)) {
2566  RCHECK(buffer->TryReadWriteChild(&extends));
2567  }
2568  for (uint32_t i = 0; i < pssh.size(); ++i)
2569  RCHECK(buffer->ReadWriteChild(&pssh[i]));
2570  }
2571  return true;
2572 }
2573 
2574 size_t Movie::ComputeSizeInternal() {
2575  size_t box_size = HeaderSize() + header.ComputeSize() +
2576  metadata.ComputeSize() + extends.ComputeSize();
2577  for (uint32_t i = 0; i < tracks.size(); ++i)
2578  box_size += tracks[i].ComputeSize();
2579  for (uint32_t i = 0; i < pssh.size(); ++i)
2580  box_size += pssh[i].ComputeSize();
2581  return box_size;
2582 }
2583 
2584 TrackFragmentDecodeTime::TrackFragmentDecodeTime() = default;
2585 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() = default;
2586 
2588  return FOURCC_tfdt;
2589 }
2590 
2591 bool TrackFragmentDecodeTime::ReadWriteInternal(BoxBuffer* buffer) {
2592  RCHECK(ReadWriteHeaderInternal(buffer));
2593  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
2594  RCHECK(buffer->ReadWriteUInt64NBytes(&decode_time, num_bytes));
2595  return true;
2596 }
2597 
2598 size_t TrackFragmentDecodeTime::ComputeSizeInternal() {
2599  version = IsFitIn32Bits(decode_time) ? 0 : 1;
2600  return HeaderSize() + sizeof(uint32_t) * (1 + version);
2601 }
2602 
2603 MovieFragmentHeader::MovieFragmentHeader() = default;
2604 MovieFragmentHeader::~MovieFragmentHeader() = default;
2605 
2607  return FOURCC_mfhd;
2608 }
2609 
2610 bool MovieFragmentHeader::ReadWriteInternal(BoxBuffer* buffer) {
2611  return ReadWriteHeaderInternal(buffer) &&
2612  buffer->ReadWriteUInt32(&sequence_number);
2613 }
2614 
2615 size_t MovieFragmentHeader::ComputeSizeInternal() {
2616  return HeaderSize() + sizeof(sequence_number);
2617 }
2618 
2619 TrackFragmentHeader::TrackFragmentHeader() = default;
2620 TrackFragmentHeader::~TrackFragmentHeader() = default;
2621 
2623  return FOURCC_tfhd;
2624 }
2625 
2626 bool TrackFragmentHeader::ReadWriteInternal(BoxBuffer* buffer) {
2627  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&track_id));
2628 
2629  if (flags & kBaseDataOffsetPresentMask) {
2630  // MSE requires 'default-base-is-moof' to be set and
2631  // 'base-data-offset-present' not to be set. We omit these checks as some
2632  // valid files in the wild don't follow these rules, though they use moof as
2633  // base.
2634  uint64_t base_data_offset;
2635  RCHECK(buffer->ReadWriteUInt64(&base_data_offset));
2636  DLOG(WARNING) << "base-data-offset-present is not expected. Assumes "
2637  "default-base-is-moof.";
2638  }
2639 
2640  if (flags & kSampleDescriptionIndexPresentMask) {
2641  RCHECK(buffer->ReadWriteUInt32(&sample_description_index));
2642  } else if (buffer->Reading()) {
2643  sample_description_index = 0;
2644  }
2645 
2646  if (flags & kDefaultSampleDurationPresentMask) {
2647  RCHECK(buffer->ReadWriteUInt32(&default_sample_duration));
2648  } else if (buffer->Reading()) {
2649  default_sample_duration = 0;
2650  }
2651 
2652  if (flags & kDefaultSampleSizePresentMask) {
2653  RCHECK(buffer->ReadWriteUInt32(&default_sample_size));
2654  } else if (buffer->Reading()) {
2655  default_sample_size = 0;
2656  }
2657 
2658  if (flags & kDefaultSampleFlagsPresentMask)
2659  RCHECK(buffer->ReadWriteUInt32(&default_sample_flags));
2660  return true;
2661 }
2662 
2663 size_t TrackFragmentHeader::ComputeSizeInternal() {
2664  size_t box_size = HeaderSize() + sizeof(track_id);
2665  if (flags & kSampleDescriptionIndexPresentMask)
2666  box_size += sizeof(sample_description_index);
2667  if (flags & kDefaultSampleDurationPresentMask)
2668  box_size += sizeof(default_sample_duration);
2669  if (flags & kDefaultSampleSizePresentMask)
2670  box_size += sizeof(default_sample_size);
2671  if (flags & kDefaultSampleFlagsPresentMask)
2672  box_size += sizeof(default_sample_flags);
2673  return box_size;
2674 }
2675 
2676 TrackFragmentRun::TrackFragmentRun() = default;
2677 TrackFragmentRun::~TrackFragmentRun() = default;
2678 
2680  return FOURCC_trun;
2681 }
2682 
2683 bool TrackFragmentRun::ReadWriteInternal(BoxBuffer* buffer) {
2684  if (!buffer->Reading()) {
2685  // Determine whether version 0 or version 1 should be used.
2686  // Use version 0 if possible, use version 1 if there is a negative
2687  // sample_offset value.
2688  version = 0;
2689  if (flags & kSampleCompTimeOffsetsPresentMask) {
2690  for (uint32_t i = 0; i < sample_count; ++i) {
2691  if (sample_composition_time_offsets[i] < 0) {
2692  version = 1;
2693  break;
2694  }
2695  }
2696  }
2697  }
2698 
2699  RCHECK(ReadWriteHeaderInternal(buffer) &&
2700  buffer->ReadWriteUInt32(&sample_count));
2701 
2702  bool data_offset_present = (flags & kDataOffsetPresentMask) != 0;
2703  bool first_sample_flags_present = (flags & kFirstSampleFlagsPresentMask) != 0;
2704  bool sample_duration_present = (flags & kSampleDurationPresentMask) != 0;
2705  bool sample_size_present = (flags & kSampleSizePresentMask) != 0;
2706  bool sample_flags_present = (flags & kSampleFlagsPresentMask) != 0;
2707  bool sample_composition_time_offsets_present =
2708  (flags & kSampleCompTimeOffsetsPresentMask) != 0;
2709 
2710  if (data_offset_present) {
2711  RCHECK(buffer->ReadWriteUInt32(&data_offset));
2712  } else {
2713  // NOTE: If the data-offset is not present, then the data for this run
2714  // starts immediately after the data of the previous run, or at the
2715  // base-data-offset defined by the track fragment header if this is the
2716  // first run in a track fragment. If the data-offset is present, it is
2717  // relative to the base-data-offset established in the track fragment
2718  // header.
2719  NOTIMPLEMENTED();
2720  }
2721 
2722  uint32_t first_sample_flags(0);
2723 
2724  if (buffer->Reading()) {
2725  if (first_sample_flags_present)
2726  RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
2727 
2728  if (sample_duration_present)
2729  sample_durations.resize(sample_count);
2730  if (sample_size_present)
2731  sample_sizes.resize(sample_count);
2732  if (sample_flags_present)
2733  sample_flags.resize(sample_count);
2734  if (sample_composition_time_offsets_present)
2735  sample_composition_time_offsets.resize(sample_count);
2736  } else {
2737  if (first_sample_flags_present) {
2738  first_sample_flags = sample_flags[0];
2739  DCHECK(sample_flags.size() == 1);
2740  RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
2741  }
2742 
2743  if (sample_duration_present)
2744  DCHECK(sample_durations.size() == sample_count);
2745  if (sample_size_present)
2746  DCHECK(sample_sizes.size() == sample_count);
2747  if (sample_flags_present)
2748  DCHECK(sample_flags.size() == sample_count);
2749  if (sample_composition_time_offsets_present)
2750  DCHECK(sample_composition_time_offsets.size() == sample_count);
2751  }
2752 
2753  for (uint32_t i = 0; i < sample_count; ++i) {
2754  if (sample_duration_present)
2755  RCHECK(buffer->ReadWriteUInt32(&sample_durations[i]));
2756  if (sample_size_present)
2757  RCHECK(buffer->ReadWriteUInt32(&sample_sizes[i]));
2758  if (sample_flags_present)
2759  RCHECK(buffer->ReadWriteUInt32(&sample_flags[i]));
2760 
2761  if (sample_composition_time_offsets_present) {
2762  if (version == 0) {
2763  uint32_t sample_offset = sample_composition_time_offsets[i];
2764  RCHECK(buffer->ReadWriteUInt32(&sample_offset));
2765  sample_composition_time_offsets[i] = sample_offset;
2766  } else {
2767  int32_t sample_offset = sample_composition_time_offsets[i];
2768  RCHECK(buffer->ReadWriteInt32(&sample_offset));
2769  sample_composition_time_offsets[i] = sample_offset;
2770  }
2771  }
2772  }
2773 
2774  if (buffer->Reading()) {
2775  if (first_sample_flags_present) {
2776  if (sample_flags.size() == 0) {
2777  sample_flags.push_back(first_sample_flags);
2778  } else {
2779  sample_flags[0] = first_sample_flags;
2780  }
2781  }
2782  }
2783  return true;
2784 }
2785 
2786 size_t TrackFragmentRun::ComputeSizeInternal() {
2787  size_t box_size = HeaderSize() + sizeof(sample_count);
2788  if (flags & kDataOffsetPresentMask)
2789  box_size += sizeof(data_offset);
2790  if (flags & kFirstSampleFlagsPresentMask)
2791  box_size += sizeof(uint32_t);
2792  uint32_t fields = (flags & kSampleDurationPresentMask ? 1 : 0) +
2793  (flags & kSampleSizePresentMask ? 1 : 0) +
2794  (flags & kSampleFlagsPresentMask ? 1 : 0) +
2795  (flags & kSampleCompTimeOffsetsPresentMask ? 1 : 0);
2796  box_size += fields * sizeof(uint32_t) * sample_count;
2797  return box_size;
2798 }
2799 
2800 TrackFragment::TrackFragment() = default;
2801 TrackFragment::~TrackFragment() = default;
2802 
2803 FourCC TrackFragment::BoxType() const {
2804  return FOURCC_traf;
2805 }
2806 
2807 bool TrackFragment::ReadWriteInternal(BoxBuffer* buffer) {
2808  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2809  buffer->ReadWriteChild(&header));
2810  if (buffer->Reading()) {
2811  DCHECK(buffer->reader());
2812  decode_time_absent = !buffer->reader()->ChildExist(&decode_time);
2813  if (!decode_time_absent)
2814  RCHECK(buffer->ReadWriteChild(&decode_time));
2815  RCHECK(buffer->reader()->TryReadChildren(&runs) &&
2816  buffer->reader()->TryReadChildren(&sample_group_descriptions) &&
2817  buffer->reader()->TryReadChildren(&sample_to_groups));
2818  } else {
2819  if (!decode_time_absent)
2820  RCHECK(buffer->ReadWriteChild(&decode_time));
2821  for (uint32_t i = 0; i < runs.size(); ++i)
2822  RCHECK(buffer->ReadWriteChild(&runs[i]));
2823  for (uint32_t i = 0; i < sample_to_groups.size(); ++i)
2824  RCHECK(buffer->ReadWriteChild(&sample_to_groups[i]));
2825  for (uint32_t i = 0; i < sample_group_descriptions.size(); ++i)
2826  RCHECK(buffer->ReadWriteChild(&sample_group_descriptions[i]));
2827  }
2828  return buffer->TryReadWriteChild(&auxiliary_size) &&
2829  buffer->TryReadWriteChild(&auxiliary_offset) &&
2830  buffer->TryReadWriteChild(&sample_encryption);
2831 }
2832 
2833 size_t TrackFragment::ComputeSizeInternal() {
2834  size_t box_size = HeaderSize() + header.ComputeSize() +
2835  decode_time.ComputeSize() + auxiliary_size.ComputeSize() +
2836  auxiliary_offset.ComputeSize() +
2837  sample_encryption.ComputeSize();
2838  for (uint32_t i = 0; i < runs.size(); ++i)
2839  box_size += runs[i].ComputeSize();
2840  for (uint32_t i = 0; i < sample_group_descriptions.size(); ++i)
2841  box_size += sample_group_descriptions[i].ComputeSize();
2842  for (uint32_t i = 0; i < sample_to_groups.size(); ++i)
2843  box_size += sample_to_groups[i].ComputeSize();
2844  return box_size;
2845 }
2846 
2847 MovieFragment::MovieFragment() = default;
2848 MovieFragment::~MovieFragment() = default;
2849 
2850 FourCC MovieFragment::BoxType() const {
2851  return FOURCC_moof;
2852 }
2853 
2854 bool MovieFragment::ReadWriteInternal(BoxBuffer* buffer) {
2855  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
2856  buffer->ReadWriteChild(&header));
2857  if (buffer->Reading()) {
2858  BoxReader* reader = buffer->reader();
2859  DCHECK(reader);
2860  RCHECK(reader->ReadChildren(&tracks) && reader->TryReadChildren(&pssh));
2861  } else {
2862  for (uint32_t i = 0; i < tracks.size(); ++i)
2863  RCHECK(buffer->ReadWriteChild(&tracks[i]));
2864  for (uint32_t i = 0; i < pssh.size(); ++i)
2865  RCHECK(buffer->ReadWriteChild(&pssh[i]));
2866  }
2867  return true;
2868 }
2869 
2870 size_t MovieFragment::ComputeSizeInternal() {
2871  size_t box_size = HeaderSize() + header.ComputeSize();
2872  for (uint32_t i = 0; i < tracks.size(); ++i)
2873  box_size += tracks[i].ComputeSize();
2874  for (uint32_t i = 0; i < pssh.size(); ++i)
2875  box_size += pssh[i].ComputeSize();
2876  return box_size;
2877 }
2878 
2879 SegmentIndex::SegmentIndex() = default;
2880 SegmentIndex::~SegmentIndex() = default;
2881 
2882 FourCC SegmentIndex::BoxType() const {
2883  return FOURCC_sidx;
2884 }
2885 
2886 bool SegmentIndex::ReadWriteInternal(BoxBuffer* buffer) {
2887  RCHECK(ReadWriteHeaderInternal(buffer) &&
2888  buffer->ReadWriteUInt32(&reference_id) &&
2889  buffer->ReadWriteUInt32(&timescale));
2890 
2891  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
2892  RCHECK(
2893  buffer->ReadWriteUInt64NBytes(&earliest_presentation_time, num_bytes) &&
2894  buffer->ReadWriteUInt64NBytes(&first_offset, num_bytes));
2895 
2896  uint16_t reference_count;
2897  if (references.size() <= std::numeric_limits<uint16_t>::max()) {
2898  reference_count = static_cast<uint16_t>(references.size());
2899  } else {
2900  reference_count = std::numeric_limits<uint16_t>::max();
2901  LOG(WARNING) << "Seeing " << references.size()
2902  << " subsegment references, but at most " << reference_count
2903  << " references can be stored in 'sidx' box."
2904  << " The extra references are truncated.";
2905  LOG(WARNING) << "The stream will not play to the end in DASH.";
2906  LOG(WARNING) << "A possible workaround is to increase segment duration.";
2907  }
2908  RCHECK(buffer->IgnoreBytes(2) && // reserved.
2909  buffer->ReadWriteUInt16(&reference_count));
2910  if (buffer->Reading())
2911  references.resize(reference_count);
2912 
2913  uint32_t reference_type_size;
2914  uint32_t sap;
2915  for (uint32_t i = 0; i < reference_count; ++i) {
2916  if (!buffer->Reading()) {
2917  reference_type_size = references[i].referenced_size;
2918  if (references[i].reference_type)
2919  reference_type_size |= (1 << 31);
2920  sap = (references[i].sap_type << 28) | references[i].sap_delta_time;
2921  if (references[i].starts_with_sap)
2922  sap |= (1 << 31);
2923  }
2924  RCHECK(buffer->ReadWriteUInt32(&reference_type_size) &&
2925  buffer->ReadWriteUInt32(&references[i].subsegment_duration) &&
2926  buffer->ReadWriteUInt32(&sap));
2927  if (buffer->Reading()) {
2928  references[i].reference_type = (reference_type_size >> 31) ? true : false;
2929  references[i].referenced_size = reference_type_size & ~(1 << 31);
2930  references[i].starts_with_sap = (sap >> 31) ? true : false;
2931  references[i].sap_type =
2932  static_cast<SegmentReference::SAPType>((sap >> 28) & 0x07);
2933  references[i].sap_delta_time = sap & ~(0xF << 28);
2934  }
2935  }
2936  return true;
2937 }
2938 
2939 size_t SegmentIndex::ComputeSizeInternal() {
2940  version = IsFitIn32Bits(earliest_presentation_time, first_offset) ? 0 : 1;
2941  return HeaderSize() + sizeof(reference_id) + sizeof(timescale) +
2942  sizeof(uint32_t) * (1 + version) * 2 + 2 * sizeof(uint16_t) +
2943  3 * sizeof(uint32_t) *
2944  std::min(
2945  references.size(),
2946  static_cast<size_t>(std::numeric_limits<uint16_t>::max()));
2947 }
2948 
2949 MediaData::MediaData() = default;
2950 MediaData::~MediaData() = default;
2951 
2952 FourCC MediaData::BoxType() const {
2953  return FOURCC_mdat;
2954 }
2955 
2956 bool MediaData::ReadWriteInternal(BoxBuffer* buffer) {
2957  NOTIMPLEMENTED() << "Actual data is parsed and written separately.";
2958  return false;
2959 }
2960 
2961 size_t MediaData::ComputeSizeInternal() {
2962  return HeaderSize() + data_size;
2963 }
2964 
2965 CueSourceIDBox::CueSourceIDBox() = default;
2966 CueSourceIDBox::~CueSourceIDBox() = default;
2967 
2968 FourCC CueSourceIDBox::BoxType() const {
2969  return FOURCC_vsid;
2970 }
2971 
2972 bool CueSourceIDBox::ReadWriteInternal(BoxBuffer* buffer) {
2973  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteInt32(&source_id));
2974  return true;
2975 }
2976 
2977 size_t CueSourceIDBox::ComputeSizeInternal() {
2978  if (source_id == kCueSourceIdNotSet)
2979  return 0;
2980  return HeaderSize() + sizeof(source_id);
2981 }
2982 
2983 CueTimeBox::CueTimeBox() = default;
2984 CueTimeBox::~CueTimeBox() = default;
2985 
2986 FourCC CueTimeBox::BoxType() const {
2987  return FOURCC_ctim;
2988 }
2989 
2990 bool CueTimeBox::ReadWriteInternal(BoxBuffer* buffer) {
2991  RCHECK(ReadWriteHeaderInternal(buffer));
2992  return buffer->ReadWriteString(
2993  &cue_current_time,
2994  buffer->Reading() ? buffer->BytesLeft() : cue_current_time.size());
2995 }
2996 
2997 size_t CueTimeBox::ComputeSizeInternal() {
2998  if (cue_current_time.empty())
2999  return 0;
3000  return HeaderSize() + cue_current_time.size();
3001 }
3002 
3003 CueIDBox::CueIDBox() = default;
3004 CueIDBox::~CueIDBox() = default;
3005 
3006 FourCC CueIDBox::BoxType() const {
3007  return FOURCC_iden;
3008 }
3009 
3010 bool CueIDBox::ReadWriteInternal(BoxBuffer* buffer) {
3011  RCHECK(ReadWriteHeaderInternal(buffer));
3012  return buffer->ReadWriteString(
3013  &cue_id, buffer->Reading() ? buffer->BytesLeft() : cue_id.size());
3014 }
3015 
3016 size_t CueIDBox::ComputeSizeInternal() {
3017  if (cue_id.empty())
3018  return 0;
3019  return HeaderSize() + cue_id.size();
3020 }
3021 
3022 CueSettingsBox::CueSettingsBox() = default;
3023 CueSettingsBox::~CueSettingsBox() = default;
3024 
3025 FourCC CueSettingsBox::BoxType() const {
3026  return FOURCC_sttg;
3027 }
3028 
3029 bool CueSettingsBox::ReadWriteInternal(BoxBuffer* buffer) {
3030  RCHECK(ReadWriteHeaderInternal(buffer));
3031  return buffer->ReadWriteString(
3032  &settings, buffer->Reading() ? buffer->BytesLeft() : settings.size());
3033 }
3034 
3035 size_t CueSettingsBox::ComputeSizeInternal() {
3036  if (settings.empty())
3037  return 0;
3038  return HeaderSize() + settings.size();
3039 }
3040 
3041 CuePayloadBox::CuePayloadBox() = default;
3042 CuePayloadBox::~CuePayloadBox() = default;
3043 
3044 FourCC CuePayloadBox::BoxType() const {
3045  return FOURCC_payl;
3046 }
3047 
3048 bool CuePayloadBox::ReadWriteInternal(BoxBuffer* buffer) {
3049  RCHECK(ReadWriteHeaderInternal(buffer));
3050  return buffer->ReadWriteString(
3051  &cue_text, buffer->Reading() ? buffer->BytesLeft() : cue_text.size());
3052 }
3053 
3054 size_t CuePayloadBox::ComputeSizeInternal() {
3055  return HeaderSize() + cue_text.size();
3056 }
3057 
3058 VTTEmptyCueBox::VTTEmptyCueBox() = default;
3059 VTTEmptyCueBox::~VTTEmptyCueBox() = default;
3060 
3061 FourCC VTTEmptyCueBox::BoxType() const {
3062  return FOURCC_vtte;
3063 }
3064 
3065 bool VTTEmptyCueBox::ReadWriteInternal(BoxBuffer* buffer) {
3066  return ReadWriteHeaderInternal(buffer);
3067 }
3068 
3069 size_t VTTEmptyCueBox::ComputeSizeInternal() {
3070  return HeaderSize();
3071 }
3072 
3073 VTTAdditionalTextBox::VTTAdditionalTextBox() = default;
3074 VTTAdditionalTextBox::~VTTAdditionalTextBox() = default;
3075 
3077  return FOURCC_vtta;
3078 }
3079 
3080 bool VTTAdditionalTextBox::ReadWriteInternal(BoxBuffer* buffer) {
3081  RCHECK(ReadWriteHeaderInternal(buffer));
3082  return buffer->ReadWriteString(
3083  &cue_additional_text,
3084  buffer->Reading() ? buffer->BytesLeft() : cue_additional_text.size());
3085 }
3086 
3087 size_t VTTAdditionalTextBox::ComputeSizeInternal() {
3088  return HeaderSize() + cue_additional_text.size();
3089 }
3090 
3091 VTTCueBox::VTTCueBox() = default;
3092 VTTCueBox::~VTTCueBox() = default;
3093 
3094 FourCC VTTCueBox::BoxType() const {
3095  return FOURCC_vttc;
3096 }
3097 
3098 bool VTTCueBox::ReadWriteInternal(BoxBuffer* buffer) {
3099  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
3100  buffer->TryReadWriteChild(&cue_source_id) &&
3101  buffer->TryReadWriteChild(&cue_id) &&
3102  buffer->TryReadWriteChild(&cue_time) &&
3103  buffer->TryReadWriteChild(&cue_settings) &&
3104  buffer->ReadWriteChild(&cue_payload));
3105  return true;
3106 }
3107 
3108 size_t VTTCueBox::ComputeSizeInternal() {
3109  return HeaderSize() + cue_source_id.ComputeSize() + cue_id.ComputeSize() +
3110  cue_time.ComputeSize() + cue_settings.ComputeSize() +
3111  cue_payload.ComputeSize();
3112 }
3113 
3114 } // namespace mp4
3115 } // namespace media
3116 } // namespace shaka
virtual bool Parse(const std::vector< uint8_t > &data)
bool Parse(const std::vector< uint8_t > &data)
void Write(BufferWriter *writer)
BufferWriter * writer()
Definition: box_buffer.h:212
bool IgnoreBytes(size_t num_bytes)
Definition: box_buffer.h:201
bool ReadWriteUInt64NBytes(uint64_t *v, size_t num_bytes)
Definition: box_buffer.h:119
bool TryReadWriteChild(Box *box)
Definition: box_buffer.h:189
size_t BytesLeft() const
Definition: box_buffer.h:64
bool ReadWriteString(std::string *str, size_t size)
Definition: box_buffer.h:141
bool ReadWriteChild(Box *box)
Definition: box_buffer.h:178
Class for reading MP4 boxes.
Definition: box_reader.h:28
bool ReadChildren(std::vector< T > *children)
Definition: box_reader.h:131
bool ChildExist(Box *child)
Definition: box_reader.cc:104
bool ReadChild(Box *child)
Definition: box_reader.cc:92
bool TryReadChild(Box *child)
Definition: box_reader.cc:108
static BoxReader * ReadBox(const uint8_t *buf, const size_t buf_size, bool *err)
Definition: box_reader.cc:38
bool TryReadChildren(std::vector< T > *children)
Definition: box_reader.h:137
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
virtual uint32_t HeaderSize() const
Definition: box.cc:57
void Write(BufferWriter *writer)
Definition: box.cc:27
virtual bool ReadWriteHeaderInternal(BoxBuffer *buffer)
Definition: box.cc:63
uint32_t ComputeSize()
Definition: box.cc:52
uint32_t box_size()
Definition: box.h:55
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
uint32_t HeaderSize() const final
Definition: box.cc:77
bool ReadWriteHeaderInternal(BoxBuffer *buffer) final
Definition: box.cc:82
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
bool ParseFromBuffer(uint8_t iv_size, bool has_subsamples, BufferReader *reader)
bool ReadWrite(uint8_t iv_size, bool has_subsamples, BoxBuffer *buffer)
std::vector< uint8_t > sample_encryption_data
bool ParseFromSampleEncryptionData(uint8_t l_iv_size, std::vector< SampleEncryptionEntry > *l_sample_encryption_entries) const
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override