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