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