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