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