Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/mp4/track_run_iterator.h" | 5 #include "media/mp4/track_run_iterator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "media/base/stream_parser_buffer.h" | 9 #include "media/base/stream_parser_buffer.h" |
| 10 #include "media/mp4/rcheck.h" | 10 #include "media/mp4/rcheck.h" |
| 11 | 11 |
| 12 namespace media { | 12 namespace media { |
| 13 namespace mp4 { | 13 namespace mp4 { |
| 14 | 14 |
| 15 base::TimeDelta TimeDeltaFromFrac(int64 numer, int64 denom) { | 15 struct SampleInfo { |
| 16 int size; | |
| 17 int duration; | |
| 18 int cts_offset; | |
| 19 bool is_keyframe; | |
| 20 }; | |
| 21 | |
| 22 struct TrackRunInfo { | |
| 23 uint32 track_id; | |
| 24 std::vector<SampleInfo> samples; | |
| 25 int64 timescale; | |
| 26 int64 start_dts; | |
| 27 int64 sample_start_offset; | |
| 28 | |
| 29 int64 aux_info_start_offset; // Only valid if aux_info_total_size > 0. | |
| 30 int aux_info_default_size; | |
| 31 std::vector<uint8> aux_info_sizes; // Present if default_size == 0. | |
|
ddorwin
2012/07/17 01:14:21
Present => Populated or Non-empty
strobe_
2012/07/19 02:43:35
Done.
| |
| 32 int aux_info_total_size; | |
| 33 | |
| 34 TrackEncryption track_encryption; | |
| 35 | |
| 36 TrackRunInfo(); | |
| 37 ~TrackRunInfo(); | |
| 38 }; | |
| 39 | |
| 40 TrackRunInfo::TrackRunInfo() | |
| 41 : track_id(0), | |
| 42 timescale(-1), | |
| 43 start_dts(-1), | |
| 44 sample_start_offset(-1), | |
| 45 aux_info_start_offset(-1), | |
| 46 aux_info_default_size(-1), | |
| 47 aux_info_total_size(-1) { | |
| 48 } | |
| 49 TrackRunInfo::~TrackRunInfo() {} | |
| 50 | |
| 51 TimeDelta TimeDeltaFromFrac(int64 numer, int64 denom) { | |
|
ddorwin
2012/07/17 01:14:21
Function and var names should usually be complete
ddorwin
2012/07/17 01:14:21
What does "FromFrac" mean? Isn't it really convert
strobe_
2012/07/19 02:43:35
The time base is referred to as the denominator el
| |
| 16 DCHECK_LT((numer > 0 ? numer : -numer), | 52 DCHECK_LT((numer > 0 ? numer : -numer), |
|
ddorwin
2012/07/17 01:14:21
use abs()?
strobe_
2012/07/19 02:43:35
Nope, breaks build on cros-tegra2.
| |
| 17 kint64max / base::Time::kMicrosecondsPerSecond); | 53 kint64max / base::Time::kMicrosecondsPerSecond); |
| 18 return base::TimeDelta::FromMicroseconds( | 54 return TimeDelta::FromMicroseconds( |
| 19 base::Time::kMicrosecondsPerSecond * numer / denom); | 55 base::Time::kMicrosecondsPerSecond * numer / denom); |
| 20 } | 56 } |
| 21 | 57 |
| 22 static const uint32 kSampleIsDifferenceSampleFlagMask = 0x10000; | 58 static const uint32 kSampleIsDifferenceSampleFlagMask = 0x10000; |
|
ddorwin
2012/07/17 01:14:21
file constant should be at the top of the file in
strobe_
2012/07/19 02:43:35
Done.
| |
| 23 | 59 |
| 24 TrackRunInfo::TrackRunInfo() | |
| 25 : track_id(0), | |
| 26 sample_start_offset(-1), | |
| 27 is_encrypted(false), | |
| 28 cenc_start_offset(-1), | |
| 29 cenc_total_size(-1), | |
| 30 default_cenc_size(0) {} | |
| 31 | |
| 32 TrackRunInfo::~TrackRunInfo() {} | |
| 33 | 60 |
| 34 TrackRunIterator::TrackRunIterator() : sample_offset_(0) {} | 61 TrackRunIterator::TrackRunIterator() : sample_offset_(0) {} |
| 35 TrackRunIterator::~TrackRunIterator() {} | 62 TrackRunIterator::~TrackRunIterator() {} |
| 36 | 63 |
| 37 static void PopulateSampleInfo(const Track& trak, | 64 static void PopulateSampleInfo(const TrackExtends& trex, |
| 38 const TrackExtends& trex, | |
| 39 const TrackFragmentHeader& tfhd, | 65 const TrackFragmentHeader& tfhd, |
| 40 const TrackFragmentRun& trun, | 66 const TrackFragmentRun& trun, |
| 41 const uint32 i, | 67 const uint32 i, |
| 42 SampleInfo* sample_info) { | 68 SampleInfo* sample_info) { |
| 43 if (i < trun.sample_sizes.size()) { | 69 if (i < trun.sample_sizes.size()) { |
| 44 sample_info->size = trun.sample_sizes[i]; | 70 sample_info->size = trun.sample_sizes[i]; |
| 45 } else if (tfhd.default_sample_size > 0) { | 71 } else if (tfhd.default_sample_size > 0) { |
| 46 sample_info->size = tfhd.default_sample_size; | 72 sample_info->size = tfhd.default_sample_size; |
| 47 } else { | 73 } else { |
| 48 sample_info->size = trex.default_sample_size; | 74 sample_info->size = trex.default_sample_size; |
| 49 } | 75 } |
| 50 | 76 |
| 51 const uint64 timescale = trak.media.header.timescale; | |
| 52 uint64 duration; | |
| 53 if (i < trun.sample_durations.size()) { | 77 if (i < trun.sample_durations.size()) { |
| 54 duration = trun.sample_durations[i]; | 78 sample_info->duration = trun.sample_durations[i]; |
| 55 } else if (tfhd.default_sample_duration > 0) { | 79 } else if (tfhd.default_sample_duration > 0) { |
| 56 duration = tfhd.default_sample_duration; | 80 sample_info->duration = tfhd.default_sample_duration; |
| 57 } else { | 81 } else { |
| 58 duration = trex.default_sample_duration; | 82 sample_info->duration = trex.default_sample_duration; |
| 59 } | 83 } |
| 60 sample_info->duration = TimeDeltaFromFrac(duration, timescale); | |
| 61 | 84 |
| 62 if (i < trun.sample_composition_time_offsets.size()) { | 85 if (i < trun.sample_composition_time_offsets.size()) { |
| 63 sample_info->cts_offset = | 86 sample_info->cts_offset = trun.sample_composition_time_offsets[i]; |
| 64 TimeDeltaFromFrac(trun.sample_composition_time_offsets[i], timescale); | |
| 65 } else { | 87 } else { |
| 66 sample_info->cts_offset = TimeDelta::FromMicroseconds(0); | 88 sample_info->cts_offset = 0; |
| 67 } | 89 } |
| 68 | 90 |
| 69 uint32 flags; | 91 uint32 flags; |
| 70 if (i < trun.sample_flags.size()) { | 92 if (i < trun.sample_flags.size()) { |
| 71 flags = trun.sample_flags[i]; | 93 flags = trun.sample_flags[i]; |
| 72 } else if (tfhd.has_default_sample_flags) { | 94 } else if (tfhd.has_default_sample_flags) { |
| 73 flags = tfhd.default_sample_flags; | 95 flags = tfhd.default_sample_flags; |
| 74 } else { | 96 } else { |
| 75 flags = trex.default_sample_flags; | 97 flags = trex.default_sample_flags; |
| 76 } | 98 } |
| 77 sample_info->is_keyframe = !(flags & kSampleIsDifferenceSampleFlagMask); | 99 sample_info->is_keyframe = !(flags & kSampleIsDifferenceSampleFlagMask); |
| 78 } | 100 } |
| 79 | 101 |
| 80 class CompareOffset { | 102 class CompareMinTrackRunDataOffset { |
|
ddorwin
2012/07/17 01:14:21
What does this do?
strobe_
2012/07/19 02:43:35
Comment added.
| |
| 81 public: | 103 public: |
| 82 bool operator()(const TrackRunInfo& a, const TrackRunInfo& b) { | 104 bool operator()(const TrackRunInfo& a, const TrackRunInfo& b) { |
| 83 int64 a_min = a.sample_start_offset; | 105 int64 a_aux = a.aux_info_total_size ? a.aux_info_start_offset : kint64max; |
| 84 if (a.is_encrypted && a.cenc_start_offset < a_min) | 106 int64 b_aux = b.aux_info_total_size ? b.aux_info_start_offset : kint64max; |
| 85 a_min = a.cenc_start_offset; | 107 |
| 86 int64 b_min = b.sample_start_offset; | 108 int64 a_lesser = std::min(a_aux, a.sample_start_offset); |
| 87 if (b.is_encrypted && b.cenc_start_offset < b_min) | 109 int64 a_greater = std::max(a_aux, a.sample_start_offset); |
| 88 b_min = b.cenc_start_offset; | 110 int64 b_lesser = std::min(b_aux, b.sample_start_offset); |
| 89 return a_min < b_min; | 111 int64 b_greater = std::max(b_aux, b.sample_start_offset); |
| 112 | |
| 113 if (a_lesser == b_lesser) return a_greater < b_greater; | |
| 114 return a_lesser < b_lesser; | |
| 90 } | 115 } |
| 91 }; | 116 }; |
| 92 | 117 |
| 93 bool TrackRunIterator::Init(const Movie& moov, const MovieFragment& moof) { | 118 bool TrackRunIterator::Init(const Movie& moov, const MovieFragment& moof) { |
| 94 runs_.clear(); | 119 runs_.clear(); |
| 95 | 120 |
| 96 for (size_t i = 0; i < moof.tracks.size(); i++) { | 121 for (size_t i = 0; i < moof.tracks.size(); i++) { |
| 97 const TrackFragment& traf = moof.tracks[i]; | 122 const TrackFragment& traf = moof.tracks[i]; |
| 98 | 123 |
| 99 const Track* trak = NULL; | 124 const Track* trak = NULL; |
| 100 for (size_t t = 0; t < moov.tracks.size(); t++) { | 125 for (size_t t = 0; t < moov.tracks.size(); t++) { |
| 101 if (moov.tracks[t].header.track_id == traf.header.track_id) | 126 if (moov.tracks[t].header.track_id == traf.header.track_id) |
| 102 trak = &moov.tracks[t]; | 127 trak = &moov.tracks[t]; |
| 103 } | 128 } |
| 129 RCHECK(trak); | |
| 104 | 130 |
| 105 const TrackExtends* trex = NULL; | 131 const TrackExtends* trex = NULL; |
| 106 for (size_t t = 0; t < moov.extends.tracks.size(); t++) { | 132 for (size_t t = 0; t < moov.extends.tracks.size(); t++) { |
| 107 if (moov.extends.tracks[t].track_id == traf.header.track_id) | 133 if (moov.extends.tracks[t].track_id == traf.header.track_id) |
| 108 trex = &moov.extends.tracks[t]; | 134 trex = &moov.extends.tracks[t]; |
| 109 } | 135 } |
| 110 RCHECK(trak && trex); | 136 RCHECK(trex); |
| 111 | 137 |
| 138 // TODO(strobe): Support multiple sample description entries | |
| 112 const ProtectionSchemeInfo* sinf = NULL; | 139 const ProtectionSchemeInfo* sinf = NULL; |
| 113 const SampleDescription& stsd = | 140 const SampleDescription& stsd = |
| 114 trak->media.information.sample_table.description; | 141 trak->media.information.sample_table.description; |
| 115 if (stsd.type == kAudio) { | 142 if (stsd.type == kAudio) { |
| 116 sinf = &stsd.audio_entries[0].sinf; | 143 sinf = &stsd.audio_entries[0].sinf; |
| 117 } else if (stsd.type == kVideo) { | 144 } else if (stsd.type == kVideo) { |
| 118 sinf = &stsd.video_entries[0].sinf; | 145 sinf = &stsd.video_entries[0].sinf; |
| 119 } else { | 146 } else { |
| 120 DVLOG(1) << "Skipping unhandled track type"; | 147 DVLOG(1) << "Skipping unhandled track type"; |
| 121 continue; | 148 continue; |
| 122 } | 149 } |
| 123 | 150 |
| 124 if (sinf->info.track_encryption.is_encrypted) { | 151 int64 run_start_dts = traf.decode_time.decode_time; |
| 125 // TODO(strobe): CENC recovery and testing (http://crbug.com/132351) | |
| 126 DVLOG(1) << "Encrypted tracks not handled"; | |
| 127 continue; | |
| 128 } | |
| 129 | 152 |
| 130 for (size_t j = 0; j < traf.runs.size(); j++) { | 153 for (size_t j = 0; j < traf.runs.size(); j++) { |
| 131 const TrackFragmentRun& trun = traf.runs[j]; | 154 const TrackFragmentRun& trun = traf.runs[j]; |
| 132 TrackRunInfo tri; | 155 TrackRunInfo tri; |
| 133 tri.track_id = traf.header.track_id; | 156 tri.track_id = traf.header.track_id; |
| 134 tri.start_dts = TimeDeltaFromFrac(traf.decode_time.decode_time, | 157 tri.timescale = trak->media.header.timescale; |
| 135 trak->media.header.timescale); | 158 tri.start_dts = run_start_dts; |
| 136 tri.sample_start_offset = trun.data_offset; | 159 tri.sample_start_offset = trun.data_offset; |
| 137 | 160 |
| 138 tri.is_encrypted = false; | 161 // Collect information from the auxiliary_offset entry with the same index |
| 139 tri.cenc_start_offset = 0; | 162 // in the 'saiz' container as the current run's index in the 'trun' |
| 140 tri.cenc_total_size = 0; | 163 // container, if it is present. |
| 141 tri.default_cenc_size = 0; | 164 if (traf.auxiliary_offset.offsets.size() > j) { |
| 165 // There should be an auxiliary info entry corresponding to each sample | |
| 166 // in the auxiliary offset entry's corresponding track run. | |
| 167 RCHECK(traf.auxiliary_size.sample_count == trun.sample_count); | |
| 168 tri.aux_info_start_offset = traf.auxiliary_offset.offsets[j]; | |
| 169 tri.aux_info_default_size = | |
| 170 traf.auxiliary_size.default_sample_info_size; | |
| 171 tri.aux_info_sizes = traf.auxiliary_size.sample_info_sizes; | |
| 172 | |
| 173 // If the default info size is positive, find the total size of the aux | |
| 174 // info block from it, otherwise sum over the individual sizes of each | |
| 175 // aux info entry in the aux_offset entry. | |
| 176 if (tri.aux_info_default_size) { | |
| 177 tri.aux_info_total_size = | |
| 178 tri.aux_info_default_size * trun.sample_count; | |
| 179 } else { | |
| 180 tri.aux_info_total_size = 0; | |
| 181 for (size_t k = 0; k < trun.sample_count; k++) { | |
| 182 tri.aux_info_total_size += tri.aux_info_sizes[k]; | |
| 183 } | |
| 184 } | |
| 185 } else { | |
| 186 tri.aux_info_start_offset = -1; | |
| 187 tri.aux_info_total_size = 0; | |
| 188 } | |
| 189 tri.track_encryption = sinf->info.track_encryption; | |
| 142 | 190 |
| 143 tri.samples.resize(trun.sample_count); | 191 tri.samples.resize(trun.sample_count); |
| 144 | |
| 145 for (size_t k = 0; k < trun.sample_count; k++) { | 192 for (size_t k = 0; k < trun.sample_count; k++) { |
| 146 PopulateSampleInfo(*trak, *trex, traf.header, trun, k, &tri.samples[k]); | 193 PopulateSampleInfo(*trex, traf.header, trun, k, &tri.samples[k]); |
| 194 run_start_dts += tri.samples[k].duration; | |
| 147 } | 195 } |
| 148 runs_.push_back(tri); | 196 runs_.push_back(tri); |
| 149 } | 197 } |
| 150 } | 198 } |
| 151 | 199 |
| 152 std::sort(runs_.begin(), runs_.end(), CompareOffset()); | 200 std::sort(runs_.begin(), runs_.end(), CompareMinTrackRunDataOffset()); |
| 153 run_itr_ = runs_.begin(); | 201 run_itr_ = runs_.begin(); |
| 154 min_clear_offset_itr_ = min_clear_offsets_.begin(); | |
| 155 ResetRun(); | 202 ResetRun(); |
| 156 return true; | 203 return true; |
| 157 } | 204 } |
| 158 | 205 |
| 159 void TrackRunIterator::AdvanceRun() { | 206 void TrackRunIterator::AdvanceRun() { |
| 160 ++run_itr_; | 207 ++run_itr_; |
| 161 if (min_clear_offset_itr_ != min_clear_offsets_.end()) | |
| 162 ++min_clear_offset_itr_; | |
| 163 ResetRun(); | 208 ResetRun(); |
| 164 } | 209 } |
| 165 | 210 |
| 166 void TrackRunIterator::ResetRun() { | 211 void TrackRunIterator::ResetRun() { |
| 167 if (!RunValid()) return; | 212 if (!RunIsValid()) return; |
| 168 sample_dts_ = run_itr_->start_dts; | 213 sample_dts_ = run_itr_->start_dts; |
| 169 sample_offset_ = run_itr_->sample_start_offset; | 214 sample_offset_ = run_itr_->sample_start_offset; |
| 170 sample_itr_ = run_itr_->samples.begin(); | 215 sample_itr_ = run_itr_->samples.begin(); |
| 216 cenc_info_.clear(); | |
| 171 } | 217 } |
| 172 | 218 |
| 173 void TrackRunIterator::AdvanceSample() { | 219 void TrackRunIterator::AdvanceSample() { |
| 174 DCHECK(SampleValid()); | 220 DCHECK(SampleIsValid()); |
| 175 sample_dts_ += sample_itr_->duration; | 221 sample_dts_ += sample_itr_->duration; |
| 176 sample_offset_ += sample_itr_->size; | 222 sample_offset_ += sample_itr_->size; |
| 177 ++sample_itr_; | 223 ++sample_itr_; |
| 178 } | 224 } |
| 179 | 225 |
| 180 bool TrackRunIterator::NeedsCENC() { | 226 // This implementation only indicates a need for caching if CENC auxiliary |
| 181 CHECK(!is_encrypted()) << "TODO(strobe): Implement CENC."; | 227 // info is available in the stream. |
| 182 return is_encrypted(); | 228 bool TrackRunIterator::AuxInfoNeedsToBeCached() { |
| 183 } | 229 DCHECK(RunIsValid()); |
| 184 | 230 return is_encrypted() && aux_info_size() > 0 && cenc_info_.size() == 0; |
| 185 bool TrackRunIterator::CacheCENC(const uint8* buf, int size) { | 231 } |
| 186 LOG(FATAL) << "Not implemented"; | 232 |
| 187 return false; | 233 // This implementation currently only caches CENC auxiliary info. |
| 188 } | 234 bool TrackRunIterator::CacheAuxInfo(const uint8* buf, int buf_size) { |
| 189 | 235 RCHECK(AuxInfoNeedsToBeCached() && buf_size >= aux_info_size()); |
| 190 bool TrackRunIterator::RunValid() const { | 236 |
| 237 cenc_info_.resize(run_itr_->samples.size()); | |
| 238 int64 pos = 0; | |
| 239 for (size_t i = 0; i < run_itr_->samples.size(); i++) { | |
| 240 int info_size = run_itr_->aux_info_default_size; | |
| 241 if (!info_size) | |
| 242 info_size = run_itr_->aux_info_sizes[i]; | |
| 243 | |
| 244 BufferReader reader(buf + pos, info_size); | |
| 245 RCHECK(cenc_info_[i].Parse(run_itr_->track_encryption.default_iv_size, | |
| 246 &reader)); | |
| 247 pos += info_size; | |
| 248 } | |
| 249 | |
| 250 return true; | |
| 251 } | |
| 252 | |
| 253 bool TrackRunIterator::RunIsValid() const { | |
| 191 return run_itr_ != runs_.end(); | 254 return run_itr_ != runs_.end(); |
| 192 } | 255 } |
| 193 | 256 |
| 194 bool TrackRunIterator::SampleValid() const { | 257 bool TrackRunIterator::SampleIsValid() const { |
| 195 return RunValid() && (sample_itr_ != run_itr_->samples.end()); | 258 return RunIsValid() && (sample_itr_ != run_itr_->samples.end()); |
| 196 } | 259 } |
| 197 | 260 |
| 198 int64 TrackRunIterator::GetMaxClearOffset() { | 261 int64 TrackRunIterator::GetMaxClearOffset() { |
| 199 int64 offset = kint64max; | 262 int64 offset = kint64max; |
|
ddorwin
2012/07/17 01:14:21
max_offset?
strobe_
2012/07/19 02:43:35
Well, internal to this function, it's really the m
| |
| 200 | 263 |
| 201 if (SampleValid()) { | 264 if (SampleIsValid()) { |
| 202 offset = std::min(offset, sample_offset_); | 265 offset = std::min(offset, sample_offset_); |
| 203 if (NeedsCENC()) { | 266 if (AuxInfoNeedsToBeCached()) { |
| 204 offset = std::min(offset, cenc_offset()); | 267 offset = std::min(offset, aux_info_offset()); |
| 205 } | 268 } |
| 206 } | 269 } |
| 207 if (min_clear_offset_itr_ != min_clear_offsets_.end()) { | 270 if (run_itr_ != runs_.end()) { |
| 208 offset = std::min(offset, *min_clear_offset_itr_); | 271 std::vector<TrackRunInfo>::const_iterator next_run = run_itr_ + 1; |
| 209 } | 272 if (next_run != runs_.end()) { |
| 210 if (offset == kint64max) return 0; | 273 offset = std::min(offset, next_run->sample_start_offset); |
| 274 if (next_run->aux_info_total_size) | |
| 275 offset = std::min(offset, next_run->aux_info_start_offset); | |
| 276 } | |
| 277 } | |
| 211 return offset; | 278 return offset; |
| 212 } | 279 } |
| 213 | 280 |
| 214 TimeDelta TrackRunIterator::GetMinDecodeTimestamp() { | 281 TimeDelta TrackRunIterator::GetMinDecodeTimestamp() { |
| 215 TimeDelta dts = kInfiniteDuration(); | 282 TimeDelta dts = kInfiniteDuration(); |
| 216 for (size_t i = 0; i < runs_.size(); i++) { | 283 for (size_t i = 0; i < runs_.size(); i++) { |
| 217 if (runs_[i].start_dts < dts) | 284 TimeDelta run_dts = TimeDeltaFromFrac(runs_[i].start_dts, |
| 218 dts = runs_[i].start_dts; | 285 runs_[i].timescale); |
| 286 if (run_dts < dts) | |
| 287 dts = run_dts; | |
|
ddorwin
2012/07/17 01:14:21
Why?
strobe_
2012/07/19 02:43:35
Addressed by rebase.
| |
| 219 } | 288 } |
| 220 return dts; | 289 return dts; |
| 221 } | 290 } |
| 222 | 291 |
| 223 uint32 TrackRunIterator::track_id() const { | 292 uint32 TrackRunIterator::track_id() const { |
| 224 DCHECK(RunValid()); | 293 DCHECK(RunIsValid()); |
| 225 return run_itr_->track_id; | 294 return run_itr_->track_id; |
| 226 } | 295 } |
| 227 | 296 |
| 228 bool TrackRunIterator::is_encrypted() const { | 297 bool TrackRunIterator::is_encrypted() const { |
| 229 DCHECK(RunValid()); | 298 DCHECK(RunIsValid()); |
| 230 return run_itr_->is_encrypted; | 299 return run_itr_->track_encryption.is_encrypted; |
| 231 } | 300 } |
| 232 | 301 |
| 233 int64 TrackRunIterator::cenc_offset() const { | 302 int64 TrackRunIterator::aux_info_offset() const { |
| 234 DCHECK(is_encrypted()); | 303 return run_itr_->aux_info_start_offset; |
| 235 return run_itr_->cenc_start_offset; | 304 } |
| 236 } | 305 |
| 237 | 306 int TrackRunIterator::aux_info_size() const { |
| 238 int TrackRunIterator::cenc_size() const { | 307 return run_itr_->aux_info_total_size; |
| 239 DCHECK(is_encrypted()); | 308 } |
| 240 return run_itr_->cenc_total_size; | 309 |
| 241 } | 310 int64 TrackRunIterator::sample_offset() const { |
| 242 | 311 DCHECK(SampleIsValid()); |
| 243 int64 TrackRunIterator::offset() const { | |
| 244 DCHECK(SampleValid()); | |
| 245 return sample_offset_; | 312 return sample_offset_; |
| 246 } | 313 } |
| 247 | 314 |
| 248 int TrackRunIterator::size() const { | 315 int TrackRunIterator::sample_size() const { |
| 249 DCHECK(SampleValid()); | 316 DCHECK(SampleIsValid()); |
| 250 return sample_itr_->size; | 317 return sample_itr_->size; |
| 251 } | 318 } |
| 252 | 319 |
| 253 TimeDelta TrackRunIterator::dts() const { | 320 TimeDelta TrackRunIterator::dts() const { |
| 254 DCHECK(SampleValid()); | 321 DCHECK(SampleIsValid()); |
| 255 return sample_dts_; | 322 return TimeDeltaFromFrac(sample_dts_, run_itr_->timescale); |
| 256 } | 323 } |
| 257 | 324 |
| 258 TimeDelta TrackRunIterator::cts() const { | 325 TimeDelta TrackRunIterator::cts() const { |
| 259 DCHECK(SampleValid()); | 326 DCHECK(SampleIsValid()); |
| 260 return sample_dts_ + sample_itr_->cts_offset; | 327 return TimeDeltaFromFrac(sample_dts_ + sample_itr_->cts_offset, |
| 328 run_itr_->timescale); | |
| 261 } | 329 } |
| 262 | 330 |
| 263 TimeDelta TrackRunIterator::duration() const { | 331 TimeDelta TrackRunIterator::duration() const { |
| 264 DCHECK(SampleValid()); | 332 DCHECK(SampleIsValid()); |
| 265 return sample_itr_->duration; | 333 return TimeDeltaFromFrac(sample_itr_->duration, run_itr_->timescale); |
| 266 } | 334 } |
| 267 | 335 |
| 268 bool TrackRunIterator::is_keyframe() const { | 336 bool TrackRunIterator::is_keyframe() const { |
| 269 DCHECK(SampleValid()); | 337 DCHECK(SampleIsValid()); |
| 270 return sample_itr_->is_keyframe; | 338 return sample_itr_->is_keyframe; |
| 271 } | 339 } |
| 272 | 340 |
| 273 const FrameCENCInfo& TrackRunIterator::frame_cenc_info() { | 341 scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { |
| 274 DCHECK(is_encrypted()); | 342 int sample_idx = sample_itr_ - run_itr_->samples.begin(); |
| 275 return frame_cenc_info_; | 343 const FrameCENCInfo& cenc_info = cenc_info_[sample_idx]; |
|
ddorwin
2012/07/17 01:14:21
check size of the vector/array first.
strobe_
2012/07/19 02:43:35
Done.
| |
| 344 DCHECK(is_encrypted() && !AuxInfoNeedsToBeCached()); | |
| 345 | |
| 346 if (!cenc_info.subsamples.empty() && | |
| 347 (cenc_info.GetTotalSizeOfSubsamples() != | |
| 348 static_cast<size_t>(sample_size()))) { | |
| 349 DVLOG(1) << "Incorrect CENC subsample size."; | |
| 350 return scoped_ptr<DecryptConfig>(); | |
| 351 } | |
| 352 | |
| 353 return scoped_ptr<DecryptConfig>(new DecryptConfig( | |
| 354 &run_itr_->track_encryption.default_kid[0], | |
| 355 run_itr_->track_encryption.default_kid.size(), | |
| 356 std::string(cenc_info.iv, cenc_info.iv + arraysize(cenc_info.iv)), | |
|
ddorwin
2012/07/17 01:14:21
why not just size as second param?
strobe_
2012/07/19 02:43:35
Would require typecasting.
| |
| 357 cenc_info.subsamples)); | |
| 276 } | 358 } |
| 277 | 359 |
| 278 } // namespace mp4 | 360 } // namespace mp4 |
| 279 } // namespace media | 361 } // namespace media |
| OLD | NEW |