15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/mp4/track_run_iterator.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/buffers.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/formats/mp4/rcheck.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "media/formats/mp4/sample_to_group_iterator.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace mp4 {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SampleInfo {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int duration;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cts_offset;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_keyframe;
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool is_random_access_point;
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  uint32 cenc_group_description_index;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TrackRunInfo {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 track_id;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SampleInfo> samples;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 timescale;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 start_dts;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 sample_start_offset;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_audio;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const AudioSampleEntry* audio_description;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VideoSampleEntry* video_description;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 aux_info_start_offset;  // Only valid if aux_info_total_size > 0.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int aux_info_default_size;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8> aux_info_sizes;  // Populated if default_size == 0.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int aux_info_total_size;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::vector<CencSampleEncryptionInfoEntry> sample_encryption_info;
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrackRunInfo();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~TrackRunInfo();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TrackRunInfo::TrackRunInfo()
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : track_id(0),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timescale(-1),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_dts(-1),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sample_start_offset(-1),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_audio(false),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aux_info_start_offset(-1),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aux_info_default_size(-1),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aux_info_total_size(-1) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TrackRunInfo::~TrackRunInfo() {}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::TimeDelta TimeDeltaFromRational(int64 numer, int64 denom) {
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // To avoid overflow, split the following calculation:
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (numer * base::Time::kMicrosecondsPerSecond) / denom
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // into:
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //  (numer / denom) * base::Time::kMicrosecondsPerSecond +
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // ((numer % denom) * base::Time::kMicrosecondsPerSecond) / denom
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 a = numer / denom;
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_LE((a > 0 ? a : -a), kint64max / base::Time::kMicrosecondsPerSecond);
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 timea_in_us = a * base::Time::kMicrosecondsPerSecond;
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 b = numer % denom;
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_LE((b > 0 ? b : -b), kint64max / base::Time::kMicrosecondsPerSecond);
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int64 timeb_in_us = (b * base::Time::kMicrosecondsPerSecond) / denom;
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK((timeb_in_us < 0) || (timea_in_us <= kint64max - timeb_in_us));
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK((timeb_in_us > 0) || (timea_in_us >= kint64min - timeb_in_us));
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return base::TimeDelta::FromMicroseconds(timea_in_us + timeb_in_us);
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)DecodeTimestamp DecodeTimestampFromRational(int64 numer, int64 denom) {
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return DecodeTimestamp::FromPresentationTime(
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      TimeDeltaFromRational(numer, denom));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TrackRunIterator::TrackRunIterator(const Movie* moov,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const LogCB& log_cb)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : moov_(moov), log_cb_(log_cb), sample_offset_(0) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(moov);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TrackRunIterator::~TrackRunIterator() {}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic bool PopulateSampleInfo(const TrackExtends& trex,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const TrackFragmentHeader& tfhd,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const TrackFragmentRun& trun,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const int64 edit_list_offset,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const uint32 i,
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                               SampleInfo* sample_info,
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const SampleDependsOn sdtp_sample_depends_on,
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const LogCB& log_cb) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i < trun.sample_sizes.size()) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->size = trun.sample_sizes[i];
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (tfhd.default_sample_size > 0) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->size = tfhd.default_sample_size;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->size = trex.default_sample_size;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i < trun.sample_durations.size()) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->duration = trun.sample_durations[i];
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (tfhd.default_sample_duration > 0) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->duration = tfhd.default_sample_duration;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->duration = trex.default_sample_duration;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i < trun.sample_composition_time_offsets.size()) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->cts_offset = trun.sample_composition_time_offsets[i];
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_info->cts_offset = 0;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sample_info->cts_offset += edit_list_offset;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 flags;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i < trun.sample_flags.size()) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags = trun.sample_flags[i];
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (tfhd.has_default_sample_flags) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags = tfhd.default_sample_flags;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags = trex.default_sample_flags;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SampleDependsOn sample_depends_on =
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<SampleDependsOn>((flags >> 24) & 0x3);
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (sample_depends_on == kSampleDependsOnUnknown)
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    sample_depends_on = sdtp_sample_depends_on;
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // ISO/IEC 14496-12  Section 8.8.3.1 : The negation of |sample_is_sync_sample|
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // provides the same information as the sync sample table [8.6.2]. When
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // |sample_is_sync_sample| is true for a sample, it is the same as if the
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // sample were not in a movie fragment and marked with an entry in the sync
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // sample table (or, if all samples are sync samples, the sync sample table
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // were absent).
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool sample_is_sync_sample = !(flags & kSampleIsNonSyncSample);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sample_info->is_random_access_point = sample_is_sync_sample;
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (sample_depends_on) {
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case kSampleDependsOnUnknown:
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sample_info->is_keyframe = sample_is_sync_sample;
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case kSampleDependsOnOthers:
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      sample_info->is_keyframe = false;
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case kSampleDependsOnNoOther:
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      sample_info->is_keyframe = true;
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case kSampleDependsOnReserved:
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MEDIA_LOG(log_cb) << "Reserved value used in sample dependency info.";
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In well-structured encrypted media, each track run will be immediately
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// preceded by its auxiliary information; this is the only optimal storage
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pattern in terms of minimum number of bytes from a serial stream needed to
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// begin playback. It also allows us to optimize caching on memory-constrained
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// architectures, because we can cache the relatively small auxiliary
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// information for an entire run and then discard data from the input stream,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instead of retaining the entire 'mdat' box.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We optimize for this situation (with no loss of generality) by sorting track
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// runs during iteration in order of their first data offset (either sample data
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or auxiliary data).
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CompareMinTrackRunDataOffset {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const TrackRunInfo& a, const TrackRunInfo& b) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 a_aux = a.aux_info_total_size ? a.aux_info_start_offset : kint64max;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 b_aux = b.aux_info_total_size ? b.aux_info_start_offset : kint64max;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 a_lesser = std::min(a_aux, a.sample_start_offset);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 a_greater = std::max(a_aux, a.sample_start_offset);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 b_lesser = std::min(b_aux, b.sample_start_offset);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 b_greater = std::max(b_aux, b.sample_start_offset);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (a_lesser == b_lesser) return a_greater < b_greater;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a_lesser < b_lesser;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::Init(const MovieFragment& moof) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  runs_.clear();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < moof.tracks.size(); i++) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TrackFragment& traf = moof.tracks[i];
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Track* trak = NULL;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t t = 0; t < moov_->tracks.size(); t++) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (moov_->tracks[t].header.track_id == traf.header.track_id)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trak = &moov_->tracks[t];
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RCHECK(trak);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TrackExtends* trex = NULL;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t t = 0; t < moov_->extends.tracks.size(); t++) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (moov_->extends.tracks[t].track_id == traf.header.track_id)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trex = &moov_->extends.tracks[t];
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RCHECK(trex);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SampleDescription& stsd =
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trak->media.information.sample_table.description;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stsd.type != kAudio && stsd.type != kVideo) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Skipping unhandled track type";
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t desc_idx = traf.header.sample_description_index;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!desc_idx) desc_idx = trex->default_sample_description_index;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RCHECK(desc_idx > 0);  // Descriptions are one-indexed in the file
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    desc_idx -= 1;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Process edit list to remove CTS offset introduced in the presence of
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // B-frames (those that contain a single edit with a nonnegative media
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // time). Other uses of edit lists are not supported, as they are
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // both uncommon and better served by higher-level protocols.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 edit_list_offset = 0;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<EditListEntry>& edits = trak->edit.list.edits;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!edits.empty()) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (edits.size() > 1)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "Multi-entry edit box detected; some components ignored.";
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (edits[0].media_time < 0) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "Empty edit list entry ignored.";
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        edit_list_offset = -edits[0].media_time;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SampleToGroupIterator sample_to_group_itr(traf.sample_to_group);
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool is_sample_to_group_valid = sample_to_group_itr.IsValid();
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 run_start_dts = traf.decode_time.decode_time;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sample_count_sum = 0;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < traf.runs.size(); j++) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const TrackFragmentRun& trun = traf.runs[j];
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TrackRunInfo tri;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tri.track_id = traf.header.track_id;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tri.timescale = trak->media.header.timescale;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tri.start_dts = run_start_dts;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tri.sample_start_offset = trun.data_offset;
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      tri.sample_encryption_info = traf.sample_group_description.entries;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tri.is_audio = (stsd.type == kAudio);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (tri.is_audio) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RCHECK(!stsd.audio_entries.empty());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (desc_idx > stsd.audio_entries.size())
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          desc_idx = 0;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tri.audio_description = &stsd.audio_entries[desc_idx];
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RCHECK(!stsd.video_entries.empty());
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (desc_idx > stsd.video_entries.size())
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          desc_idx = 0;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tri.video_description = &stsd.video_entries[desc_idx];
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Collect information from the auxiliary_offset entry with the same index
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // in the 'saiz' container as the current run's index in the 'trun'
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // container, if it is present.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (traf.auxiliary_offset.offsets.size() > j) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // There should be an auxiliary info entry corresponding to each sample
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // in the auxiliary offset entry's corresponding track run.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RCHECK(traf.auxiliary_size.sample_count >=
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sample_count_sum + trun.sample_count);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tri.aux_info_start_offset = traf.auxiliary_offset.offsets[j];
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tri.aux_info_default_size =
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            traf.auxiliary_size.default_sample_info_size;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (tri.aux_info_default_size == 0) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const std::vector<uint8>& sizes =
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              traf.auxiliary_size.sample_info_sizes;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tri.aux_info_sizes.insert(tri.aux_info_sizes.begin(),
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              sizes.begin() + sample_count_sum,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              sizes.begin() + sample_count_sum + trun.sample_count);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If the default info size is positive, find the total size of the aux
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // info block from it, otherwise sum over the individual sizes of each
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // aux info entry in the aux_offset entry.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (tri.aux_info_default_size) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tri.aux_info_total_size =
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              tri.aux_info_default_size * trun.sample_count;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tri.aux_info_total_size = 0;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          for (size_t k = 0; k < trun.sample_count; k++) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tri.aux_info_total_size += tri.aux_info_sizes[k];
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tri.aux_info_start_offset = -1;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tri.aux_info_total_size = 0;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tri.samples.resize(trun.sample_count);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t k = 0; k < trun.sample_count; k++) {
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!PopulateSampleInfo(*trex, traf.header, trun, edit_list_offset,
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                k, &tri.samples[k],
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                traf.sdtp.sample_depends_on(k),
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                log_cb_)) {
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          return false;
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        run_start_dts += tri.samples[k].duration;
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (!is_sample_to_group_valid) {
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          // Set group description index to 0 to read encryption information
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          // from TrackEncryption Box.
318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          tri.samples[k].cenc_group_description_index = 0;
319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          continue;
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // ISO-14496-12 Section 8.9.2.3 and 8.9.4 : group description index
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // (1) ranges from 1 to the number of sample group entries in the track
324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // level SampleGroupDescription Box, or (2) takes the value 0 to
325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // indicate that this sample is a member of no group, in this case, the
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // sample is associated with the default values specified in
327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // TrackEncryption Box, or (3) starts at 0x10001, i.e. the index value
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // 1, with the value 1 in the top 16 bits, to reference fragment-local
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // SampleGroupDescription Box.
330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // Case (1) is not supported currently. We might not need it either as
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // the same functionality can be better achieved using (2).
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        uint32 index = sample_to_group_itr.group_description_index();
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (index >= SampleToGroupEntry::kFragmentGroupDescriptionIndexBase) {
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          index -= SampleToGroupEntry::kFragmentGroupDescriptionIndexBase;
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          RCHECK(index != 0 && index <= tri.sample_encryption_info.size());
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        } else if (index != 0) {
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          NOTIMPLEMENTED() << "'sgpd' box in 'moov' is not supported.";
338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          return false;
339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        }
340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        tri.samples[k].cenc_group_description_index = index;
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        is_sample_to_group_valid = sample_to_group_itr.Advance();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      runs_.push_back(tri);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sample_count_sum += trun.sample_count;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // We should have iterated through all samples in SampleToGroup Box.
348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    RCHECK(!sample_to_group_itr.IsValid());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(runs_.begin(), runs_.end(), CompareMinTrackRunDataOffset());
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_itr_ = runs_.begin();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetRun();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrackRunIterator::AdvanceRun() {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++run_itr_;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetRun();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrackRunIterator::ResetRun() {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsRunValid()) return;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sample_dts_ = run_itr_->start_dts;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sample_offset_ = run_itr_->sample_start_offset;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sample_itr_ = run_itr_->samples.begin();
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cenc_info_.clear();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TrackRunIterator::AdvanceSample() {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSampleValid());
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sample_dts_ += sample_itr_->duration;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sample_offset_ += sample_itr_->size;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++sample_itr_;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This implementation only indicates a need for caching if CENC auxiliary
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// info is available in the stream.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::AuxInfoNeedsToBeCached() {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsRunValid());
381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return aux_info_size() > 0 && cenc_info_.size() == 0;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This implementation currently only caches CENC auxiliary info.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::CacheAuxInfo(const uint8* buf, int buf_size) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RCHECK(AuxInfoNeedsToBeCached() && buf_size >= aux_info_size());
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cenc_info_.resize(run_itr_->samples.size());
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 pos = 0;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < run_itr_->samples.size(); i++) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int info_size = run_itr_->aux_info_default_size;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!info_size)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info_size = run_itr_->aux_info_sizes[i];
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (IsSampleEncrypted(i)) {
396010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      BufferReader reader(buf + pos, info_size);
397010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      RCHECK(cenc_info_[i].Parse(GetIvSize(i), &reader));
398010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos += info_size;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::IsRunValid() const {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run_itr_ != runs_.end();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::IsSampleValid() const {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsRunValid() && (sample_itr_ != run_itr_->samples.end());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because tracks are in sorted order and auxiliary information is cached when
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returning samples, it is guaranteed that no data will be required before the
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lesser of the minimum data offset of this track and the next in sequence.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (The stronger condition - that no data is required before the minimum data
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// offset of this track alone - is not guaranteed, because the BMFF spec does
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not have any inter-run ordering restrictions.)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 TrackRunIterator::GetMaxClearOffset() {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 offset = kint64max;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsSampleValid()) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset = std::min(offset, sample_offset_);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (AuxInfoNeedsToBeCached())
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offset = std::min(offset, aux_info_offset());
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (run_itr_ != runs_.end()) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<TrackRunInfo>::const_iterator next_run = run_itr_ + 1;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_run != runs_.end()) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offset = std::min(offset, next_run->sample_start_offset);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (next_run->aux_info_total_size)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        offset = std::min(offset, next_run->aux_info_start_offset);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset == kint64max) return 0;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return offset;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 TrackRunIterator::track_id() const {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsRunValid());
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run_itr_->track_id;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::is_encrypted() const {
445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(IsSampleValid());
446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return IsSampleEncrypted(sample_itr_ - run_itr_->samples.begin());
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 TrackRunIterator::aux_info_offset() const {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run_itr_->aux_info_start_offset;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TrackRunIterator::aux_info_size() const {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run_itr_->aux_info_total_size;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::is_audio() const {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsRunValid());
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run_itr_->is_audio;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const AudioSampleEntry& TrackRunIterator::audio_description() const {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_audio());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(run_itr_->audio_description);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *run_itr_->audio_description;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const VideoSampleEntry& TrackRunIterator::video_description() const {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_audio());
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(run_itr_->video_description);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *run_itr_->video_description;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 TrackRunIterator::sample_offset() const {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSampleValid());
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sample_offset_;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TrackRunIterator::sample_size() const {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSampleValid());
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sample_itr_->size;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)DecodeTimestamp TrackRunIterator::dts() const {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSampleValid());
4866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return DecodeTimestampFromRational(sample_dts_, run_itr_->timescale);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::TimeDelta TrackRunIterator::cts() const {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSampleValid());
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TimeDeltaFromRational(sample_dts_ + sample_itr_->cts_offset,
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               run_itr_->timescale);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::TimeDelta TrackRunIterator::duration() const {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSampleValid());
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TimeDeltaFromRational(sample_itr_->duration, run_itr_->timescale);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrackRunIterator::is_keyframe() const {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsSampleValid());
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sample_itr_->is_keyframe;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool TrackRunIterator::is_random_access_point() const {
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(IsSampleValid());
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return sample_itr_->is_random_access_point;
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const TrackEncryption& TrackRunIterator::track_encryption() const {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_audio())
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return audio_description().sinf.info.track_encryption;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return video_description().sinf.info.track_encryption;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
517010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(is_encrypted());
518010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
519010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (cenc_info_.empty()) {
520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK_EQ(0, aux_info_size());
521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "Aux Info is not available.";
522010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return scoped_ptr<DecryptConfig>();
523010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
524010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t sample_idx = sample_itr_ - run_itr_->samples.begin();
526010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_LT(sample_idx, cenc_info_.size());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FrameCENCInfo& cenc_info = cenc_info_[sample_idx];
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  size_t total_size = 0;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cenc_info.subsamples.empty() &&
531f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      (!cenc_info.GetTotalSizeOfSubsamples(&total_size) ||
532f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       total_size != static_cast<size_t>(sample_size()))) {
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MEDIA_LOG(log_cb_) << "Incorrect CENC subsample size.";
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scoped_ptr<DecryptConfig>();
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::vector<uint8>& kid = GetKeyId(sample_idx);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scoped_ptr<DecryptConfig>(new DecryptConfig(
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()),
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string(reinterpret_cast<const char*>(cenc_info.iv),
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  arraysize(cenc_info.iv)),
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cenc_info.subsamples));
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)uint32 TrackRunIterator::GetGroupDescriptionIndex(uint32 sample_index) const {
546010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(IsRunValid());
547010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_LT(sample_index, run_itr_->samples.size());
548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return run_itr_->samples[sample_index].cenc_group_description_index;
549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
550010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
551010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const CencSampleEncryptionInfoEntry&
552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TrackRunIterator::GetSampleEncryptionInfoEntry(
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint32 group_description_index) const {
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(IsRunValid());
555010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_NE(group_description_index, 0u);
556010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_LE(group_description_index, run_itr_->sample_encryption_info.size());
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // |group_description_index| is 1-based. Subtract by 1 to index the vector.
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return run_itr_->sample_encryption_info[group_description_index - 1];
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool TrackRunIterator::IsSampleEncrypted(size_t sample_index) const {
562010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  uint32 index = GetGroupDescriptionIndex(sample_index);
563010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return (index == 0) ? track_encryption().is_encrypted
564010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                      : GetSampleEncryptionInfoEntry(index).is_encrypted;
565010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
566010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
567010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const std::vector<uint8>& TrackRunIterator::GetKeyId(
568010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    size_t sample_index) const {
569010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  uint32 index = GetGroupDescriptionIndex(sample_index);
570010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return (index == 0) ? track_encryption().default_kid
571010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                      : GetSampleEncryptionInfoEntry(index).key_id;
572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
573010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
574010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)uint8 TrackRunIterator::GetIvSize(size_t sample_index) const {
575010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  uint32 index = GetGroupDescriptionIndex(sample_index);
576010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return (index == 0) ? track_encryption().default_iv_size
577010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                      : GetSampleEncryptionInfoEntry(index).iv_size;
578010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace mp4
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
582