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