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