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