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