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