DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs 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/formats/mp4/box_buffer.h"
12 #include "packager/media/formats/mp4/rcheck.h"
13 
14 namespace {
15 const uint32_t kFourCCSize = 4;
16 
17 // Key Id size as defined in CENC spec.
18 const uint32_t kCencKeyIdSize = 16;
19 
20 // 9 uint32_t in big endian formatted array.
21 const uint8_t kUnityMatrix[] = {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22  0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
23  0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0};
24 
25 // Default entries for HandlerReference box.
26 const char kVideoHandlerName[] = "VideoHandler";
27 const char kAudioHandlerName[] = "SoundHandler";
28 const char kTextHandlerName[] = "TextHandler";
29 
30 // Default values for VideoSampleEntry box.
31 const uint32_t kVideoResolution = 0x00480000; // 72 dpi.
32 const uint16_t kVideoFrameCount = 1;
33 const uint16_t kVideoDepth = 0x0018;
34 
35 const uint32_t kCompressorNameSize = 32u;
36 const char kAvcCompressorName[] = "\012AVC Coding";
37 const char kHevcCompressorName[] = "\013HEVC Coding";
38 const char kVpcCompressorName[] = "\012VPC Coding";
39 
40 // Using negative value as "not set". It is very unlikely that 2^31 cues happen
41 // at once.
42 const int kCueSourceIdNotSet = -1;
43 
44 // According to ISO/IEC FDIS 23001-7: CENC spec, IV should be either
45 // 64-bit (8-byte) or 128-bit (16-byte).
46 bool IsIvSizeValid(size_t iv_size) {
47  return iv_size == 8 || iv_size == 16;
48 }
49 
50 // Default values to construct the following fields in ddts box. Values are set
51 // according to FFMPEG.
52 // bit(2) FrameDuration; // 3 = 4096
53 // bit(5) StreamConstruction; // 18
54 // bit(1) CoreLFEPresent; // 0 = none
55 // bit(6) CoreLayout; // 31 = ignore core layout
56 // bit(14) CoreSize; // 0
57 // bit(1) StereoDownmix // 0 = none
58 // bit(3) RepresentationType; // 4
59 // bit(16) ChannelLayout; // 0xf = 5.1 channel layout.
60 // bit(1) MultiAssetFlag // 0 = single asset
61 // bit(1) LBRDurationMod // 0 = ignore
62 // bit(1) ReservedBoxPresent // 0 = none
63 // bit(5) Reserved // 0
64 const uint8_t kDdtsExtraData[] = {0xe4, 0x7c, 0, 4, 0, 0x0f, 0};
65 
66 // Utility functions to check if the 64bit integers can fit in 32bit integer.
67 bool IsFitIn32Bits(uint64_t a) {
68  return a <= std::numeric_limits<uint32_t>::max();
69 }
70 
71 bool IsFitIn32Bits(int64_t a) {
72  return a <= std::numeric_limits<int32_t>::max() &&
73  a >= std::numeric_limits<int32_t>::min();
74 }
75 
76 template <typename T1, typename T2>
77 bool IsFitIn32Bits(T1 a1, T2 a2) {
78  return IsFitIn32Bits(a1) && IsFitIn32Bits(a2);
79 }
80 
81 template <typename T1, typename T2, typename T3>
82 bool IsFitIn32Bits(T1 a1, T2 a2, T3 a3) {
83  return IsFitIn32Bits(a1) && IsFitIn32Bits(a2) && IsFitIn32Bits(a3);
84 }
85 
86 } // namespace
87 
88 namespace edash_packager {
89 namespace media {
90 namespace mp4 {
91 
92 FileType::FileType() : major_brand(FOURCC_NULL), minor_version(0) {}
93 FileType::~FileType() {}
94 FourCC FileType::BoxType() const { return FOURCC_FTYP; }
95 
96 bool FileType::ReadWriteInternal(BoxBuffer* buffer) {
97  RCHECK(ReadWriteHeaderInternal(buffer) &&
98  buffer->ReadWriteFourCC(&major_brand) &&
99  buffer->ReadWriteUInt32(&minor_version));
100  size_t num_brands;
101  if (buffer->Reading()) {
102  num_brands = (buffer->Size() - buffer->Pos()) / sizeof(FourCC);
103  compatible_brands.resize(num_brands);
104  } else {
105  num_brands = compatible_brands.size();
106  }
107  for (size_t i = 0; i < num_brands; ++i)
108  RCHECK(buffer->ReadWriteFourCC(&compatible_brands[i]));
109  return true;
110 }
111 
112 uint32_t FileType::ComputeSizeInternal() {
113  return HeaderSize() + kFourCCSize + sizeof(minor_version) +
114  kFourCCSize * compatible_brands.size();
115 }
116 
117 FourCC SegmentType::BoxType() const { return FOURCC_STYP; }
118 
119 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {}
120 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {}
121 FourCC ProtectionSystemSpecificHeader::BoxType() const { return FOURCC_PSSH; }
122 
123 bool ProtectionSystemSpecificHeader::ReadWriteInternal(BoxBuffer* buffer) {
124  if (!buffer->Reading() && !raw_box.empty()) {
125  // Write the raw box directly.
126  buffer->writer()->AppendVector(raw_box);
127  return true;
128  }
129 
130  uint32_t size = data.size();
131  RCHECK(ReadWriteHeaderInternal(buffer) &&
132  buffer->ReadWriteVector(&system_id, 16) &&
133  buffer->ReadWriteUInt32(&size) &&
134  buffer->ReadWriteVector(&data, size));
135 
136  if (buffer->Reading()) {
137  // Copy the entire box, including the header, for passing to EME as
138  // initData.
139  DCHECK(raw_box.empty());
140  BoxReader* reader = buffer->reader();
141  DCHECK(reader);
142  raw_box.assign(reader->data(), reader->data() + reader->size());
143  }
144  return true;
145 }
146 
147 uint32_t ProtectionSystemSpecificHeader::ComputeSizeInternal() {
148  if (!raw_box.empty()) {
149  return raw_box.size();
150  } else {
151  return HeaderSize() + system_id.size() + sizeof(uint32_t) + data.size();
152  }
153 }
154 
155 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {}
156 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {}
157 FourCC SampleAuxiliaryInformationOffset::BoxType() const { return FOURCC_SAIO; }
158 
159 bool SampleAuxiliaryInformationOffset::ReadWriteInternal(BoxBuffer* buffer) {
160  RCHECK(ReadWriteHeaderInternal(buffer));
161  if (flags & 1)
162  RCHECK(buffer->IgnoreBytes(8)); // aux_info_type and parameter.
163 
164  uint32_t count = offsets.size();
165  RCHECK(buffer->ReadWriteUInt32(&count));
166  offsets.resize(count);
167 
168  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
169  for (uint32_t i = 0; i < count; ++i)
170  RCHECK(buffer->ReadWriteUInt64NBytes(&offsets[i], num_bytes));
171  return true;
172 }
173 
174 uint32_t SampleAuxiliaryInformationOffset::ComputeSizeInternal() {
175  // This box is optional. Skip it if it is empty.
176  if (offsets.size() == 0)
177  return 0;
178  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
179  return HeaderSize() + sizeof(uint32_t) + num_bytes * offsets.size();
180 }
181 
182 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
183  : default_sample_info_size(0), sample_count(0) {}
184 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {}
185 FourCC SampleAuxiliaryInformationSize::BoxType() const { return FOURCC_SAIZ; }
186 
187 bool SampleAuxiliaryInformationSize::ReadWriteInternal(BoxBuffer* buffer) {
188  RCHECK(ReadWriteHeaderInternal(buffer));
189  if (flags & 1)
190  RCHECK(buffer->IgnoreBytes(8));
191 
192  RCHECK(buffer->ReadWriteUInt8(&default_sample_info_size) &&
193  buffer->ReadWriteUInt32(&sample_count));
194  if (default_sample_info_size == 0)
195  RCHECK(buffer->ReadWriteVector(&sample_info_sizes, sample_count));
196  return true;
197 }
198 
199 uint32_t SampleAuxiliaryInformationSize::ComputeSizeInternal() {
200  // This box is optional. Skip it if it is empty.
201  if (sample_count == 0)
202  return 0;
203  return HeaderSize() + sizeof(default_sample_info_size) +
204  sizeof(sample_count) +
205  (default_sample_info_size == 0 ? sample_info_sizes.size() : 0);
206 }
207 
208 SampleEncryptionEntry::SampleEncryptionEntry() {}
209 SampleEncryptionEntry::~SampleEncryptionEntry() {}
210 
211 bool SampleEncryptionEntry::ReadWrite(uint8_t iv_size,
212  bool has_subsamples,
213  BoxBuffer* buffer) {
214  DCHECK(IsIvSizeValid(iv_size));
215  DCHECK(buffer);
216 
217  RCHECK(buffer->ReadWriteVector(&initialization_vector, iv_size));
218 
219  if (!has_subsamples) {
220  subsamples.clear();
221  return true;
222  }
223 
224  uint16_t subsample_count = subsamples.size();
225  RCHECK(buffer->ReadWriteUInt16(&subsample_count));
226  RCHECK(subsample_count > 0);
227  subsamples.resize(subsample_count);
228  for (auto& subsample : subsamples) {
229  RCHECK(buffer->ReadWriteUInt16(&subsample.clear_bytes) &&
230  buffer->ReadWriteUInt32(&subsample.cipher_bytes));
231  }
232  return true;
233 }
234 
236  bool has_subsamples,
237  BufferReader* reader) {
238  DCHECK(IsIvSizeValid(iv_size));
239  DCHECK(reader);
240 
241  initialization_vector.resize(iv_size);
242  RCHECK(reader->ReadToVector(&initialization_vector, iv_size));
243 
244  if (!has_subsamples) {
245  subsamples.clear();
246  return true;
247  }
248 
249  uint16_t subsample_count;
250  RCHECK(reader->Read2(&subsample_count));
251  RCHECK(subsample_count > 0);
252  subsamples.resize(subsample_count);
253  for (auto& subsample : subsamples) {
254  RCHECK(reader->Read2(&subsample.clear_bytes) &&
255  reader->Read4(&subsample.cipher_bytes));
256  }
257  return true;
258 }
259 
261  const uint32_t subsample_entry_size = sizeof(uint16_t) + sizeof(uint32_t);
262  const uint16_t subsample_count = subsamples.size();
263  return initialization_vector.size() +
264  (subsample_count > 0 ? (sizeof(subsample_count) +
265  subsample_entry_size * subsample_count)
266  : 0);
267 }
268 
270  uint32_t size = 0;
271  for (uint32_t i = 0; i < subsamples.size(); ++i)
272  size += subsamples[i].clear_bytes + subsamples[i].cipher_bytes;
273  return size;
274 }
275 
276 SampleEncryption::SampleEncryption() : iv_size(0) {}
277 SampleEncryption::~SampleEncryption() {}
278 FourCC SampleEncryption::BoxType() const { return FOURCC_SENC; }
279 
280 bool SampleEncryption::ReadWriteInternal(BoxBuffer* buffer) {
281  RCHECK(ReadWriteHeaderInternal(buffer));
282 
283  // If we don't know |iv_size|, store sample encryption data to parse later
284  // after we know iv_size.
285  if (buffer->Reading() && iv_size == 0) {
286  RCHECK(buffer->ReadWriteVector(&sample_encryption_data,
287  buffer->Size() - buffer->Pos()));
288  return true;
289  }
290 
291  if (!IsIvSizeValid(iv_size)) {
292  LOG(ERROR) << "IV_size can only be 8 or 16, but seeing " << iv_size;
293  return false;
294  }
295 
296  uint32_t sample_count = sample_encryption_entries.size();
297  RCHECK(buffer->ReadWriteUInt32(&sample_count));
298 
299  sample_encryption_entries.resize(sample_count);
300  for (auto& sample_encryption_entry : sample_encryption_entries) {
301  RCHECK(sample_encryption_entry.ReadWrite(
302  iv_size, flags & kUseSubsampleEncryption, buffer));
303  }
304  return true;
305 }
306 
307 uint32_t SampleEncryption::ComputeSizeInternal() {
308  const uint32_t sample_count = sample_encryption_entries.size();
309  if (sample_count == 0) {
310  // Sample encryption box is optional. Skip it if it is empty.
311  return 0;
312  }
313 
314  DCHECK(IsIvSizeValid(iv_size));
315  uint32_t box_size = HeaderSize() + sizeof(sample_count);
316  if (flags & kUseSubsampleEncryption) {
317  for (const SampleEncryptionEntry& sample_encryption_entry :
318  sample_encryption_entries) {
319  box_size += sample_encryption_entry.ComputeSize();
320  }
321  } else {
322  box_size += sample_count * iv_size;
323  }
324  return box_size;
325 }
326 
328  size_t iv_size,
329  std::vector<SampleEncryptionEntry>* sample_encryption_entries) const {
330  DCHECK(IsIvSizeValid(iv_size));
331 
332  BufferReader reader(vector_as_array(&sample_encryption_data),
333  sample_encryption_data.size());
334  uint32_t sample_count = 0;
335  RCHECK(reader.Read4(&sample_count));
336 
337  sample_encryption_entries->resize(sample_count);
338  for (auto& sample_encryption_entry : *sample_encryption_entries) {
339  RCHECK(sample_encryption_entry.ParseFromBuffer(
340  iv_size, flags & kUseSubsampleEncryption, &reader));
341  }
342  return true;
343 }
344 
345 OriginalFormat::OriginalFormat() : format(FOURCC_NULL) {}
346 OriginalFormat::~OriginalFormat() {}
347 FourCC OriginalFormat::BoxType() const { return FOURCC_FRMA; }
348 
349 bool OriginalFormat::ReadWriteInternal(BoxBuffer* buffer) {
350  return ReadWriteHeaderInternal(buffer) && buffer->ReadWriteFourCC(&format);
351 }
352 
353 uint32_t OriginalFormat::ComputeSizeInternal() {
354  return HeaderSize() + kFourCCSize;
355 }
356 
357 SchemeType::SchemeType() : type(FOURCC_NULL), version(0) {}
358 SchemeType::~SchemeType() {}
359 FourCC SchemeType::BoxType() const { return FOURCC_SCHM; }
360 
361 bool SchemeType::ReadWriteInternal(BoxBuffer* buffer) {
362  RCHECK(ReadWriteHeaderInternal(buffer) &&
363  buffer->ReadWriteFourCC(&type) &&
364  buffer->ReadWriteUInt32(&version));
365  return true;
366 }
367 
368 uint32_t SchemeType::ComputeSizeInternal() {
369  return HeaderSize() + kFourCCSize + sizeof(version);
370 }
371 
372 TrackEncryption::TrackEncryption()
373  : is_encrypted(false), default_iv_size(0), default_kid(16, 0) {}
374 TrackEncryption::~TrackEncryption() {}
375 FourCC TrackEncryption::BoxType() const { return FOURCC_TENC; }
376 
377 bool TrackEncryption::ReadWriteInternal(BoxBuffer* buffer) {
378  if (!buffer->Reading()) {
379  if (default_kid.size() != kCencKeyIdSize) {
380  LOG(WARNING) << "CENC defines key id length of " << kCencKeyIdSize
381  << " bytes; got " << default_kid.size()
382  << ". Resized accordingly.";
383  default_kid.resize(kCencKeyIdSize);
384  }
385  }
386 
387  uint8_t flag = is_encrypted ? 1 : 0;
388  RCHECK(ReadWriteHeaderInternal(buffer) &&
389  buffer->IgnoreBytes(2) && // reserved.
390  buffer->ReadWriteUInt8(&flag) &&
391  buffer->ReadWriteUInt8(&default_iv_size) &&
392  buffer->ReadWriteVector(&default_kid, kCencKeyIdSize));
393  if (buffer->Reading()) {
394  is_encrypted = (flag != 0);
395  if (is_encrypted) {
396  RCHECK(default_iv_size == 8 || default_iv_size == 16);
397  } else {
398  RCHECK(default_iv_size == 0);
399  }
400  }
401  return true;
402 }
403 
404 uint32_t TrackEncryption::ComputeSizeInternal() {
405  return HeaderSize() + sizeof(uint32_t) + kCencKeyIdSize;
406 }
407 
408 SchemeInfo::SchemeInfo() {}
409 SchemeInfo::~SchemeInfo() {}
410 FourCC SchemeInfo::BoxType() const { return FOURCC_SCHI; }
411 
412 bool SchemeInfo::ReadWriteInternal(BoxBuffer* buffer) {
413  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->PrepareChildren() &&
414  buffer->ReadWriteChild(&track_encryption));
415  return true;
416 }
417 
418 uint32_t SchemeInfo::ComputeSizeInternal() {
419  return HeaderSize() + track_encryption.ComputeSize();
420 }
421 
422 ProtectionSchemeInfo::ProtectionSchemeInfo() {}
423 ProtectionSchemeInfo::~ProtectionSchemeInfo() {}
424 FourCC ProtectionSchemeInfo::BoxType() const { return FOURCC_SINF; }
425 
426 bool ProtectionSchemeInfo::ReadWriteInternal(BoxBuffer* buffer) {
427  RCHECK(ReadWriteHeaderInternal(buffer) &&
428  buffer->PrepareChildren() &&
429  buffer->ReadWriteChild(&format) &&
430  buffer->ReadWriteChild(&type));
431  if (type.type == FOURCC_CENC)
432  RCHECK(buffer->ReadWriteChild(&info));
433  // Other protection schemes are silently ignored. Since the protection scheme
434  // type can't be determined until this box is opened, we return 'true' for
435  // non-CENC protection scheme types. It is the parent box's responsibility to
436  // ensure that this scheme type is a supported one.
437  return true;
438 }
439 
440 uint32_t ProtectionSchemeInfo::ComputeSizeInternal() {
441  // Skip sinf box if it is not initialized.
442  if (format.format == FOURCC_NULL)
443  return 0;
444  return HeaderSize() + format.ComputeSize() + type.ComputeSize() +
445  info.ComputeSize();
446 }
447 
448 MovieHeader::MovieHeader()
449  : creation_time(0),
450  modification_time(0),
451  timescale(0),
452  duration(0),
453  rate(1 << 16),
454  volume(1 << 8),
455  next_track_id(0) {}
456 MovieHeader::~MovieHeader() {}
457 FourCC MovieHeader::BoxType() const { return FOURCC_MVHD; }
458 
459 bool MovieHeader::ReadWriteInternal(BoxBuffer* buffer) {
460  RCHECK(ReadWriteHeaderInternal(buffer));
461 
462  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
463  RCHECK(buffer->ReadWriteUInt64NBytes(&creation_time, num_bytes) &&
464  buffer->ReadWriteUInt64NBytes(&modification_time, num_bytes) &&
465  buffer->ReadWriteUInt32(&timescale) &&
466  buffer->ReadWriteUInt64NBytes(&duration, num_bytes));
467 
468  std::vector<uint8_t> matrix(kUnityMatrix,
469  kUnityMatrix + arraysize(kUnityMatrix));
470  RCHECK(buffer->ReadWriteInt32(&rate) &&
471  buffer->ReadWriteInt16(&volume) &&
472  buffer->IgnoreBytes(10) && // reserved
473  buffer->ReadWriteVector(&matrix, matrix.size()) &&
474  buffer->IgnoreBytes(24) && // predefined zero
475  buffer->ReadWriteUInt32(&next_track_id));
476  return true;
477 }
478 
479 uint32_t MovieHeader::ComputeSizeInternal() {
480  version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
481  return HeaderSize() + sizeof(uint32_t) * (1 + version) * 3 +
482  sizeof(timescale) + sizeof(rate) + sizeof(volume) +
483  sizeof(next_track_id) + sizeof(kUnityMatrix) + 10 +
484  24; // 10 bytes reserved, 24 bytes predefined.
485 }
486 
487 TrackHeader::TrackHeader()
488  : creation_time(0),
489  modification_time(0),
490  track_id(0),
491  duration(0),
492  layer(0),
493  alternate_group(0),
494  volume(-1),
495  width(0),
496  height(0) {
497  flags = kTrackEnabled | kTrackInMovie;
498 }
499 TrackHeader::~TrackHeader() {}
500 FourCC TrackHeader::BoxType() const { return FOURCC_TKHD; }
501 
502 bool TrackHeader::ReadWriteInternal(BoxBuffer* buffer) {
503  RCHECK(ReadWriteHeaderInternal(buffer));
504 
505  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
506  RCHECK(buffer->ReadWriteUInt64NBytes(&creation_time, num_bytes) &&
507  buffer->ReadWriteUInt64NBytes(&modification_time, num_bytes) &&
508  buffer->ReadWriteUInt32(&track_id) &&
509  buffer->IgnoreBytes(4) && // reserved
510  buffer->ReadWriteUInt64NBytes(&duration, num_bytes));
511 
512  if (!buffer->Reading()) {
513  // Set default value for volume, if track is audio, 0x100 else 0.
514  if (volume == -1)
515  volume = (width != 0 && height != 0) ? 0 : 0x100;
516  }
517  std::vector<uint8_t> matrix(kUnityMatrix,
518  kUnityMatrix + arraysize(kUnityMatrix));
519  RCHECK(buffer->IgnoreBytes(8) && // reserved
520  buffer->ReadWriteInt16(&layer) &&
521  buffer->ReadWriteInt16(&alternate_group) &&
522  buffer->ReadWriteInt16(&volume) &&
523  buffer->IgnoreBytes(2) && // reserved
524  buffer->ReadWriteVector(&matrix, matrix.size()) &&
525  buffer->ReadWriteUInt32(&width) &&
526  buffer->ReadWriteUInt32(&height));
527  return true;
528 }
529 
530 uint32_t TrackHeader::ComputeSizeInternal() {
531  version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
532  return HeaderSize() + sizeof(track_id) +
533  sizeof(uint32_t) * (1 + version) * 3 + sizeof(layer) +
534  sizeof(alternate_group) + sizeof(volume) + sizeof(width) +
535  sizeof(height) + sizeof(kUnityMatrix) + 14; // 14 bytes reserved.
536 }
537 
538 SampleDescription::SampleDescription() : type(kInvalid) {}
539 SampleDescription::~SampleDescription() {}
540 FourCC SampleDescription::BoxType() const { return FOURCC_STSD; }
541 
542 bool SampleDescription::ReadWriteInternal(BoxBuffer* buffer) {
543  uint32_t count = 0;
544  switch (type) {
545  case kVideo:
546  count = video_entries.size();
547  break;
548  case kAudio:
549  count = audio_entries.size();
550  break;
551  case kText:
552  count = wvtt_entries.size();
553  break;
554  default:
555  NOTIMPLEMENTED() << "SampleDecryption type " << type
556  << " is not handled. Skipping.";
557  }
558  RCHECK(ReadWriteHeaderInternal(buffer) &&
559  buffer->ReadWriteUInt32(&count));
560 
561  if (buffer->Reading()) {
562  BoxReader* reader = buffer->reader();
563  DCHECK(reader);
564  video_entries.clear();
565  audio_entries.clear();
566  // Note: this value is preset before scanning begins. See comments in the
567  // Parse(Media*) function.
568  if (type == kVideo) {
569  RCHECK(reader->ReadAllChildren(&video_entries));
570  RCHECK(video_entries.size() == count);
571  } else if (type == kAudio) {
572  RCHECK(reader->ReadAllChildren(&audio_entries));
573  RCHECK(audio_entries.size() == count);
574  } else if (type == kText) {
575  RCHECK(reader->ReadAllChildren(&wvtt_entries));
576  RCHECK(wvtt_entries.size() == count);
577  }
578  } else {
579  DCHECK_LT(0u, count);
580  if (type == kVideo) {
581  for (uint32_t i = 0; i < count; ++i)
582  RCHECK(buffer->ReadWriteChild(&video_entries[i]));
583  } else if (type == kAudio) {
584  for (uint32_t i = 0; i < count; ++i)
585  RCHECK(buffer->ReadWriteChild(&audio_entries[i]));
586  } else if (type == kText) {
587  for (uint32_t i = 0; i < count; ++i)
588  RCHECK(buffer->ReadWriteChild(&wvtt_entries[i]));
589  } else {
590  NOTIMPLEMENTED();
591  }
592  }
593  return true;
594 }
595 
596 uint32_t SampleDescription::ComputeSizeInternal() {
597  uint32_t box_size = HeaderSize() + sizeof(uint32_t);
598  if (type == kVideo) {
599  for (uint32_t i = 0; i < video_entries.size(); ++i)
600  box_size += video_entries[i].ComputeSize();
601  } else if (type == kAudio) {
602  for (uint32_t i = 0; i < audio_entries.size(); ++i)
603  box_size += audio_entries[i].ComputeSize();
604  }
605  return box_size;
606 }
607 
608 DecodingTimeToSample::DecodingTimeToSample() {}
609 DecodingTimeToSample::~DecodingTimeToSample() {}
610 FourCC DecodingTimeToSample::BoxType() const { return FOURCC_STTS; }
611 
612 bool DecodingTimeToSample::ReadWriteInternal(BoxBuffer* buffer) {
613  uint32_t count = decoding_time.size();
614  RCHECK(ReadWriteHeaderInternal(buffer) &&
615  buffer->ReadWriteUInt32(&count));
616 
617  decoding_time.resize(count);
618  for (uint32_t i = 0; i < count; ++i) {
619  RCHECK(buffer->ReadWriteUInt32(&decoding_time[i].sample_count) &&
620  buffer->ReadWriteUInt32(&decoding_time[i].sample_delta));
621  }
622  return true;
623 }
624 
625 uint32_t DecodingTimeToSample::ComputeSizeInternal() {
626  return HeaderSize() + sizeof(uint32_t) +
627  sizeof(DecodingTime) * decoding_time.size();
628 }
629 
630 CompositionTimeToSample::CompositionTimeToSample() {}
631 CompositionTimeToSample::~CompositionTimeToSample() {}
632 FourCC CompositionTimeToSample::BoxType() const { return FOURCC_CTTS; }
633 
634 bool CompositionTimeToSample::ReadWriteInternal(BoxBuffer* buffer) {
635  uint32_t count = composition_offset.size();
636  if (!buffer->Reading()) {
637  // Determine whether version 0 or version 1 should be used.
638  // Use version 0 if possible, use version 1 if there is a negative
639  // sample_offset value.
640  version = 0;
641  for (uint32_t i = 0; i < count; ++i) {
642  if (composition_offset[i].sample_offset < 0) {
643  version = 1;
644  break;
645  }
646  }
647  }
648 
649  RCHECK(ReadWriteHeaderInternal(buffer) &&
650  buffer->ReadWriteUInt32(&count));
651 
652  composition_offset.resize(count);
653  for (uint32_t i = 0; i < count; ++i) {
654  RCHECK(buffer->ReadWriteUInt32(&composition_offset[i].sample_count));
655 
656  if (version == 0) {
657  uint32_t sample_offset = composition_offset[i].sample_offset;
658  RCHECK(buffer->ReadWriteUInt32(&sample_offset));
659  composition_offset[i].sample_offset = sample_offset;
660  } else {
661  int32_t sample_offset = composition_offset[i].sample_offset;
662  RCHECK(buffer->ReadWriteInt32(&sample_offset));
663  composition_offset[i].sample_offset = sample_offset;
664  }
665  }
666  return true;
667 }
668 
669 uint32_t CompositionTimeToSample::ComputeSizeInternal() {
670  // This box is optional. Skip it if it is empty.
671  if (composition_offset.empty())
672  return 0;
673  // Structure CompositionOffset contains |sample_offset| (uint32_t) and
674  // |sample_offset| (int64_t). The actual size of |sample_offset| is
675  // 4 bytes (uint32_t for version 0 and int32_t for version 1).
676  const uint32_t kCompositionOffsetSize = sizeof(uint32_t) * 2;
677  return HeaderSize() + sizeof(uint32_t) +
678  kCompositionOffsetSize * composition_offset.size();
679 }
680 
681 SampleToChunk::SampleToChunk() {}
682 SampleToChunk::~SampleToChunk() {}
683 FourCC SampleToChunk::BoxType() const { return FOURCC_STSC; }
684 
685 bool SampleToChunk::ReadWriteInternal(BoxBuffer* buffer) {
686  uint32_t count = chunk_info.size();
687  RCHECK(ReadWriteHeaderInternal(buffer) &&
688  buffer->ReadWriteUInt32(&count));
689 
690  chunk_info.resize(count);
691  for (uint32_t i = 0; i < count; ++i) {
692  RCHECK(buffer->ReadWriteUInt32(&chunk_info[i].first_chunk) &&
693  buffer->ReadWriteUInt32(&chunk_info[i].samples_per_chunk) &&
694  buffer->ReadWriteUInt32(&chunk_info[i].sample_description_index));
695  // first_chunk values are always increasing.
696  RCHECK(i == 0 ? chunk_info[i].first_chunk == 1
697  : chunk_info[i].first_chunk > chunk_info[i - 1].first_chunk);
698  }
699  return true;
700 }
701 
702 uint32_t SampleToChunk::ComputeSizeInternal() {
703  return HeaderSize() + sizeof(uint32_t) +
704  sizeof(ChunkInfo) * chunk_info.size();
705 }
706 
707 SampleSize::SampleSize() : sample_size(0), sample_count(0) {}
708 SampleSize::~SampleSize() {}
709 FourCC SampleSize::BoxType() const { return FOURCC_STSZ; }
710 
711 bool SampleSize::ReadWriteInternal(BoxBuffer* buffer) {
712  RCHECK(ReadWriteHeaderInternal(buffer) &&
713  buffer->ReadWriteUInt32(&sample_size) &&
714  buffer->ReadWriteUInt32(&sample_count));
715 
716  if (sample_size == 0) {
717  if (buffer->Reading())
718  sizes.resize(sample_count);
719  else
720  DCHECK(sample_count == sizes.size());
721  for (uint32_t i = 0; i < sample_count; ++i)
722  RCHECK(buffer->ReadWriteUInt32(&sizes[i]));
723  }
724  return true;
725 }
726 
727 uint32_t SampleSize::ComputeSizeInternal() {
728  return HeaderSize() + sizeof(sample_size) + sizeof(sample_count) +
729  (sample_size == 0 ? sizeof(uint32_t) * sizes.size() : 0);
730 }
731 
732 CompactSampleSize::CompactSampleSize() : field_size(0) {}
733 CompactSampleSize::~CompactSampleSize() {}
734 FourCC CompactSampleSize::BoxType() const { return FOURCC_STZ2; }
735 
736 bool CompactSampleSize::ReadWriteInternal(BoxBuffer* buffer) {
737  uint32_t sample_count = sizes.size();
738  RCHECK(ReadWriteHeaderInternal(buffer) &&
739  buffer->IgnoreBytes(3) &&
740  buffer->ReadWriteUInt8(&field_size) &&
741  buffer->ReadWriteUInt32(&sample_count));
742 
743  // Reserve one more entry if field size is 4 bits.
744  sizes.resize(sample_count + (field_size == 4 ? 1 : 0), 0);
745  switch (field_size) {
746  case 4:
747  for (uint32_t i = 0; i < sample_count; i += 2) {
748  if (buffer->Reading()) {
749  uint8_t size = 0;
750  RCHECK(buffer->ReadWriteUInt8(&size));
751  sizes[i] = size >> 4;
752  sizes[i + 1] = size & 0x0F;
753  } else {
754  DCHECK_LT(sizes[i], 16u);
755  DCHECK_LT(sizes[i + 1], 16u);
756  uint8_t size = (sizes[i] << 4) | sizes[i + 1];
757  RCHECK(buffer->ReadWriteUInt8(&size));
758  }
759  }
760  break;
761  case 8:
762  for (uint32_t i = 0; i < sample_count; ++i) {
763  uint8_t size = sizes[i];
764  RCHECK(buffer->ReadWriteUInt8(&size));
765  sizes[i] = size;
766  }
767  break;
768  case 16:
769  for (uint32_t i = 0; i < sample_count; ++i) {
770  uint16_t size = sizes[i];
771  RCHECK(buffer->ReadWriteUInt16(&size));
772  sizes[i] = size;
773  }
774  break;
775  default:
776  RCHECK(false);
777  }
778  sizes.resize(sample_count);
779  return true;
780 }
781 
782 uint32_t CompactSampleSize::ComputeSizeInternal() {
783  return HeaderSize() + sizeof(uint32_t) + sizeof(uint32_t) +
784  (field_size * sizes.size() + 7) / 8;
785 }
786 
787 ChunkOffset::ChunkOffset() {}
788 ChunkOffset::~ChunkOffset() {}
789 FourCC ChunkOffset::BoxType() const { return FOURCC_STCO; }
790 
791 bool ChunkOffset::ReadWriteInternal(BoxBuffer* buffer) {
792  uint32_t count = offsets.size();
793  RCHECK(ReadWriteHeaderInternal(buffer) &&
794  buffer->ReadWriteUInt32(&count));
795 
796  offsets.resize(count);
797  for (uint32_t i = 0; i < count; ++i)
798  RCHECK(buffer->ReadWriteUInt64NBytes(&offsets[i], sizeof(uint32_t)));
799  return true;
800 }
801 
802 uint32_t ChunkOffset::ComputeSizeInternal() {
803  return HeaderSize() + sizeof(uint32_t) + sizeof(uint32_t) * offsets.size();
804 }
805 
806 ChunkLargeOffset::ChunkLargeOffset() {}
807 ChunkLargeOffset::~ChunkLargeOffset() {}
808 FourCC ChunkLargeOffset::BoxType() const { return FOURCC_CO64; }
809 
810 bool ChunkLargeOffset::ReadWriteInternal(BoxBuffer* buffer) {
811  uint32_t count = offsets.size();
812 
813  if (!buffer->Reading()) {
814  // Switch to ChunkOffset box if it is able to fit in 32 bits offset.
815  if (count == 0 || IsFitIn32Bits(offsets[count - 1])) {
816  ChunkOffset stco;
817  stco.offsets.swap(offsets);
818  DCHECK(buffer->writer());
819  stco.Write(buffer->writer());
820  stco.offsets.swap(offsets);
821  return true;
822  }
823  }
824 
825  RCHECK(ReadWriteHeaderInternal(buffer) &&
826  buffer->ReadWriteUInt32(&count));
827 
828  offsets.resize(count);
829  for (uint32_t i = 0; i < count; ++i)
830  RCHECK(buffer->ReadWriteUInt64(&offsets[i]));
831  return true;
832 }
833 
834 uint32_t ChunkLargeOffset::ComputeSizeInternal() {
835  uint32_t count = offsets.size();
836  int use_large_offset =
837  (count > 0 && !IsFitIn32Bits(offsets[count - 1])) ? 1 : 0;
838  return HeaderSize() + sizeof(count) +
839  sizeof(uint32_t) * (1 + use_large_offset) * offsets.size();
840 }
841 
842 SyncSample::SyncSample() {}
843 SyncSample::~SyncSample() {}
844 FourCC SyncSample::BoxType() const { return FOURCC_STSS; }
845 
846 bool SyncSample::ReadWriteInternal(BoxBuffer* buffer) {
847  uint32_t count = sample_number.size();
848  RCHECK(ReadWriteHeaderInternal(buffer) &&
849  buffer->ReadWriteUInt32(&count));
850 
851  sample_number.resize(count);
852  for (uint32_t i = 0; i < count; ++i)
853  RCHECK(buffer->ReadWriteUInt32(&sample_number[i]));
854  return true;
855 }
856 
857 uint32_t SyncSample::ComputeSizeInternal() {
858  // Sync sample box is optional. Skip it if it is empty.
859  if (sample_number.empty())
860  return 0;
861  return HeaderSize() + sizeof(uint32_t) +
862  sizeof(uint32_t) * sample_number.size();
863 }
864 
865 SampleTable::SampleTable() {}
866 SampleTable::~SampleTable() {}
867 FourCC SampleTable::BoxType() const { return FOURCC_STBL; }
868 
869 bool SampleTable::ReadWriteInternal(BoxBuffer* buffer) {
870  RCHECK(ReadWriteHeaderInternal(buffer) &&
871  buffer->PrepareChildren() &&
872  buffer->ReadWriteChild(&description) &&
873  buffer->ReadWriteChild(&decoding_time_to_sample) &&
874  buffer->TryReadWriteChild(&composition_time_to_sample) &&
875  buffer->ReadWriteChild(&sample_to_chunk));
876 
877  if (buffer->Reading()) {
878  BoxReader* reader = buffer->reader();
879  DCHECK(reader);
880 
881  // Either SampleSize or CompactSampleSize must present.
882  if (reader->ChildExist(&sample_size)) {
883  RCHECK(reader->ReadChild(&sample_size));
884  } else {
885  CompactSampleSize compact_sample_size;
886  RCHECK(reader->ReadChild(&compact_sample_size));
887  sample_size.sample_size = 0;
888  sample_size.sample_count = compact_sample_size.sizes.size();
889  sample_size.sizes.swap(compact_sample_size.sizes);
890  }
891 
892  // Either ChunkOffset or ChunkLargeOffset must present.
893  if (reader->ChildExist(&chunk_large_offset)) {
894  RCHECK(reader->ReadChild(&chunk_large_offset));
895  } else {
896  ChunkOffset chunk_offset;
897  RCHECK(reader->ReadChild(&chunk_offset));
898  chunk_large_offset.offsets.swap(chunk_offset.offsets);
899  }
900  } else {
901  RCHECK(buffer->ReadWriteChild(&sample_size) &&
902  buffer->ReadWriteChild(&chunk_large_offset));
903  }
904  RCHECK(buffer->TryReadWriteChild(&sync_sample));
905  return true;
906 }
907 
908 uint32_t SampleTable::ComputeSizeInternal() {
909  return HeaderSize() + description.ComputeSize() +
910  decoding_time_to_sample.ComputeSize() +
911  composition_time_to_sample.ComputeSize() +
912  sample_to_chunk.ComputeSize() + sample_size.ComputeSize() +
913  chunk_large_offset.ComputeSize() + sync_sample.ComputeSize();
914 }
915 
916 EditList::EditList() {}
917 EditList::~EditList() {}
918 FourCC EditList::BoxType() const { return FOURCC_ELST; }
919 
920 bool EditList::ReadWriteInternal(BoxBuffer* buffer) {
921  uint32_t count = edits.size();
922  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteUInt32(&count));
923  edits.resize(count);
924 
925  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
926  for (uint32_t i = 0; i < count; ++i) {
927  RCHECK(
928  buffer->ReadWriteUInt64NBytes(&edits[i].segment_duration, num_bytes) &&
929  buffer->ReadWriteInt64NBytes(&edits[i].media_time, num_bytes) &&
930  buffer->ReadWriteInt16(&edits[i].media_rate_integer) &&
931  buffer->ReadWriteInt16(&edits[i].media_rate_fraction));
932  }
933  return true;
934 }
935 
936 uint32_t EditList::ComputeSizeInternal() {
937  // EditList box is optional. Skip it if it is empty.
938  if (edits.empty())
939  return 0;
940 
941  version = 0;
942  for (uint32_t i = 0; i < edits.size(); ++i) {
943  if (!IsFitIn32Bits(edits[i].segment_duration, edits[i].media_time)) {
944  version = 1;
945  break;
946  }
947  }
948  return HeaderSize() + sizeof(uint32_t) +
949  (sizeof(uint32_t) * (1 + version) * 2 + sizeof(int16_t) * 2) *
950  edits.size();
951 }
952 
953 Edit::Edit() {}
954 Edit::~Edit() {}
955 FourCC Edit::BoxType() const { return FOURCC_EDTS; }
956 
957 bool Edit::ReadWriteInternal(BoxBuffer* buffer) {
958  return ReadWriteHeaderInternal(buffer) &&
959  buffer->PrepareChildren() &&
960  buffer->ReadWriteChild(&list);
961 }
962 
963 uint32_t Edit::ComputeSizeInternal() {
964  // Edit box is optional. Skip it if it is empty.
965  if (list.edits.empty())
966  return 0;
967  return HeaderSize() + list.ComputeSize();
968 }
969 
970 HandlerReference::HandlerReference() : type(kInvalid) {}
971 HandlerReference::~HandlerReference() {}
972 FourCC HandlerReference::BoxType() const { return FOURCC_HDLR; }
973 
974 bool HandlerReference::ReadWriteInternal(BoxBuffer* buffer) {
975  FourCC hdlr_type = FOURCC_NULL;
976  std::vector<uint8_t> handler_name;
977  if (!buffer->Reading()) {
978  if (type == kVideo) {
979  hdlr_type = FOURCC_VIDE;
980  handler_name.assign(kVideoHandlerName,
981  kVideoHandlerName + arraysize(kVideoHandlerName));
982  } else if (type == kAudio) {
983  hdlr_type = FOURCC_SOUN;
984  handler_name.assign(kAudioHandlerName,
985  kAudioHandlerName + arraysize(kAudioHandlerName));
986  } else if (type == kText) {
987  hdlr_type = FOURCC_TEXT;
988  handler_name.assign(kTextHandlerName,
989  kTextHandlerName + arraysize(kTextHandlerName));
990  } else {
991  NOTIMPLEMENTED();
992  return false;
993  }
994  }
995  RCHECK(ReadWriteHeaderInternal(buffer) &&
996  buffer->IgnoreBytes(4) && // predefined.
997  buffer->ReadWriteFourCC(&hdlr_type));
998  if (buffer->Reading()) {
999  // Note: for reading, remaining fields in box ignored.
1000  if (hdlr_type == FOURCC_VIDE) {
1001  type = kVideo;
1002  } else if (hdlr_type == FOURCC_SOUN) {
1003  type = kAudio;
1004  } else {
1005  type = kInvalid;
1006  }
1007  } else {
1008  RCHECK(buffer->IgnoreBytes(12) && // reserved.
1009  buffer->ReadWriteVector(&handler_name, handler_name.size()));
1010  }
1011  return true;
1012 }
1013 
1014 uint32_t HandlerReference::ComputeSizeInternal() {
1015  uint32_t box_size = HeaderSize() + kFourCCSize + 16; // 16 bytes Reserved
1016  if (type == kVideo) {
1017  box_size += sizeof(kVideoHandlerName);
1018  } else if (type == kAudio) {
1019  box_size += sizeof(kAudioHandlerName);
1020  } else {
1021  box_size += sizeof(kTextHandlerName);
1022  }
1023  return box_size;
1024 }
1025 
1026 CodecConfigurationRecord::CodecConfigurationRecord() : box_type(FOURCC_NULL) {}
1027 CodecConfigurationRecord::~CodecConfigurationRecord() {}
1029  // CodecConfigurationRecord should be parsed according to format recovered in
1030  // VideoSampleEntry. |box_type| is determined dynamically there.
1031  return box_type;
1032 }
1033 
1034 bool CodecConfigurationRecord::ReadWriteInternal(BoxBuffer* buffer) {
1035  RCHECK(ReadWriteHeaderInternal(buffer));
1036  if (buffer->Reading()) {
1037  RCHECK(buffer->ReadWriteVector(&data, buffer->BytesLeft()));
1038  } else {
1039  RCHECK(buffer->ReadWriteVector(&data, data.size()));
1040  }
1041  return true;
1042 }
1043 
1044 uint32_t CodecConfigurationRecord::ComputeSizeInternal() {
1045  if (data.empty())
1046  return 0;
1047  return HeaderSize() + data.size();
1048 }
1049 
1050 PixelAspectRatio::PixelAspectRatio() : h_spacing(0), v_spacing(0) {}
1051 PixelAspectRatio::~PixelAspectRatio() {}
1052 FourCC PixelAspectRatio::BoxType() const { return FOURCC_PASP; }
1053 
1054 bool PixelAspectRatio::ReadWriteInternal(BoxBuffer* buffer) {
1055  RCHECK(ReadWriteHeaderInternal(buffer) &&
1056  buffer->ReadWriteUInt32(&h_spacing) &&
1057  buffer->ReadWriteUInt32(&v_spacing));
1058  return true;
1059 }
1060 
1061 uint32_t PixelAspectRatio::ComputeSizeInternal() {
1062  // This box is optional. Skip it if it is not initialized.
1063  if (h_spacing == 0 && v_spacing == 0)
1064  return 0;
1065  // Both values must be positive.
1066  DCHECK(h_spacing != 0 && v_spacing != 0);
1067  return HeaderSize() + sizeof(h_spacing) + sizeof(v_spacing);
1068 }
1069 
1070 VideoSampleEntry::VideoSampleEntry()
1071  : format(FOURCC_NULL), data_reference_index(1), width(0), height(0) {}
1072 
1073 VideoSampleEntry::~VideoSampleEntry() {}
1075  if (format == FOURCC_NULL) {
1076  LOG(ERROR) << "VideoSampleEntry should be parsed according to the "
1077  << "handler type recovered in its Media ancestor.";
1078  }
1079  return format;
1080 }
1081 
1082 bool VideoSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
1083  std::vector<uint8_t> compressor_name;
1084  if (buffer->Reading()) {
1085  DCHECK(buffer->reader());
1086  format = buffer->reader()->type();
1087  } else {
1088  RCHECK(ReadWriteHeaderInternal(buffer));
1089 
1090  const FourCC actual_format = GetActualFormat();
1091  switch (actual_format) {
1092  case FOURCC_AVC1:
1093  compressor_name.assign(
1094  kAvcCompressorName,
1095  kAvcCompressorName + arraysize(kAvcCompressorName));
1096  break;
1097  case FOURCC_HEV1:
1098  case FOURCC_HVC1:
1099  compressor_name.assign(
1100  kHevcCompressorName,
1101  kHevcCompressorName + arraysize(kHevcCompressorName));
1102  break;
1103  case FOURCC_VP08:
1104  case FOURCC_VP09:
1105  case FOURCC_VP10:
1106  compressor_name.assign(
1107  kVpcCompressorName,
1108  kVpcCompressorName + arraysize(kVpcCompressorName));
1109  break;
1110  default:
1111  LOG(ERROR) << FourCCToString(actual_format) << " is not supported.";
1112  return false;
1113  }
1114  compressor_name.resize(kCompressorNameSize);
1115  }
1116 
1117  uint32_t video_resolution = kVideoResolution;
1118  uint16_t video_frame_count = kVideoFrameCount;
1119  uint16_t video_depth = kVideoDepth;
1120  int16_t predefined = -1;
1121  RCHECK(buffer->IgnoreBytes(6) && // reserved.
1122  buffer->ReadWriteUInt16(&data_reference_index) &&
1123  buffer->IgnoreBytes(16) && // predefined 0.
1124  buffer->ReadWriteUInt16(&width) &&
1125  buffer->ReadWriteUInt16(&height) &&
1126  buffer->ReadWriteUInt32(&video_resolution) &&
1127  buffer->ReadWriteUInt32(&video_resolution) &&
1128  buffer->IgnoreBytes(4) && // reserved.
1129  buffer->ReadWriteUInt16(&video_frame_count) &&
1130  buffer->ReadWriteVector(&compressor_name, kCompressorNameSize) &&
1131  buffer->ReadWriteUInt16(&video_depth) &&
1132  buffer->ReadWriteInt16(&predefined));
1133 
1134  RCHECK(buffer->PrepareChildren());
1135 
1136  if (format == FOURCC_ENCV) {
1137  if (buffer->Reading()) {
1138  // Continue scanning until a recognized protection scheme is found,
1139  // or until we run out of protection schemes.
1140  while (sinf.type.type != FOURCC_CENC) {
1141  if (!buffer->ReadWriteChild(&sinf))
1142  return false;
1143  }
1144  } else {
1145  RCHECK(buffer->ReadWriteChild(&sinf));
1146  }
1147  }
1148 
1149  const FourCC actual_format = GetActualFormat();
1150  switch (actual_format) {
1151  case FOURCC_AVC1:
1152  codec_config_record.box_type = FOURCC_AVCC;
1153  break;
1154  case FOURCC_HEV1:
1155  case FOURCC_HVC1:
1156  codec_config_record.box_type = FOURCC_HVCC;
1157  break;
1158  case FOURCC_VP08:
1159  case FOURCC_VP09:
1160  case FOURCC_VP10:
1161  codec_config_record.box_type = FOURCC_VPCC;
1162  break;
1163  default:
1164  LOG(ERROR) << FourCCToString(actual_format) << " is not supported.";
1165  return false;
1166  }
1167  RCHECK(buffer->ReadWriteChild(&codec_config_record));
1168  RCHECK(buffer->TryReadWriteChild(&pixel_aspect));
1169  return true;
1170 }
1171 
1172 uint32_t VideoSampleEntry::ComputeSizeInternal() {
1173  return HeaderSize() + sizeof(data_reference_index) + sizeof(width) +
1174  sizeof(height) + sizeof(kVideoResolution) * 2 +
1175  sizeof(kVideoFrameCount) + sizeof(kVideoDepth) +
1176  pixel_aspect.ComputeSize() + sinf.ComputeSize() +
1177  codec_config_record.ComputeSize() + kCompressorNameSize + 6 + 4 + 16 +
1178  2; // 6 + 4 bytes reserved, 16 + 2 bytes predefined.
1179 }
1180 
1181 ElementaryStreamDescriptor::ElementaryStreamDescriptor() {}
1182 ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
1183 FourCC ElementaryStreamDescriptor::BoxType() const { return FOURCC_ESDS; }
1184 
1185 bool ElementaryStreamDescriptor::ReadWriteInternal(BoxBuffer* buffer) {
1186  RCHECK(ReadWriteHeaderInternal(buffer));
1187  if (buffer->Reading()) {
1188  std::vector<uint8_t> data;
1189  RCHECK(buffer->ReadWriteVector(&data, buffer->BytesLeft()));
1190  RCHECK(es_descriptor.Parse(data));
1191  if (es_descriptor.IsAAC()) {
1192  RCHECK(aac_audio_specific_config.Parse(
1193  es_descriptor.decoder_specific_info()));
1194  }
1195  } else {
1196  DCHECK(buffer->writer());
1197  es_descriptor.Write(buffer->writer());
1198  }
1199  return true;
1200 }
1201 
1202 uint32_t ElementaryStreamDescriptor::ComputeSizeInternal() {
1203  // This box is optional. Skip it if not initialized.
1204  if (es_descriptor.object_type() == kForbidden)
1205  return 0;
1206  return HeaderSize() + es_descriptor.ComputeSize();
1207 }
1208 
1209 DTSSpecific::DTSSpecific()
1210  : sampling_frequency(0),
1211  max_bitrate(0),
1212  avg_bitrate(0),
1213  pcm_sample_depth(0) {}
1214 DTSSpecific::~DTSSpecific() {}
1215 FourCC DTSSpecific::BoxType() const { return FOURCC_DDTS; }
1216 
1217 bool DTSSpecific::ReadWriteInternal(BoxBuffer* buffer) {
1218  RCHECK(ReadWriteHeaderInternal(buffer) &&
1219  buffer->ReadWriteUInt32(&sampling_frequency) &&
1220  buffer->ReadWriteUInt32(&max_bitrate) &&
1221  buffer->ReadWriteUInt32(&avg_bitrate) &&
1222  buffer->ReadWriteUInt8(&pcm_sample_depth));
1223 
1224  if (buffer->Reading()) {
1225  RCHECK(buffer->ReadWriteVector(&extra_data, buffer->Size() - buffer->Pos()));
1226  } else {
1227  if (extra_data.empty()) {
1228  extra_data.assign(kDdtsExtraData,
1229  kDdtsExtraData + sizeof(kDdtsExtraData));
1230  }
1231  RCHECK(buffer->ReadWriteVector(&extra_data, extra_data.size()));
1232  }
1233  return true;
1234 }
1235 
1236 uint32_t DTSSpecific::ComputeSizeInternal() {
1237  // This box is optional. Skip it if not initialized.
1238  if (sampling_frequency == 0)
1239  return 0;
1240  return HeaderSize() + sizeof(sampling_frequency) + sizeof(max_bitrate) +
1241  sizeof(avg_bitrate) + sizeof(pcm_sample_depth) +
1242  sizeof(kDdtsExtraData);
1243 }
1244 
1245 AudioSampleEntry::AudioSampleEntry()
1246  : format(FOURCC_NULL),
1247  data_reference_index(1),
1248  channelcount(2),
1249  samplesize(16),
1250  samplerate(0) {}
1251 
1252 AudioSampleEntry::~AudioSampleEntry() {}
1253 
1255  if (format == FOURCC_NULL) {
1256  LOG(ERROR) << "AudioSampleEntry should be parsed according to the "
1257  << "handler type recovered in its Media ancestor.";
1258  }
1259  return format;
1260 }
1261 
1262 bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
1263  if (buffer->Reading()) {
1264  DCHECK(buffer->reader());
1265  format = buffer->reader()->type();
1266  } else {
1267  RCHECK(ReadWriteHeaderInternal(buffer));
1268  }
1269 
1270  // Convert from integer to 16.16 fixed point for writing.
1271  samplerate <<= 16;
1272  RCHECK(buffer->IgnoreBytes(6) && // reserved.
1273  buffer->ReadWriteUInt16(&data_reference_index) &&
1274  buffer->IgnoreBytes(8) && // reserved.
1275  buffer->ReadWriteUInt16(&channelcount) &&
1276  buffer->ReadWriteUInt16(&samplesize) &&
1277  buffer->IgnoreBytes(4) && // predefined.
1278  buffer->ReadWriteUInt32(&samplerate));
1279  // Convert from 16.16 fixed point to integer.
1280  samplerate >>= 16;
1281 
1282  RCHECK(buffer->PrepareChildren());
1283  if (format == FOURCC_ENCA) {
1284  if (buffer->Reading()) {
1285  // Continue scanning until a recognized protection scheme is found,
1286  // or until we run out of protection schemes.
1287  while (sinf.type.type != FOURCC_CENC) {
1288  if (!buffer->ReadWriteChild(&sinf))
1289  return false;
1290  }
1291  } else {
1292  RCHECK(buffer->ReadWriteChild(&sinf));
1293  }
1294  }
1295 
1296  RCHECK(buffer->TryReadWriteChild(&esds));
1297  RCHECK(buffer->TryReadWriteChild(&ddts));
1298  return true;
1299 }
1300 
1301 uint32_t AudioSampleEntry::ComputeSizeInternal() {
1302  return HeaderSize() + sizeof(data_reference_index) + sizeof(channelcount) +
1303  sizeof(samplesize) + sizeof(samplerate) + sinf.ComputeSize() +
1304  esds.ComputeSize() + ddts.ComputeSize() + 6 +
1305  8 + // 6 + 8 bytes reserved.
1306  4; // 4 bytes predefined.
1307 }
1308 
1309 WebVTTConfigurationBox::WebVTTConfigurationBox() {}
1310 WebVTTConfigurationBox::~WebVTTConfigurationBox() {}
1311 
1313  return FOURCC_vttC;
1314 }
1315 
1316 bool WebVTTConfigurationBox::ReadWriteInternal(BoxBuffer* buffer) {
1317  RCHECK(ReadWriteHeaderInternal(buffer));
1318  return buffer->ReadWriteString(
1319  &config,
1320  buffer->Reading() ? buffer->BytesLeft() : config.size());
1321 }
1322 
1323 uint32_t WebVTTConfigurationBox::ComputeSizeInternal() {
1324  return HeaderSize() + config.size();
1325 }
1326 
1327 WebVTTSourceLabelBox::WebVTTSourceLabelBox() {}
1328 WebVTTSourceLabelBox::~WebVTTSourceLabelBox() {}
1329 
1331  return FOURCC_vlab;
1332 }
1333 
1334 bool WebVTTSourceLabelBox::ReadWriteInternal(BoxBuffer* buffer) {
1335  RCHECK(ReadWriteHeaderInternal(buffer));
1336  return buffer->ReadWriteString(&source_label, buffer->Reading()
1337  ? buffer->BytesLeft()
1338  : source_label.size());
1339 }
1340 
1341 uint32_t WebVTTSourceLabelBox::ComputeSizeInternal() {
1342  if (source_label.empty())
1343  return 0;
1344  return HeaderSize() + source_label.size();
1345 }
1346 
1347 WVTTSampleEntry::WVTTSampleEntry() {}
1348 WVTTSampleEntry::~WVTTSampleEntry() {}
1349 
1351  return FOURCC_wvtt;
1352 }
1353 
1354 bool WVTTSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
1355  // TODO(rkuroiwa): Handle the optional MPEG4BitRateBox.
1356  RCHECK(ReadWriteHeaderInternal(buffer) &&
1357  buffer->IgnoreBytes(6) && // reserved for SampleEntry.
1358  buffer->ReadWriteUInt16(&data_reference_index) &&
1359  buffer->PrepareChildren() &&
1360  buffer->ReadWriteChild(&config) &&
1361  buffer->ReadWriteChild(&label));
1362  return true;
1363 }
1364 
1365 uint32_t WVTTSampleEntry::ComputeSizeInternal() {
1366  // 6 for the (anonymous) reserved bytes for SampleEntry class.
1367  return HeaderSize() + 6 + sizeof(data_reference_index) +
1368  config.ComputeSize() + label.ComputeSize();
1369 }
1370 
1371 MediaHeader::MediaHeader()
1372  : creation_time(0), modification_time(0), timescale(0), duration(0) {
1373  language[0] = 0;
1374 }
1375 MediaHeader::~MediaHeader() {}
1376 FourCC MediaHeader::BoxType() const { return FOURCC_MDHD; }
1377 
1378 bool MediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
1379  RCHECK(ReadWriteHeaderInternal(buffer));
1380 
1381  uint8_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
1382  RCHECK(buffer->ReadWriteUInt64NBytes(&creation_time, num_bytes) &&
1383  buffer->ReadWriteUInt64NBytes(&modification_time, num_bytes) &&
1384  buffer->ReadWriteUInt32(&timescale) &&
1385  buffer->ReadWriteUInt64NBytes(&duration, num_bytes));
1386 
1387  if (buffer->Reading()) {
1388  // Read language codes into temp first then use BitReader to read the
1389  // values. ISO-639-2/T language code: unsigned int(5)[3] language (2 bytes).
1390  std::vector<uint8_t> temp;
1391  RCHECK(buffer->ReadWriteVector(&temp, 2));
1392 
1393  BitReader bit_reader(&temp[0], 2);
1394  bit_reader.SkipBits(1);
1395  for (int i = 0; i < 3; ++i) {
1396  CHECK(bit_reader.ReadBits(5, &language[i]));
1397  language[i] += 0x60;
1398  }
1399  language[3] = '\0';
1400  } else {
1401  // Set up default language if it is not set.
1402  const char kUndefinedLanguage[] = "und";
1403  if (language[0] == 0)
1404  strcpy(language, kUndefinedLanguage);
1405 
1406  // Lang format: bit(1) pad, unsigned int(5)[3] language.
1407  uint16_t lang = 0;
1408  for (int i = 0; i < 3; ++i)
1409  lang |= (language[i] - 0x60) << ((2 - i) * 5);
1410  RCHECK(buffer->ReadWriteUInt16(&lang));
1411  }
1412 
1413  RCHECK(buffer->IgnoreBytes(2)); // predefined.
1414  return true;
1415 }
1416 
1417 uint32_t MediaHeader::ComputeSizeInternal() {
1418  version = IsFitIn32Bits(creation_time, modification_time, duration) ? 0 : 1;
1419  return HeaderSize() + sizeof(timescale) +
1420  sizeof(uint32_t) * (1 + version) * 3 + 2 + // 2 bytes language.
1421  2; // 2 bytes predefined.
1422 }
1423 
1424 VideoMediaHeader::VideoMediaHeader()
1425  : graphicsmode(0), opcolor_red(0), opcolor_green(0), opcolor_blue(0) {
1426  const uint32_t kVideoMediaHeaderFlags = 1;
1427  flags = kVideoMediaHeaderFlags;
1428 }
1429 VideoMediaHeader::~VideoMediaHeader() {}
1430 FourCC VideoMediaHeader::BoxType() const { return FOURCC_VMHD; }
1431 bool VideoMediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
1432  RCHECK(ReadWriteHeaderInternal(buffer) &&
1433  buffer->ReadWriteUInt16(&graphicsmode) &&
1434  buffer->ReadWriteUInt16(&opcolor_red) &&
1435  buffer->ReadWriteUInt16(&opcolor_green) &&
1436  buffer->ReadWriteUInt16(&opcolor_blue));
1437  return true;
1438 }
1439 
1440 uint32_t VideoMediaHeader::ComputeSizeInternal() {
1441  return HeaderSize() + sizeof(graphicsmode) + sizeof(opcolor_red) +
1442  sizeof(opcolor_green) + sizeof(opcolor_blue);
1443 }
1444 
1445 SoundMediaHeader::SoundMediaHeader() : balance(0) {}
1446 SoundMediaHeader::~SoundMediaHeader() {}
1447 FourCC SoundMediaHeader::BoxType() const { return FOURCC_SMHD; }
1448 bool SoundMediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
1449  RCHECK(ReadWriteHeaderInternal(buffer) &&
1450  buffer->ReadWriteUInt16(&balance) &&
1451  buffer->IgnoreBytes(2)); // reserved.
1452  return true;
1453 }
1454 
1455 uint32_t SoundMediaHeader::ComputeSizeInternal() {
1456  return HeaderSize() + sizeof(balance) + sizeof(uint16_t);
1457 }
1458 
1459 SubtitleMediaHeader::SubtitleMediaHeader() {}
1460 SubtitleMediaHeader::~SubtitleMediaHeader() {}
1461 
1462 FourCC SubtitleMediaHeader::BoxType() const { return FOURCC_sthd; }
1463 
1464 bool SubtitleMediaHeader::ReadWriteInternal(BoxBuffer* buffer) {
1465  return ReadWriteHeaderInternal(buffer);
1466 }
1467 
1468 uint32_t SubtitleMediaHeader::ComputeSizeInternal() {
1469  return HeaderSize();
1470 }
1471 
1472 DataEntryUrl::DataEntryUrl() {
1473  const uint32_t kDataEntryUrlFlags = 1;
1474  flags = kDataEntryUrlFlags;
1475 }
1476 DataEntryUrl::~DataEntryUrl() {}
1477 FourCC DataEntryUrl::BoxType() const { return FOURCC_URL; }
1478 bool DataEntryUrl::ReadWriteInternal(BoxBuffer* buffer) {
1479  RCHECK(ReadWriteHeaderInternal(buffer));
1480  if (buffer->Reading()) {
1481  RCHECK(buffer->ReadWriteVector(&location, buffer->Size() - buffer->Pos()));
1482  } else {
1483  RCHECK(buffer->ReadWriteVector(&location, location.size()));
1484  }
1485  return true;
1486 }
1487 
1488 uint32_t DataEntryUrl::ComputeSizeInternal() {
1489  return HeaderSize() + location.size();
1490 }
1491 
1492 DataReference::DataReference() {
1493  // Default 1 entry.
1494  data_entry.resize(1);
1495 }
1496 DataReference::~DataReference() {}
1497 FourCC DataReference::BoxType() const { return FOURCC_DREF; }
1498 bool DataReference::ReadWriteInternal(BoxBuffer* buffer) {
1499  uint32_t entry_count = data_entry.size();
1500  RCHECK(ReadWriteHeaderInternal(buffer) &&
1501  buffer->ReadWriteUInt32(&entry_count));
1502  data_entry.resize(entry_count);
1503  RCHECK(buffer->PrepareChildren());
1504  for (uint32_t i = 0; i < entry_count; ++i)
1505  RCHECK(buffer->ReadWriteChild(&data_entry[i]));
1506  return true;
1507 }
1508 
1509 uint32_t DataReference::ComputeSizeInternal() {
1510  uint32_t count = data_entry.size();
1511  uint32_t box_size = HeaderSize() + sizeof(count);
1512  for (uint32_t i = 0; i < count; ++i)
1513  box_size += data_entry[i].ComputeSize();
1514  return box_size;
1515 }
1516 
1517 DataInformation::DataInformation() {}
1518 DataInformation::~DataInformation() {}
1519 FourCC DataInformation::BoxType() const { return FOURCC_DINF; }
1520 
1521 bool DataInformation::ReadWriteInternal(BoxBuffer* buffer) {
1522  return ReadWriteHeaderInternal(buffer) &&
1523  buffer->PrepareChildren() &&
1524  buffer->ReadWriteChild(&dref);
1525 }
1526 
1527 uint32_t DataInformation::ComputeSizeInternal() {
1528  return HeaderSize() + dref.ComputeSize();
1529 }
1530 
1531 MediaInformation::MediaInformation() {}
1532 MediaInformation::~MediaInformation() {}
1533 FourCC MediaInformation::BoxType() const { return FOURCC_MINF; }
1534 
1535 bool MediaInformation::ReadWriteInternal(BoxBuffer* buffer) {
1536  RCHECK(ReadWriteHeaderInternal(buffer) &&
1537  buffer->PrepareChildren() &&
1538  buffer->ReadWriteChild(&dinf) &&
1539  buffer->ReadWriteChild(&sample_table));
1540  switch (sample_table.description.type) {
1541  case kVideo:
1542  RCHECK(buffer->ReadWriteChild(&vmhd));
1543  break;
1544  case kAudio:
1545  RCHECK(buffer->ReadWriteChild(&smhd));
1546  break;
1547  case kText:
1548  RCHECK(buffer->ReadWriteChild(&sthd));
1549  break;
1550  default:
1551  NOTIMPLEMENTED();
1552  }
1553  // Hint is not supported for now.
1554  return true;
1555 }
1556 
1557 uint32_t MediaInformation::ComputeSizeInternal() {
1558  uint32_t box_size =
1559  HeaderSize() + dinf.ComputeSize() + sample_table.ComputeSize();
1560  switch (sample_table.description.type) {
1561  case kVideo:
1562  box_size += vmhd.ComputeSize();
1563  break;
1564  case kAudio:
1565  box_size += smhd.ComputeSize();
1566  break;
1567  case kText:
1568  box_size += sthd.ComputeSize();
1569  break;
1570  default:
1571  NOTIMPLEMENTED();
1572  }
1573  return box_size;
1574 }
1575 
1576 Media::Media() {}
1577 Media::~Media() {}
1578 FourCC Media::BoxType() const { return FOURCC_MDIA; }
1579 
1580 bool Media::ReadWriteInternal(BoxBuffer* buffer) {
1581  RCHECK(ReadWriteHeaderInternal(buffer) &&
1582  buffer->PrepareChildren() &&
1583  buffer->ReadWriteChild(&header) &&
1584  buffer->ReadWriteChild(&handler));
1585  if (buffer->Reading()) {
1586  // Maddeningly, the HandlerReference box specifies how to parse the
1587  // SampleDescription box, making the latter the only box (of those that we
1588  // support) which cannot be parsed correctly on its own (or even with
1589  // information from its strict ancestor tree). We thus copy the handler type
1590  // to the sample description box *before* parsing it to provide this
1591  // information while parsing.
1592  information.sample_table.description.type = handler.type;
1593  } else {
1594  DCHECK_EQ(information.sample_table.description.type, handler.type);
1595  }
1596  RCHECK(buffer->ReadWriteChild(&information));
1597  return true;
1598 }
1599 
1600 uint32_t Media::ComputeSizeInternal() {
1601  return HeaderSize() + header.ComputeSize() + handler.ComputeSize() +
1602  information.ComputeSize();
1603 }
1604 
1605 Track::Track() {}
1606 Track::~Track() {}
1607 FourCC Track::BoxType() const { return FOURCC_TRAK; }
1608 
1609 bool Track::ReadWriteInternal(BoxBuffer* buffer) {
1610  RCHECK(ReadWriteHeaderInternal(buffer) &&
1611  buffer->PrepareChildren() &&
1612  buffer->ReadWriteChild(&header) &&
1613  buffer->ReadWriteChild(&media) &&
1614  buffer->TryReadWriteChild(&edit) &&
1615  buffer->TryReadWriteChild(&sample_encryption));
1616  return true;
1617 }
1618 
1619 uint32_t Track::ComputeSizeInternal() {
1620  return HeaderSize() + header.ComputeSize() + media.ComputeSize() +
1621  edit.ComputeSize();
1622 }
1623 
1624 MovieExtendsHeader::MovieExtendsHeader() : fragment_duration(0) {}
1625 MovieExtendsHeader::~MovieExtendsHeader() {}
1626 FourCC MovieExtendsHeader::BoxType() const { return FOURCC_MEHD; }
1627 
1628 bool MovieExtendsHeader::ReadWriteInternal(BoxBuffer* buffer) {
1629  RCHECK(ReadWriteHeaderInternal(buffer));
1630  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
1631  RCHECK(buffer->ReadWriteUInt64NBytes(&fragment_duration, num_bytes));
1632  return true;
1633 }
1634 
1635 uint32_t MovieExtendsHeader::ComputeSizeInternal() {
1636  // This box is optional. Skip it if it is not used.
1637  if (fragment_duration == 0)
1638  return 0;
1639  version = IsFitIn32Bits(fragment_duration) ? 0 : 1;
1640  return HeaderSize() + sizeof(uint32_t) * (1 + version);
1641 }
1642 
1643 TrackExtends::TrackExtends()
1644  : track_id(0),
1645  default_sample_description_index(0),
1646  default_sample_duration(0),
1647  default_sample_size(0),
1648  default_sample_flags(0) {}
1649 TrackExtends::~TrackExtends() {}
1650 FourCC TrackExtends::BoxType() const { return FOURCC_TREX; }
1651 
1652 bool TrackExtends::ReadWriteInternal(BoxBuffer* buffer) {
1653  RCHECK(ReadWriteHeaderInternal(buffer) &&
1654  buffer->ReadWriteUInt32(&track_id) &&
1655  buffer->ReadWriteUInt32(&default_sample_description_index) &&
1656  buffer->ReadWriteUInt32(&default_sample_duration) &&
1657  buffer->ReadWriteUInt32(&default_sample_size) &&
1658  buffer->ReadWriteUInt32(&default_sample_flags));
1659  return true;
1660 }
1661 
1662 uint32_t TrackExtends::ComputeSizeInternal() {
1663  return HeaderSize() + sizeof(track_id) +
1664  sizeof(default_sample_description_index) +
1665  sizeof(default_sample_duration) + sizeof(default_sample_size) +
1666  sizeof(default_sample_flags);
1667 }
1668 
1669 MovieExtends::MovieExtends() {}
1670 MovieExtends::~MovieExtends() {}
1671 FourCC MovieExtends::BoxType() const { return FOURCC_MVEX; }
1672 
1673 bool MovieExtends::ReadWriteInternal(BoxBuffer* buffer) {
1674  RCHECK(ReadWriteHeaderInternal(buffer) &&
1675  buffer->PrepareChildren() &&
1676  buffer->TryReadWriteChild(&header));
1677  if (buffer->Reading()) {
1678  DCHECK(buffer->reader());
1679  RCHECK(buffer->reader()->ReadChildren(&tracks));
1680  } else {
1681  for (uint32_t i = 0; i < tracks.size(); ++i)
1682  RCHECK(buffer->ReadWriteChild(&tracks[i]));
1683  }
1684  return true;
1685 }
1686 
1687 uint32_t MovieExtends::ComputeSizeInternal() {
1688  // This box is optional. Skip it if it does not contain any track.
1689  if (tracks.size() == 0)
1690  return 0;
1691  uint32_t box_size = HeaderSize() + header.ComputeSize();
1692  for (uint32_t i = 0; i < tracks.size(); ++i)
1693  box_size += tracks[i].ComputeSize();
1694  return box_size;
1695 }
1696 
1697 Movie::Movie() {}
1698 Movie::~Movie() {}
1699 FourCC Movie::BoxType() const { return FOURCC_MOOV; }
1700 
1701 bool Movie::ReadWriteInternal(BoxBuffer* buffer) {
1702  RCHECK(ReadWriteHeaderInternal(buffer) &&
1703  buffer->PrepareChildren() &&
1704  buffer->ReadWriteChild(&header) &&
1705  buffer->TryReadWriteChild(&extends));
1706  if (buffer->Reading()) {
1707  BoxReader* reader = buffer->reader();
1708  DCHECK(reader);
1709  RCHECK(reader->ReadChildren(&tracks) &&
1710  reader->TryReadChildren(&pssh));
1711  } else {
1712  for (uint32_t i = 0; i < tracks.size(); ++i)
1713  RCHECK(buffer->ReadWriteChild(&tracks[i]));
1714  for (uint32_t i = 0; i < pssh.size(); ++i)
1715  RCHECK(buffer->ReadWriteChild(&pssh[i]));
1716  }
1717  return true;
1718 }
1719 
1720 uint32_t Movie::ComputeSizeInternal() {
1721  uint32_t box_size =
1722  HeaderSize() + header.ComputeSize() + extends.ComputeSize();
1723  for (uint32_t i = 0; i < tracks.size(); ++i)
1724  box_size += tracks[i].ComputeSize();
1725  for (uint32_t i = 0; i < pssh.size(); ++i)
1726  box_size += pssh[i].ComputeSize();
1727  return box_size;
1728 }
1729 
1730 TrackFragmentDecodeTime::TrackFragmentDecodeTime() : decode_time(0) {}
1731 TrackFragmentDecodeTime::~TrackFragmentDecodeTime() {}
1732 FourCC TrackFragmentDecodeTime::BoxType() const { return FOURCC_TFDT; }
1733 
1734 bool TrackFragmentDecodeTime::ReadWriteInternal(BoxBuffer* buffer) {
1735  RCHECK(ReadWriteHeaderInternal(buffer));
1736  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
1737  RCHECK(buffer->ReadWriteUInt64NBytes(&decode_time, num_bytes));
1738  return true;
1739 }
1740 
1741 uint32_t TrackFragmentDecodeTime::ComputeSizeInternal() {
1742  version = IsFitIn32Bits(decode_time) ? 0 : 1;
1743  return HeaderSize() + sizeof(uint32_t) * (1 + version);
1744 }
1745 
1746 MovieFragmentHeader::MovieFragmentHeader() : sequence_number(0) {}
1747 MovieFragmentHeader::~MovieFragmentHeader() {}
1748 FourCC MovieFragmentHeader::BoxType() const { return FOURCC_MFHD; }
1749 
1750 bool MovieFragmentHeader::ReadWriteInternal(BoxBuffer* buffer) {
1751  return ReadWriteHeaderInternal(buffer) &&
1752  buffer->ReadWriteUInt32(&sequence_number);
1753 }
1754 
1755 uint32_t MovieFragmentHeader::ComputeSizeInternal() {
1756  return HeaderSize() + sizeof(sequence_number);
1757 }
1758 
1759 TrackFragmentHeader::TrackFragmentHeader()
1760  : track_id(0),
1761  sample_description_index(0),
1762  default_sample_duration(0),
1763  default_sample_size(0),
1764  default_sample_flags(0) {}
1765 
1766 TrackFragmentHeader::~TrackFragmentHeader() {}
1767 FourCC TrackFragmentHeader::BoxType() const { return FOURCC_TFHD; }
1768 
1769 bool TrackFragmentHeader::ReadWriteInternal(BoxBuffer* buffer) {
1770  RCHECK(ReadWriteHeaderInternal(buffer) &&
1771  buffer->ReadWriteUInt32(&track_id));
1772 
1773  if (flags & kBaseDataOffsetPresentMask) {
1774  // MSE requires 'default-base-is-moof' to be set and
1775  // 'base-data-offset-present' not to be set. We omit these checks as some
1776  // valid files in the wild don't follow these rules, though they use moof as
1777  // base.
1778  uint64_t base_data_offset;
1779  RCHECK(buffer->ReadWriteUInt64(&base_data_offset));
1780  DLOG(WARNING) << "base-data-offset-present is not expected. Assumes "
1781  "default-base-is-moof.";
1782  }
1783 
1784  if (flags & kSampleDescriptionIndexPresentMask) {
1785  RCHECK(buffer->ReadWriteUInt32(&sample_description_index));
1786  } else if (buffer->Reading()) {
1787  sample_description_index = 0;
1788  }
1789 
1790  if (flags & kDefaultSampleDurationPresentMask) {
1791  RCHECK(buffer->ReadWriteUInt32(&default_sample_duration));
1792  } else if (buffer->Reading()) {
1793  default_sample_duration = 0;
1794  }
1795 
1796  if (flags & kDefaultSampleSizePresentMask) {
1797  RCHECK(buffer->ReadWriteUInt32(&default_sample_size));
1798  } else if (buffer->Reading()) {
1799  default_sample_size = 0;
1800  }
1801 
1802  if (flags & kDefaultSampleFlagsPresentMask)
1803  RCHECK(buffer->ReadWriteUInt32(&default_sample_flags));
1804  return true;
1805 }
1806 
1807 uint32_t TrackFragmentHeader::ComputeSizeInternal() {
1808  uint32_t box_size = HeaderSize() + sizeof(track_id);
1809  if (flags & kSampleDescriptionIndexPresentMask)
1810  box_size += sizeof(sample_description_index);
1811  if (flags & kDefaultSampleDurationPresentMask)
1812  box_size += sizeof(default_sample_duration);
1813  if (flags & kDefaultSampleSizePresentMask)
1814  box_size += sizeof(default_sample_size);
1815  if (flags & kDefaultSampleFlagsPresentMask)
1816  box_size += sizeof(default_sample_flags);
1817  return box_size;
1818 }
1819 
1820 TrackFragmentRun::TrackFragmentRun() : sample_count(0), data_offset(0) {}
1821 TrackFragmentRun::~TrackFragmentRun() {}
1822 FourCC TrackFragmentRun::BoxType() const { return FOURCC_TRUN; }
1823 
1824 bool TrackFragmentRun::ReadWriteInternal(BoxBuffer* buffer) {
1825  if (!buffer->Reading()) {
1826  // Determine whether version 0 or version 1 should be used.
1827  // Use version 0 if possible, use version 1 if there is a negative
1828  // sample_offset value.
1829  version = 0;
1830  if (flags & kSampleCompTimeOffsetsPresentMask) {
1831  for (uint32_t i = 0; i < sample_count; ++i) {
1832  if (sample_composition_time_offsets[i] < 0) {
1833  version = 1;
1834  break;
1835  }
1836  }
1837  }
1838  }
1839 
1840  RCHECK(ReadWriteHeaderInternal(buffer) &&
1841  buffer->ReadWriteUInt32(&sample_count));
1842 
1843  bool data_offset_present = (flags & kDataOffsetPresentMask) != 0;
1844  bool first_sample_flags_present = (flags & kFirstSampleFlagsPresentMask) != 0;
1845  bool sample_duration_present = (flags & kSampleDurationPresentMask) != 0;
1846  bool sample_size_present = (flags & kSampleSizePresentMask) != 0;
1847  bool sample_flags_present = (flags & kSampleFlagsPresentMask) != 0;
1848  bool sample_composition_time_offsets_present =
1849  (flags & kSampleCompTimeOffsetsPresentMask) != 0;
1850 
1851  if (data_offset_present) {
1852  RCHECK(buffer->ReadWriteUInt32(&data_offset));
1853  } else {
1854  // NOTE: If the data-offset is not present, then the data for this run
1855  // starts immediately after the data of the previous run, or at the
1856  // base-data-offset defined by the track fragment header if this is the
1857  // first run in a track fragment. If the data-offset is present, it is
1858  // relative to the base-data-offset established in the track fragment
1859  // header.
1860  NOTIMPLEMENTED();
1861  }
1862 
1863  uint32_t first_sample_flags;
1864 
1865  if (buffer->Reading()) {
1866  if (first_sample_flags_present)
1867  RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
1868 
1869  if (sample_duration_present)
1870  sample_durations.resize(sample_count);
1871  if (sample_size_present)
1872  sample_sizes.resize(sample_count);
1873  if (sample_flags_present)
1874  sample_flags.resize(sample_count);
1875  if (sample_composition_time_offsets_present)
1876  sample_composition_time_offsets.resize(sample_count);
1877  } else {
1878  if (first_sample_flags_present) {
1879  first_sample_flags = sample_flags[0];
1880  DCHECK(sample_flags.size() == 1);
1881  RCHECK(buffer->ReadWriteUInt32(&first_sample_flags));
1882  }
1883 
1884  if (sample_duration_present)
1885  DCHECK(sample_durations.size() == sample_count);
1886  if (sample_size_present)
1887  DCHECK(sample_sizes.size() == sample_count);
1888  if (sample_flags_present)
1889  DCHECK(sample_flags.size() == sample_count);
1890  if (sample_composition_time_offsets_present)
1891  DCHECK(sample_composition_time_offsets.size() == sample_count);
1892  }
1893 
1894  for (uint32_t i = 0; i < sample_count; ++i) {
1895  if (sample_duration_present)
1896  RCHECK(buffer->ReadWriteUInt32(&sample_durations[i]));
1897  if (sample_size_present)
1898  RCHECK(buffer->ReadWriteUInt32(&sample_sizes[i]));
1899  if (sample_flags_present)
1900  RCHECK(buffer->ReadWriteUInt32(&sample_flags[i]));
1901 
1902  if (sample_composition_time_offsets_present) {
1903  if (version == 0) {
1904  uint32_t sample_offset = sample_composition_time_offsets[i];
1905  RCHECK(buffer->ReadWriteUInt32(&sample_offset));
1906  sample_composition_time_offsets[i] = sample_offset;
1907  } else {
1908  int32_t sample_offset = sample_composition_time_offsets[i];
1909  RCHECK(buffer->ReadWriteInt32(&sample_offset));
1910  sample_composition_time_offsets[i] = sample_offset;
1911  }
1912  }
1913  }
1914 
1915  if (buffer->Reading()) {
1916  if (first_sample_flags_present) {
1917  if (sample_flags.size() == 0) {
1918  sample_flags.push_back(first_sample_flags);
1919  } else {
1920  sample_flags[0] = first_sample_flags;
1921  }
1922  }
1923  }
1924  return true;
1925 }
1926 
1927 uint32_t TrackFragmentRun::ComputeSizeInternal() {
1928  uint32_t box_size = HeaderSize() + sizeof(sample_count);
1929  if (flags & kDataOffsetPresentMask)
1930  box_size += sizeof(data_offset);
1931  if (flags & kFirstSampleFlagsPresentMask)
1932  box_size += sizeof(uint32_t);
1933  uint32_t fields = (flags & kSampleDurationPresentMask ? 1 : 0) +
1934  (flags & kSampleSizePresentMask ? 1 : 0) +
1935  (flags & kSampleFlagsPresentMask ? 1 : 0) +
1936  (flags & kSampleCompTimeOffsetsPresentMask ? 1 : 0);
1937  box_size += fields * sizeof(uint32_t) * sample_count;
1938  return box_size;
1939 }
1940 
1941 SampleToGroup::SampleToGroup() : grouping_type(0), grouping_type_parameter(0) {}
1942 SampleToGroup::~SampleToGroup() {}
1943 FourCC SampleToGroup::BoxType() const { return FOURCC_SBGP; }
1944 
1945 bool SampleToGroup::ReadWriteInternal(BoxBuffer* buffer) {
1946  RCHECK(ReadWriteHeaderInternal(buffer) &&
1947  buffer->ReadWriteUInt32(&grouping_type));
1948  if (version == 1)
1949  RCHECK(buffer->ReadWriteUInt32(&grouping_type_parameter));
1950 
1951  if (grouping_type != FOURCC_SEIG) {
1952  DCHECK(buffer->Reading());
1953  DLOG(WARNING) << "Sample group "
1954  << FourCCToString(static_cast<FourCC>(grouping_type))
1955  << " is not supported.";
1956  return true;
1957  }
1958 
1959  uint32_t count = entries.size();
1960  RCHECK(buffer->ReadWriteUInt32(&count));
1961  entries.resize(count);
1962  for (uint32_t i = 0; i < count; ++i) {
1963  RCHECK(buffer->ReadWriteUInt32(&entries[i].sample_count) &&
1964  buffer->ReadWriteUInt32(&entries[i].group_description_index));
1965  }
1966  return true;
1967 }
1968 
1969 uint32_t SampleToGroup::ComputeSizeInternal() {
1970  // This box is optional. Skip it if it is not used.
1971  if (entries.empty())
1972  return 0;
1973  return HeaderSize() + sizeof(grouping_type) +
1974  (version == 1 ? sizeof(grouping_type_parameter) : 0) +
1975  sizeof(uint32_t) + entries.size() * sizeof(entries[0]);
1976 }
1977 
1978 CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
1979  : is_encrypted(false), iv_size(0) {
1980 }
1981 CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() {};
1982 
1983 SampleGroupDescription::SampleGroupDescription() : grouping_type(0) {}
1984 SampleGroupDescription::~SampleGroupDescription() {}
1985 FourCC SampleGroupDescription::BoxType() const { return FOURCC_SGPD; }
1986 
1987 bool SampleGroupDescription::ReadWriteInternal(BoxBuffer* buffer) {
1988  RCHECK(ReadWriteHeaderInternal(buffer) &&
1989  buffer->ReadWriteUInt32(&grouping_type));
1990 
1991  if (grouping_type != FOURCC_SEIG) {
1992  DCHECK(buffer->Reading());
1993  DLOG(WARNING) << "Sample group '" << grouping_type << "' is not supported.";
1994  return true;
1995  }
1996 
1997  const size_t kEntrySize = sizeof(uint32_t) + kCencKeyIdSize;
1998  uint32_t default_length = 0;
1999  if (version == 1) {
2000  if (buffer->Reading()) {
2001  RCHECK(buffer->ReadWriteUInt32(&default_length));
2002  RCHECK(default_length == 0 || default_length >= kEntrySize);
2003  } else {
2004  default_length = kEntrySize;
2005  RCHECK(buffer->ReadWriteUInt32(&default_length));
2006  }
2007  }
2008 
2009  uint32_t count = entries.size();
2010  RCHECK(buffer->ReadWriteUInt32(&count));
2011  entries.resize(count);
2012  for (uint32_t i = 0; i < count; ++i) {
2013  if (version == 1) {
2014  if (buffer->Reading() && default_length == 0) {
2015  uint32_t description_length = 0;
2016  RCHECK(buffer->ReadWriteUInt32(&description_length));
2017  RCHECK(description_length >= kEntrySize);
2018  }
2019  }
2020 
2021  if (!buffer->Reading()) {
2022  if (entries[i].key_id.size() != kCencKeyIdSize) {
2023  LOG(WARNING) << "CENC defines key id length of " << kCencKeyIdSize
2024  << " bytes; got " << entries[i].key_id.size()
2025  << ". Resized accordingly.";
2026  entries[i].key_id.resize(kCencKeyIdSize);
2027  }
2028  }
2029 
2030  uint8_t flag = entries[i].is_encrypted ? 1 : 0;
2031  RCHECK(buffer->IgnoreBytes(2) && // reserved.
2032  buffer->ReadWriteUInt8(&flag) &&
2033  buffer->ReadWriteUInt8(&entries[i].iv_size) &&
2034  buffer->ReadWriteVector(&entries[i].key_id, kCencKeyIdSize));
2035 
2036  if (buffer->Reading()) {
2037  entries[i].is_encrypted = (flag != 0);
2038  if (entries[i].is_encrypted) {
2039  RCHECK(entries[i].iv_size == 8 || entries[i].iv_size == 16);
2040  } else {
2041  RCHECK(entries[i].iv_size == 0);
2042  }
2043  }
2044  }
2045  return true;
2046 }
2047 
2048 uint32_t SampleGroupDescription::ComputeSizeInternal() {
2049  // Version 0 is obsoleted, so always generate version 1 box.
2050  version = 1;
2051  // This box is optional. Skip it if it is not used.
2052  if (entries.empty())
2053  return 0;
2054  const size_t kEntrySize = sizeof(uint32_t) + kCencKeyIdSize;
2055  return HeaderSize() + sizeof(grouping_type) +
2056  (version == 1 ? sizeof(uint32_t) : 0) + sizeof(uint32_t) +
2057  entries.size() * kEntrySize;
2058 }
2059 
2060 TrackFragment::TrackFragment() : decode_time_absent(false) {}
2061 TrackFragment::~TrackFragment() {}
2062 FourCC TrackFragment::BoxType() const { return FOURCC_TRAF; }
2063 
2064 bool TrackFragment::ReadWriteInternal(BoxBuffer* buffer) {
2065  RCHECK(ReadWriteHeaderInternal(buffer) &&
2066  buffer->PrepareChildren() &&
2067  buffer->ReadWriteChild(&header));
2068  if (buffer->Reading()) {
2069  DCHECK(buffer->reader());
2070  decode_time_absent = !buffer->reader()->ChildExist(&decode_time);
2071  if (!decode_time_absent)
2072  RCHECK(buffer->ReadWriteChild(&decode_time));
2073  RCHECK(buffer->reader()->TryReadChildren(&runs));
2074 
2075  // There could be multiple SampleGroupDescription and SampleToGroup boxes
2076  // with different grouping types. For common encryption, the relevant
2077  // grouping type is 'seig'. Continue reading until 'seig' is found, or
2078  // until running out of child boxes.
2079  while (sample_to_group.grouping_type != FOURCC_SEIG &&
2080  buffer->reader()->ChildExist(&sample_to_group)) {
2081  RCHECK(buffer->reader()->ReadChild(&sample_to_group));
2082  }
2083  while (sample_group_description.grouping_type != FOURCC_SEIG &&
2084  buffer->reader()->ChildExist(&sample_group_description)) {
2085  RCHECK(buffer->reader()->ReadChild(&sample_group_description));
2086  }
2087  } else {
2088  if (!decode_time_absent)
2089  RCHECK(buffer->ReadWriteChild(&decode_time));
2090  for (uint32_t i = 0; i < runs.size(); ++i)
2091  RCHECK(buffer->ReadWriteChild(&runs[i]));
2092  RCHECK(buffer->TryReadWriteChild(&sample_to_group) &&
2093  buffer->TryReadWriteChild(&sample_group_description));
2094  }
2095  return buffer->TryReadWriteChild(&auxiliary_size) &&
2096  buffer->TryReadWriteChild(&auxiliary_offset) &&
2097  buffer->TryReadWriteChild(&sample_encryption);
2098 }
2099 
2100 uint32_t TrackFragment::ComputeSizeInternal() {
2101  uint32_t box_size =
2102  HeaderSize() + header.ComputeSize() + decode_time.ComputeSize() +
2103  sample_to_group.ComputeSize() + sample_group_description.ComputeSize() +
2104  auxiliary_size.ComputeSize() + auxiliary_offset.ComputeSize() +
2105  sample_encryption.ComputeSize();
2106  for (uint32_t i = 0; i < runs.size(); ++i)
2107  box_size += runs[i].ComputeSize();
2108  return box_size;
2109 }
2110 
2111 MovieFragment::MovieFragment() {}
2112 MovieFragment::~MovieFragment() {}
2113 FourCC MovieFragment::BoxType() const { return FOURCC_MOOF; }
2114 
2115 bool MovieFragment::ReadWriteInternal(BoxBuffer* buffer) {
2116  RCHECK(ReadWriteHeaderInternal(buffer) &&
2117  buffer->PrepareChildren() &&
2118  buffer->ReadWriteChild(&header));
2119  if (buffer->Reading()) {
2120  BoxReader* reader = buffer->reader();
2121  DCHECK(reader);
2122  RCHECK(reader->ReadChildren(&tracks) &&
2123  reader->TryReadChildren(&pssh));
2124  } else {
2125  for (uint32_t i = 0; i < tracks.size(); ++i)
2126  RCHECK(buffer->ReadWriteChild(&tracks[i]));
2127  for (uint32_t i = 0; i < pssh.size(); ++i)
2128  RCHECK(buffer->ReadWriteChild(&pssh[i]));
2129  }
2130  return true;
2131 }
2132 
2133 uint32_t MovieFragment::ComputeSizeInternal() {
2134  uint32_t box_size = HeaderSize() + header.ComputeSize();
2135  for (uint32_t i = 0; i < tracks.size(); ++i)
2136  box_size += tracks[i].ComputeSize();
2137  for (uint32_t i = 0; i < pssh.size(); ++i)
2138  box_size += pssh[i].ComputeSize();
2139  return box_size;
2140 }
2141 
2142 SegmentIndex::SegmentIndex()
2143  : reference_id(0),
2144  timescale(0),
2145  earliest_presentation_time(0),
2146  first_offset(0) {}
2147 SegmentIndex::~SegmentIndex() {}
2148 FourCC SegmentIndex::BoxType() const { return FOURCC_SIDX; }
2149 
2150 bool SegmentIndex::ReadWriteInternal(BoxBuffer* buffer) {
2151  RCHECK(ReadWriteHeaderInternal(buffer) &&
2152  buffer->ReadWriteUInt32(&reference_id) &&
2153  buffer->ReadWriteUInt32(&timescale));
2154 
2155  size_t num_bytes = (version == 1) ? sizeof(uint64_t) : sizeof(uint32_t);
2156  RCHECK(
2157  buffer->ReadWriteUInt64NBytes(&earliest_presentation_time, num_bytes) &&
2158  buffer->ReadWriteUInt64NBytes(&first_offset, num_bytes));
2159 
2160  uint16_t reference_count = references.size();
2161  RCHECK(buffer->IgnoreBytes(2) && // reserved.
2162  buffer->ReadWriteUInt16(&reference_count));
2163  references.resize(reference_count);
2164 
2165  uint32_t reference_type_size;
2166  uint32_t sap;
2167  for (uint32_t i = 0; i < reference_count; ++i) {
2168  if (!buffer->Reading()) {
2169  reference_type_size = references[i].referenced_size;
2170  if (references[i].reference_type)
2171  reference_type_size |= (1 << 31);
2172  sap = (references[i].sap_type << 28) | references[i].sap_delta_time;
2173  if (references[i].starts_with_sap)
2174  sap |= (1 << 31);
2175  }
2176  RCHECK(buffer->ReadWriteUInt32(&reference_type_size) &&
2177  buffer->ReadWriteUInt32(&references[i].subsegment_duration) &&
2178  buffer->ReadWriteUInt32(&sap));
2179  if (buffer->Reading()) {
2180  references[i].reference_type = (reference_type_size >> 31) ? true : false;
2181  references[i].referenced_size = reference_type_size & ~(1 << 31);
2182  references[i].starts_with_sap = (sap >> 31) ? true : false;
2183  references[i].sap_type =
2184  static_cast<SegmentReference::SAPType>((sap >> 28) & 0x07);
2185  references[i].sap_delta_time = sap & ~(0xF << 28);
2186  }
2187  }
2188  return true;
2189 }
2190 
2191 uint32_t SegmentIndex::ComputeSizeInternal() {
2192  version = IsFitIn32Bits(earliest_presentation_time, first_offset) ? 0 : 1;
2193  return HeaderSize() + sizeof(reference_id) + sizeof(timescale) +
2194  sizeof(uint32_t) * (1 + version) * 2 + 2 * sizeof(uint16_t) +
2195  3 * sizeof(uint32_t) * references.size();
2196 }
2197 
2198 MediaData::MediaData() : data_size(0) {}
2199 MediaData::~MediaData() {}
2200 FourCC MediaData::BoxType() const { return FOURCC_MDAT; }
2201 
2202 bool MediaData::ReadWriteInternal(BoxBuffer* buffer) {
2203  NOTIMPLEMENTED() << "Actual data is parsed and written separately.";
2204  return false;
2205 }
2206 
2207 uint32_t MediaData::ComputeSizeInternal() {
2208  return HeaderSize() + data_size;
2209 }
2210 
2211 CueSourceIDBox::CueSourceIDBox() : source_id(kCueSourceIdNotSet) {}
2212 CueSourceIDBox::~CueSourceIDBox() {}
2213 
2214 FourCC CueSourceIDBox::BoxType() const { return FOURCC_vsid; }
2215 
2216 bool CueSourceIDBox::ReadWriteInternal(BoxBuffer* buffer) {
2217  RCHECK(ReadWriteHeaderInternal(buffer) && buffer->ReadWriteInt32(&source_id));
2218  return true;
2219 }
2220 
2221 uint32_t CueSourceIDBox::ComputeSizeInternal() {
2222  if (source_id == kCueSourceIdNotSet)
2223  return 0;
2224  return HeaderSize() + sizeof(source_id);
2225 }
2226 
2227 CueTimeBox::CueTimeBox() {}
2228 CueTimeBox::~CueTimeBox() {}
2229 
2230 FourCC CueTimeBox::BoxType() const {
2231  return FOURCC_ctim;
2232 }
2233 
2234 bool CueTimeBox::ReadWriteInternal(BoxBuffer* buffer) {
2235  RCHECK(ReadWriteHeaderInternal(buffer));
2236  return buffer->ReadWriteString(
2237  &cue_current_time,
2238  buffer->Reading() ? buffer->BytesLeft() : cue_current_time.size());
2239 }
2240 
2241 uint32_t CueTimeBox::ComputeSizeInternal() {
2242  if (cue_current_time.empty())
2243  return 0;
2244  return HeaderSize() + cue_current_time.size();
2245 }
2246 
2247 CueIDBox::CueIDBox() {}
2248 CueIDBox::~CueIDBox() {}
2249 
2250 FourCC CueIDBox::BoxType() const {
2251  return FOURCC_iden;
2252 }
2253 
2254 bool CueIDBox::ReadWriteInternal(BoxBuffer* buffer) {
2255  RCHECK(ReadWriteHeaderInternal(buffer));
2256  return buffer->ReadWriteString(
2257  &cue_id, buffer->Reading() ? buffer->BytesLeft() : cue_id.size());
2258 }
2259 
2260 uint32_t CueIDBox::ComputeSizeInternal() {
2261  if (cue_id.empty())
2262  return 0;
2263  return HeaderSize() + cue_id.size();
2264 }
2265 
2266 CueSettingsBox::CueSettingsBox() {}
2267 CueSettingsBox::~CueSettingsBox() {}
2268 
2269 FourCC CueSettingsBox::BoxType() const {
2270  return FOURCC_sttg;
2271 }
2272 
2273 bool CueSettingsBox::ReadWriteInternal(BoxBuffer* buffer) {
2274  RCHECK(ReadWriteHeaderInternal(buffer));
2275  return buffer->ReadWriteString(
2276  &settings, buffer->Reading() ? buffer->BytesLeft() : settings.size());
2277 }
2278 
2279 uint32_t CueSettingsBox::ComputeSizeInternal() {
2280  if (settings.empty())
2281  return 0;
2282  return HeaderSize() + settings.size();
2283 }
2284 
2285 CuePayloadBox::CuePayloadBox() {}
2286 CuePayloadBox::~CuePayloadBox() {}
2287 
2288 FourCC CuePayloadBox::BoxType() const {
2289  return FOURCC_payl;
2290 }
2291 
2292 bool CuePayloadBox::ReadWriteInternal(BoxBuffer* buffer) {
2293  RCHECK(ReadWriteHeaderInternal(buffer));
2294  return buffer->ReadWriteString(
2295  &cue_text, buffer->Reading() ? buffer->BytesLeft() : cue_text.size());
2296 }
2297 
2298 uint32_t CuePayloadBox::ComputeSizeInternal() {
2299  return HeaderSize() + cue_text.size();
2300 }
2301 
2302 VTTEmptyCueBox::VTTEmptyCueBox() {}
2303 VTTEmptyCueBox::~VTTEmptyCueBox() {}
2304 
2305 FourCC VTTEmptyCueBox::BoxType() const {
2306  return FOURCC_vtte;
2307 }
2308 
2309 bool VTTEmptyCueBox::ReadWriteInternal(BoxBuffer* buffer) {
2310  return ReadWriteHeaderInternal(buffer);
2311 }
2312 
2313 uint32_t VTTEmptyCueBox::ComputeSizeInternal() {
2314  return HeaderSize();
2315 }
2316 
2317 VTTAdditionalTextBox::VTTAdditionalTextBox() {}
2318 VTTAdditionalTextBox::~VTTAdditionalTextBox() {}
2319 
2321  return FOURCC_vtta;
2322 }
2323 
2324 bool VTTAdditionalTextBox::ReadWriteInternal(BoxBuffer* buffer) {
2325  RCHECK(ReadWriteHeaderInternal(buffer));
2326  return buffer->ReadWriteString(
2327  &cue_additional_text,
2328  buffer->Reading() ? buffer->BytesLeft() : cue_additional_text.size());
2329 }
2330 
2331 uint32_t VTTAdditionalTextBox::ComputeSizeInternal() {
2332  return HeaderSize() + cue_additional_text.size();
2333 }
2334 
2335 VTTCueBox::VTTCueBox() {}
2336 VTTCueBox::~VTTCueBox() {}
2337 
2338 FourCC VTTCueBox::BoxType() const {
2339  return FOURCC_vttc;
2340 }
2341 
2342 bool VTTCueBox::ReadWriteInternal(BoxBuffer* buffer) {
2343  RCHECK(ReadWriteHeaderInternal(buffer) &&
2344  buffer->PrepareChildren() &&
2345  buffer->ReadWriteChild(&cue_source_id) &&
2346  buffer->ReadWriteChild(&cue_id) &&
2347  buffer->ReadWriteChild(&cue_time) &&
2348  buffer->ReadWriteChild(&cue_settings) &&
2349  buffer->ReadWriteChild(&cue_payload));
2350  return true;
2351 }
2352 
2353 uint32_t VTTCueBox::ComputeSizeInternal() {
2354  return HeaderSize() + cue_source_id.ComputeSize() + cue_id.ComputeSize() +
2355  cue_time.ComputeSize() + cue_settings.ComputeSize() +
2356  cue_payload.ComputeSize();
2357 }
2358 
2359 } // namespace mp4
2360 } // namespace media
2361 } // namespace edash_packager
FourCC BoxType() const override
bool ReadChildren(std::vector< T > *children) WARN_UNUSED_RESULT
Definition: box_reader.h:133
bool ReadChild(Box *child) WARN_UNUSED_RESULT
Definition: box_reader.cc:123
virtual bool ReadWriteHeaderInternal(BoxBuffer *buffer)
Definition: box.cc:60
bool ReadWriteHeaderInternal(BoxBuffer *buffer) final
Definition: box.cc:79
bool ParseFromSampleEncryptionData(size_t iv_size, std::vector< SampleEncryptionEntry > *sample_encryption_entries) const
bool ChildExist(Box *child) WARN_UNUSED_RESULT
Definition: box_reader.cc:136
bool ReadWriteUInt64NBytes(uint64_t *v, size_t num_bytes)
Definition: box_buffer.h:117
bool ReadWriteString(std::string *str, size_t size)
Definition: box_buffer.h:139
bool IgnoreBytes(size_t num_bytes)
Definition: box_buffer.h:189
A class to read bit streams.
Definition: bit_reader.h:17
virtual uint32_t HeaderSize() const
Definition: box.cc:54
void Write(BufferWriter *writer)
Definition: box.cc:25
bool ParseFromBuffer(uint8_t iv_size, bool has_subsamples, BufferReader *reader)
bool TryReadChildren(std::vector< T > *children) WARN_UNUSED_RESULT
Definition: box_reader.h:139
Class for reading MP4 boxes.
Definition: box_reader.h:24
bool ReadWrite(uint8_t iv_size, bool has_subsamples, BoxBuffer *buffer)
uint32_t HeaderSize() const final
Definition: box.cc:74