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