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