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