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