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
virtual bool Parse(const std::vector< uint8_t > &data)
bool Parse(const std::vector< uint8_t > &data)
void Write(BufferWriter *writer)
BufferWriter * writer()
Definition: box_buffer.h:210
bool IgnoreBytes(size_t num_bytes)
Definition: box_buffer.h:199
bool ReadWriteUInt64NBytes(uint64_t *v, size_t num_bytes)
Definition: box_buffer.h:117
bool TryReadWriteChild(Box *box)
Definition: box_buffer.h:187
size_t BytesLeft() const
Definition: box_buffer.h:62
bool ReadWriteString(std::string *str, size_t size)
Definition: box_buffer.h:139
bool ReadWriteChild(Box *box)
Definition: box_buffer.h:176
Class for reading MP4 boxes.
Definition: box_reader.h:25
bool TryReadChild(Box *child) WARN_UNUSED_RESULT
Definition: box_reader.cc:106
bool TryReadChildren(std::vector< T > *children) WARN_UNUSED_RESULT
Definition: box_reader.h:134
bool ReadChild(Box *child) WARN_UNUSED_RESULT
Definition: box_reader.cc:90
bool ChildExist(Box *child) WARN_UNUSED_RESULT
Definition: box_reader.cc:102
static BoxReader * ReadBox(const uint8_t *buf, const size_t buf_size, bool *err)
Definition: box_reader.cc:36
bool ReadChildren(std::vector< T > *children) WARN_UNUSED_RESULT
Definition: box_reader.h:128
All the methods that are virtual are virtual for mocking.
FourCC BoxType() const override
FourCC BoxType() const override
virtual uint32_t HeaderSize() const
Definition: box.cc:55
void Write(BufferWriter *writer)
Definition: box.cc:25
virtual bool ReadWriteHeaderInternal(BoxBuffer *buffer)
Definition: box.cc:61
uint32_t ComputeSize()
Definition: box.cc:50
uint32_t box_size()
Definition: box.h:55
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
uint32_t HeaderSize() const final
Definition: box.cc:75
bool ReadWriteHeaderInternal(BoxBuffer *buffer) final
Definition: box.cc:80
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
bool ParseFromBuffer(uint8_t iv_size, bool has_subsamples, BufferReader *reader)
bool ReadWrite(uint8_t iv_size, bool has_subsamples, BoxBuffer *buffer)
bool ParseFromSampleEncryptionData(uint8_t iv_size, std::vector< SampleEncryptionEntry > *sample_encryption_entries) const
std::vector< uint8_t > sample_encryption_data
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override
FourCC BoxType() const override