OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/formats/mp4/track_run_iterator.h" | 5 #include "media/formats/mp4/track_run_iterator.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <limits> |
9 | 10 |
10 #include "media/formats/mp4/rcheck.h" | 11 #include "media/formats/mp4/rcheck.h" |
11 #include "media/formats/mp4/sample_to_group_iterator.h" | 12 #include "media/formats/mp4/sample_to_group_iterator.h" |
12 | 13 |
13 namespace media { | 14 namespace media { |
14 namespace mp4 { | 15 namespace mp4 { |
15 | 16 |
16 struct SampleInfo { | 17 struct SampleInfo { |
17 int size; | 18 int size; |
18 int duration; | 19 int duration; |
19 int cts_offset; | 20 int cts_offset; |
20 bool is_keyframe; | 21 bool is_keyframe; |
21 uint32 cenc_group_description_index; | 22 uint32_t cenc_group_description_index; |
22 }; | 23 }; |
23 | 24 |
24 struct TrackRunInfo { | 25 struct TrackRunInfo { |
25 uint32 track_id; | 26 uint32_t track_id; |
26 std::vector<SampleInfo> samples; | 27 std::vector<SampleInfo> samples; |
27 int64 timescale; | 28 int64_t timescale; |
28 int64 start_dts; | 29 int64_t start_dts; |
29 int64 sample_start_offset; | 30 int64_t sample_start_offset; |
30 | 31 |
31 bool is_audio; | 32 bool is_audio; |
32 const AudioSampleEntry* audio_description; | 33 const AudioSampleEntry* audio_description; |
33 const VideoSampleEntry* video_description; | 34 const VideoSampleEntry* video_description; |
34 const SampleGroupDescription* track_sample_encryption_group; | 35 const SampleGroupDescription* track_sample_encryption_group; |
35 | 36 |
36 int64 aux_info_start_offset; // Only valid if aux_info_total_size > 0. | 37 int64_t aux_info_start_offset; // Only valid if aux_info_total_size > 0. |
37 int aux_info_default_size; | 38 int aux_info_default_size; |
38 std::vector<uint8> aux_info_sizes; // Populated if default_size == 0. | 39 std::vector<uint8_t> aux_info_sizes; // Populated if default_size == 0. |
39 int aux_info_total_size; | 40 int aux_info_total_size; |
40 | 41 |
41 std::vector<CencSampleEncryptionInfoEntry> fragment_sample_encryption_info; | 42 std::vector<CencSampleEncryptionInfoEntry> fragment_sample_encryption_info; |
42 | 43 |
43 TrackRunInfo(); | 44 TrackRunInfo(); |
44 ~TrackRunInfo(); | 45 ~TrackRunInfo(); |
45 }; | 46 }; |
46 | 47 |
47 TrackRunInfo::TrackRunInfo() | 48 TrackRunInfo::TrackRunInfo() |
48 : track_id(0), | 49 : track_id(0), |
49 timescale(-1), | 50 timescale(-1), |
50 start_dts(-1), | 51 start_dts(-1), |
51 sample_start_offset(-1), | 52 sample_start_offset(-1), |
52 is_audio(false), | 53 is_audio(false), |
53 aux_info_start_offset(-1), | 54 aux_info_start_offset(-1), |
54 aux_info_default_size(-1), | 55 aux_info_default_size(-1), |
55 aux_info_total_size(-1) { | 56 aux_info_total_size(-1) { |
56 } | 57 } |
57 TrackRunInfo::~TrackRunInfo() {} | 58 TrackRunInfo::~TrackRunInfo() {} |
58 | 59 |
59 base::TimeDelta TimeDeltaFromRational(int64 numer, int64 denom) { | 60 base::TimeDelta TimeDeltaFromRational(int64_t numer, int64_t denom) { |
60 // To avoid overflow, split the following calculation: | 61 // To avoid overflow, split the following calculation: |
61 // (numer * base::Time::kMicrosecondsPerSecond) / denom | 62 // (numer * base::Time::kMicrosecondsPerSecond) / denom |
62 // into: | 63 // into: |
63 // (numer / denom) * base::Time::kMicrosecondsPerSecond + | 64 // (numer / denom) * base::Time::kMicrosecondsPerSecond + |
64 // ((numer % denom) * base::Time::kMicrosecondsPerSecond) / denom | 65 // ((numer % denom) * base::Time::kMicrosecondsPerSecond) / denom |
65 int64 a = numer / denom; | 66 int64_t a = numer / denom; |
66 DCHECK_LE((a > 0 ? a : -a), kint64max / base::Time::kMicrosecondsPerSecond); | 67 DCHECK_LE((a > 0 ? a : -a), std::numeric_limits<int64_t>::max() / |
67 int64 timea_in_us = a * base::Time::kMicrosecondsPerSecond; | 68 base::Time::kMicrosecondsPerSecond); |
| 69 int64_t timea_in_us = a * base::Time::kMicrosecondsPerSecond; |
68 | 70 |
69 int64 b = numer % denom; | 71 int64_t b = numer % denom; |
70 DCHECK_LE((b > 0 ? b : -b), kint64max / base::Time::kMicrosecondsPerSecond); | 72 DCHECK_LE((b > 0 ? b : -b), std::numeric_limits<int64_t>::max() / |
71 int64 timeb_in_us = (b * base::Time::kMicrosecondsPerSecond) / denom; | 73 base::Time::kMicrosecondsPerSecond); |
| 74 int64_t timeb_in_us = (b * base::Time::kMicrosecondsPerSecond) / denom; |
72 | 75 |
73 DCHECK((timeb_in_us < 0) || (timea_in_us <= kint64max - timeb_in_us)); | 76 DCHECK((timeb_in_us < 0) || |
74 DCHECK((timeb_in_us > 0) || (timea_in_us >= kint64min - timeb_in_us)); | 77 (timea_in_us <= std::numeric_limits<int64_t>::max() - timeb_in_us)); |
| 78 DCHECK((timeb_in_us > 0) || |
| 79 (timea_in_us >= std::numeric_limits<int64_t>::min() - timeb_in_us)); |
75 return base::TimeDelta::FromMicroseconds(timea_in_us + timeb_in_us); | 80 return base::TimeDelta::FromMicroseconds(timea_in_us + timeb_in_us); |
76 } | 81 } |
77 | 82 |
78 DecodeTimestamp DecodeTimestampFromRational(int64 numer, int64 denom) { | 83 DecodeTimestamp DecodeTimestampFromRational(int64_t numer, int64_t denom) { |
79 return DecodeTimestamp::FromPresentationTime( | 84 return DecodeTimestamp::FromPresentationTime( |
80 TimeDeltaFromRational(numer, denom)); | 85 TimeDeltaFromRational(numer, denom)); |
81 } | 86 } |
82 | 87 |
83 TrackRunIterator::TrackRunIterator(const Movie* moov, | 88 TrackRunIterator::TrackRunIterator(const Movie* moov, |
84 const scoped_refptr<MediaLog>& media_log) | 89 const scoped_refptr<MediaLog>& media_log) |
85 : moov_(moov), media_log_(media_log), sample_offset_(0) { | 90 : moov_(moov), media_log_(media_log), sample_offset_(0) { |
86 CHECK(moov); | 91 CHECK(moov); |
87 } | 92 } |
88 | 93 |
89 TrackRunIterator::~TrackRunIterator() {} | 94 TrackRunIterator::~TrackRunIterator() {} |
90 | 95 |
91 static std::string HexFlags(uint32 flags) { | 96 static std::string HexFlags(uint32_t flags) { |
92 std::stringstream stream; | 97 std::stringstream stream; |
93 stream << std::setfill('0') << std::setw(sizeof(flags)*2) << std::hex | 98 stream << std::setfill('0') << std::setw(sizeof(flags)*2) << std::hex |
94 << flags; | 99 << flags; |
95 return stream.str(); | 100 return stream.str(); |
96 } | 101 } |
97 | 102 |
98 static bool PopulateSampleInfo(const TrackExtends& trex, | 103 static bool PopulateSampleInfo(const TrackExtends& trex, |
99 const TrackFragmentHeader& tfhd, | 104 const TrackFragmentHeader& tfhd, |
100 const TrackFragmentRun& trun, | 105 const TrackFragmentRun& trun, |
101 const int64 edit_list_offset, | 106 const int64_t edit_list_offset, |
102 const uint32 i, | 107 const uint32_t i, |
103 SampleInfo* sample_info, | 108 SampleInfo* sample_info, |
104 const SampleDependsOn sdtp_sample_depends_on, | 109 const SampleDependsOn sdtp_sample_depends_on, |
105 bool is_audio, | 110 bool is_audio, |
106 const scoped_refptr<MediaLog>& media_log) { | 111 const scoped_refptr<MediaLog>& media_log) { |
107 if (i < trun.sample_sizes.size()) { | 112 if (i < trun.sample_sizes.size()) { |
108 sample_info->size = trun.sample_sizes[i]; | 113 sample_info->size = trun.sample_sizes[i]; |
109 } else if (tfhd.default_sample_size > 0) { | 114 } else if (tfhd.default_sample_size > 0) { |
110 sample_info->size = tfhd.default_sample_size; | 115 sample_info->size = tfhd.default_sample_size; |
111 } else { | 116 } else { |
112 sample_info->size = trex.default_sample_size; | 117 sample_info->size = trex.default_sample_size; |
113 } | 118 } |
114 | 119 |
115 if (i < trun.sample_durations.size()) { | 120 if (i < trun.sample_durations.size()) { |
116 sample_info->duration = trun.sample_durations[i]; | 121 sample_info->duration = trun.sample_durations[i]; |
117 } else if (tfhd.default_sample_duration > 0) { | 122 } else if (tfhd.default_sample_duration > 0) { |
118 sample_info->duration = tfhd.default_sample_duration; | 123 sample_info->duration = tfhd.default_sample_duration; |
119 } else { | 124 } else { |
120 sample_info->duration = trex.default_sample_duration; | 125 sample_info->duration = trex.default_sample_duration; |
121 } | 126 } |
122 | 127 |
123 if (i < trun.sample_composition_time_offsets.size()) { | 128 if (i < trun.sample_composition_time_offsets.size()) { |
124 sample_info->cts_offset = trun.sample_composition_time_offsets[i]; | 129 sample_info->cts_offset = trun.sample_composition_time_offsets[i]; |
125 } else { | 130 } else { |
126 sample_info->cts_offset = 0; | 131 sample_info->cts_offset = 0; |
127 } | 132 } |
128 sample_info->cts_offset += edit_list_offset; | 133 sample_info->cts_offset += edit_list_offset; |
129 | 134 |
130 uint32 flags; | 135 uint32_t flags; |
131 if (i < trun.sample_flags.size()) { | 136 if (i < trun.sample_flags.size()) { |
132 flags = trun.sample_flags[i]; | 137 flags = trun.sample_flags[i]; |
133 DVLOG(4) << __FUNCTION__ << " trun sample flags " << HexFlags(flags); | 138 DVLOG(4) << __FUNCTION__ << " trun sample flags " << HexFlags(flags); |
134 } else if (tfhd.has_default_sample_flags) { | 139 } else if (tfhd.has_default_sample_flags) { |
135 flags = tfhd.default_sample_flags; | 140 flags = tfhd.default_sample_flags; |
136 DVLOG(4) << __FUNCTION__ << " tfhd sample flags " << HexFlags(flags); | 141 DVLOG(4) << __FUNCTION__ << " tfhd sample flags " << HexFlags(flags); |
137 } else { | 142 } else { |
138 flags = trex.default_sample_flags; | 143 flags = trex.default_sample_flags; |
139 DVLOG(4) << __FUNCTION__ << " trex sample flags " << HexFlags(flags); | 144 DVLOG(4) << __FUNCTION__ << " trex sample flags " << HexFlags(flags); |
140 } | 145 } |
(...skipping 28 matching lines...) Expand all Loading... |
169 DVLOG(4) << __FUNCTION__ << " is_kf:" << sample_info->is_keyframe | 174 DVLOG(4) << __FUNCTION__ << " is_kf:" << sample_info->is_keyframe |
170 << " is_sync:" << sample_is_sync_sample | 175 << " is_sync:" << sample_is_sync_sample |
171 << " deps:" << sample_depends_on_others | 176 << " deps:" << sample_depends_on_others |
172 << " audio:" << is_audio; | 177 << " audio:" << is_audio; |
173 | 178 |
174 return true; | 179 return true; |
175 } | 180 } |
176 | 181 |
177 static const CencSampleEncryptionInfoEntry* GetSampleEncryptionInfoEntry( | 182 static const CencSampleEncryptionInfoEntry* GetSampleEncryptionInfoEntry( |
178 const TrackRunInfo& run_info, | 183 const TrackRunInfo& run_info, |
179 uint32 group_description_index) { | 184 uint32_t group_description_index) { |
180 const std::vector<CencSampleEncryptionInfoEntry>* entries = nullptr; | 185 const std::vector<CencSampleEncryptionInfoEntry>* entries = nullptr; |
181 | 186 |
182 // ISO-14496-12 Section 8.9.2.3 and 8.9.4 : group description index | 187 // ISO-14496-12 Section 8.9.2.3 and 8.9.4 : group description index |
183 // (1) ranges from 1 to the number of sample group entries in the track | 188 // (1) ranges from 1 to the number of sample group entries in the track |
184 // level SampleGroupDescription Box, or (2) takes the value 0 to | 189 // level SampleGroupDescription Box, or (2) takes the value 0 to |
185 // indicate that this sample is a member of no group, in this case, the | 190 // indicate that this sample is a member of no group, in this case, the |
186 // sample is associated with the default values specified in | 191 // sample is associated with the default values specified in |
187 // TrackEncryption Box, or (3) starts at 0x10001, i.e. the index value | 192 // TrackEncryption Box, or (3) starts at 0x10001, i.e. the index value |
188 // 1, with the value 1 in the top 16 bits, to reference fragment-local | 193 // 1, with the value 1 in the top 16 bits, to reference fragment-local |
189 // SampleGroupDescription Box. | 194 // SampleGroupDescription Box. |
(...skipping 23 matching lines...) Expand all Loading... |
213 // architectures, because we can cache the relatively small auxiliary | 218 // architectures, because we can cache the relatively small auxiliary |
214 // information for an entire run and then discard data from the input stream, | 219 // information for an entire run and then discard data from the input stream, |
215 // instead of retaining the entire 'mdat' box. | 220 // instead of retaining the entire 'mdat' box. |
216 // | 221 // |
217 // We optimize for this situation (with no loss of generality) by sorting track | 222 // We optimize for this situation (with no loss of generality) by sorting track |
218 // runs during iteration in order of their first data offset (either sample data | 223 // runs during iteration in order of their first data offset (either sample data |
219 // or auxiliary data). | 224 // or auxiliary data). |
220 class CompareMinTrackRunDataOffset { | 225 class CompareMinTrackRunDataOffset { |
221 public: | 226 public: |
222 bool operator()(const TrackRunInfo& a, const TrackRunInfo& b) { | 227 bool operator()(const TrackRunInfo& a, const TrackRunInfo& b) { |
223 int64 a_aux = a.aux_info_total_size ? a.aux_info_start_offset : kint64max; | 228 int64_t a_aux = a.aux_info_total_size ? a.aux_info_start_offset |
224 int64 b_aux = b.aux_info_total_size ? b.aux_info_start_offset : kint64max; | 229 : std::numeric_limits<int64_t>::max(); |
| 230 int64_t b_aux = b.aux_info_total_size ? b.aux_info_start_offset |
| 231 : std::numeric_limits<int64_t>::max(); |
225 | 232 |
226 int64 a_lesser = std::min(a_aux, a.sample_start_offset); | 233 int64_t a_lesser = std::min(a_aux, a.sample_start_offset); |
227 int64 a_greater = std::max(a_aux, a.sample_start_offset); | 234 int64_t a_greater = std::max(a_aux, a.sample_start_offset); |
228 int64 b_lesser = std::min(b_aux, b.sample_start_offset); | 235 int64_t b_lesser = std::min(b_aux, b.sample_start_offset); |
229 int64 b_greater = std::max(b_aux, b.sample_start_offset); | 236 int64_t b_greater = std::max(b_aux, b.sample_start_offset); |
230 | 237 |
231 if (a_lesser == b_lesser) return a_greater < b_greater; | 238 if (a_lesser == b_lesser) return a_greater < b_greater; |
232 return a_lesser < b_lesser; | 239 return a_lesser < b_lesser; |
233 } | 240 } |
234 }; | 241 }; |
235 | 242 |
236 bool TrackRunIterator::Init(const MovieFragment& moof) { | 243 bool TrackRunIterator::Init(const MovieFragment& moof) { |
237 runs_.clear(); | 244 runs_.clear(); |
238 | 245 |
239 for (size_t i = 0; i < moof.tracks.size(); i++) { | 246 for (size_t i = 0; i < moof.tracks.size(); i++) { |
(...skipping 21 matching lines...) Expand all Loading... |
261 } | 268 } |
262 size_t desc_idx = traf.header.sample_description_index; | 269 size_t desc_idx = traf.header.sample_description_index; |
263 if (!desc_idx) desc_idx = trex->default_sample_description_index; | 270 if (!desc_idx) desc_idx = trex->default_sample_description_index; |
264 RCHECK(desc_idx > 0); // Descriptions are one-indexed in the file | 271 RCHECK(desc_idx > 0); // Descriptions are one-indexed in the file |
265 desc_idx -= 1; | 272 desc_idx -= 1; |
266 | 273 |
267 // Process edit list to remove CTS offset introduced in the presence of | 274 // Process edit list to remove CTS offset introduced in the presence of |
268 // B-frames (those that contain a single edit with a nonnegative media | 275 // B-frames (those that contain a single edit with a nonnegative media |
269 // time). Other uses of edit lists are not supported, as they are | 276 // time). Other uses of edit lists are not supported, as they are |
270 // both uncommon and better served by higher-level protocols. | 277 // both uncommon and better served by higher-level protocols. |
271 int64 edit_list_offset = 0; | 278 int64_t edit_list_offset = 0; |
272 const std::vector<EditListEntry>& edits = trak->edit.list.edits; | 279 const std::vector<EditListEntry>& edits = trak->edit.list.edits; |
273 if (!edits.empty()) { | 280 if (!edits.empty()) { |
274 if (edits.size() > 1) | 281 if (edits.size() > 1) |
275 DVLOG(1) << "Multi-entry edit box detected; some components ignored."; | 282 DVLOG(1) << "Multi-entry edit box detected; some components ignored."; |
276 | 283 |
277 if (edits[0].media_time < 0) { | 284 if (edits[0].media_time < 0) { |
278 DVLOG(1) << "Empty edit list entry ignored."; | 285 DVLOG(1) << "Empty edit list entry ignored."; |
279 } else { | 286 } else { |
280 edit_list_offset = -edits[0].media_time; | 287 edit_list_offset = -edits[0].media_time; |
281 } | 288 } |
282 } | 289 } |
283 | 290 |
284 SampleToGroupIterator sample_to_group_itr(traf.sample_to_group); | 291 SampleToGroupIterator sample_to_group_itr(traf.sample_to_group); |
285 bool is_sample_to_group_valid = sample_to_group_itr.IsValid(); | 292 bool is_sample_to_group_valid = sample_to_group_itr.IsValid(); |
286 | 293 |
287 int64 run_start_dts = traf.decode_time.decode_time; | 294 int64_t run_start_dts = traf.decode_time.decode_time; |
288 int sample_count_sum = 0; | 295 int sample_count_sum = 0; |
289 for (size_t j = 0; j < traf.runs.size(); j++) { | 296 for (size_t j = 0; j < traf.runs.size(); j++) { |
290 const TrackFragmentRun& trun = traf.runs[j]; | 297 const TrackFragmentRun& trun = traf.runs[j]; |
291 TrackRunInfo tri; | 298 TrackRunInfo tri; |
292 tri.track_id = traf.header.track_id; | 299 tri.track_id = traf.header.track_id; |
293 tri.timescale = trak->media.header.timescale; | 300 tri.timescale = trak->media.header.timescale; |
294 tri.start_dts = run_start_dts; | 301 tri.start_dts = run_start_dts; |
295 tri.sample_start_offset = trun.data_offset; | 302 tri.sample_start_offset = trun.data_offset; |
296 tri.track_sample_encryption_group = | 303 tri.track_sample_encryption_group = |
297 &trak->media.information.sample_table.sample_group_description; | 304 &trak->media.information.sample_table.sample_group_description; |
(...skipping 18 matching lines...) Expand all Loading... |
316 // container, if it is present. | 323 // container, if it is present. |
317 if (traf.auxiliary_offset.offsets.size() > j) { | 324 if (traf.auxiliary_offset.offsets.size() > j) { |
318 // There should be an auxiliary info entry corresponding to each sample | 325 // There should be an auxiliary info entry corresponding to each sample |
319 // in the auxiliary offset entry's corresponding track run. | 326 // in the auxiliary offset entry's corresponding track run. |
320 RCHECK(traf.auxiliary_size.sample_count >= | 327 RCHECK(traf.auxiliary_size.sample_count >= |
321 sample_count_sum + trun.sample_count); | 328 sample_count_sum + trun.sample_count); |
322 tri.aux_info_start_offset = traf.auxiliary_offset.offsets[j]; | 329 tri.aux_info_start_offset = traf.auxiliary_offset.offsets[j]; |
323 tri.aux_info_default_size = | 330 tri.aux_info_default_size = |
324 traf.auxiliary_size.default_sample_info_size; | 331 traf.auxiliary_size.default_sample_info_size; |
325 if (tri.aux_info_default_size == 0) { | 332 if (tri.aux_info_default_size == 0) { |
326 const std::vector<uint8>& sizes = | 333 const std::vector<uint8_t>& sizes = |
327 traf.auxiliary_size.sample_info_sizes; | 334 traf.auxiliary_size.sample_info_sizes; |
328 tri.aux_info_sizes.insert(tri.aux_info_sizes.begin(), | 335 tri.aux_info_sizes.insert(tri.aux_info_sizes.begin(), |
329 sizes.begin() + sample_count_sum, | 336 sizes.begin() + sample_count_sum, |
330 sizes.begin() + sample_count_sum + trun.sample_count); | 337 sizes.begin() + sample_count_sum + trun.sample_count); |
331 } | 338 } |
332 | 339 |
333 // If the default info size is positive, find the total size of the aux | 340 // If the default info size is positive, find the total size of the aux |
334 // info block from it, otherwise sum over the individual sizes of each | 341 // info block from it, otherwise sum over the individual sizes of each |
335 // aux info entry in the aux_offset entry. | 342 // aux info entry in the aux_offset entry. |
336 if (tri.aux_info_default_size) { | 343 if (tri.aux_info_default_size) { |
(...skipping 20 matching lines...) Expand all Loading... |
357 | 364 |
358 run_start_dts += tri.samples[k].duration; | 365 run_start_dts += tri.samples[k].duration; |
359 | 366 |
360 if (!is_sample_to_group_valid) { | 367 if (!is_sample_to_group_valid) { |
361 // Set group description index to 0 to read encryption information | 368 // Set group description index to 0 to read encryption information |
362 // from TrackEncryption Box. | 369 // from TrackEncryption Box. |
363 tri.samples[k].cenc_group_description_index = 0; | 370 tri.samples[k].cenc_group_description_index = 0; |
364 continue; | 371 continue; |
365 } | 372 } |
366 | 373 |
367 uint32 index = sample_to_group_itr.group_description_index(); | 374 uint32_t index = sample_to_group_itr.group_description_index(); |
368 tri.samples[k].cenc_group_description_index = index; | 375 tri.samples[k].cenc_group_description_index = index; |
369 if (index != 0) | 376 if (index != 0) |
370 RCHECK(GetSampleEncryptionInfoEntry(tri, index)); | 377 RCHECK(GetSampleEncryptionInfoEntry(tri, index)); |
371 is_sample_to_group_valid = sample_to_group_itr.Advance(); | 378 is_sample_to_group_valid = sample_to_group_itr.Advance(); |
372 } | 379 } |
373 runs_.push_back(tri); | 380 runs_.push_back(tri); |
374 sample_count_sum += trun.sample_count; | 381 sample_count_sum += trun.sample_count; |
375 } | 382 } |
376 | 383 |
377 // We should have iterated through all samples in SampleToGroup Box. | 384 // We should have iterated through all samples in SampleToGroup Box. |
(...skipping 27 matching lines...) Expand all Loading... |
405 } | 412 } |
406 | 413 |
407 // This implementation only indicates a need for caching if CENC auxiliary | 414 // This implementation only indicates a need for caching if CENC auxiliary |
408 // info is available in the stream. | 415 // info is available in the stream. |
409 bool TrackRunIterator::AuxInfoNeedsToBeCached() { | 416 bool TrackRunIterator::AuxInfoNeedsToBeCached() { |
410 DCHECK(IsRunValid()); | 417 DCHECK(IsRunValid()); |
411 return aux_info_size() > 0 && cenc_info_.size() == 0; | 418 return aux_info_size() > 0 && cenc_info_.size() == 0; |
412 } | 419 } |
413 | 420 |
414 // This implementation currently only caches CENC auxiliary info. | 421 // This implementation currently only caches CENC auxiliary info. |
415 bool TrackRunIterator::CacheAuxInfo(const uint8* buf, int buf_size) { | 422 bool TrackRunIterator::CacheAuxInfo(const uint8_t* buf, int buf_size) { |
416 RCHECK(AuxInfoNeedsToBeCached() && buf_size >= aux_info_size()); | 423 RCHECK(AuxInfoNeedsToBeCached() && buf_size >= aux_info_size()); |
417 | 424 |
418 cenc_info_.resize(run_itr_->samples.size()); | 425 cenc_info_.resize(run_itr_->samples.size()); |
419 int64 pos = 0; | 426 int64_t pos = 0; |
420 for (size_t i = 0; i < run_itr_->samples.size(); i++) { | 427 for (size_t i = 0; i < run_itr_->samples.size(); i++) { |
421 int info_size = run_itr_->aux_info_default_size; | 428 int info_size = run_itr_->aux_info_default_size; |
422 if (!info_size) | 429 if (!info_size) |
423 info_size = run_itr_->aux_info_sizes[i]; | 430 info_size = run_itr_->aux_info_sizes[i]; |
424 | 431 |
425 if (IsSampleEncrypted(i)) { | 432 if (IsSampleEncrypted(i)) { |
426 BufferReader reader(buf + pos, info_size); | 433 BufferReader reader(buf + pos, info_size); |
427 RCHECK(cenc_info_[i].Parse(GetIvSize(i), &reader)); | 434 RCHECK(cenc_info_[i].Parse(GetIvSize(i), &reader)); |
428 } | 435 } |
429 pos += info_size; | 436 pos += info_size; |
430 } | 437 } |
431 | 438 |
432 return true; | 439 return true; |
433 } | 440 } |
434 | 441 |
435 bool TrackRunIterator::IsRunValid() const { | 442 bool TrackRunIterator::IsRunValid() const { |
436 return run_itr_ != runs_.end(); | 443 return run_itr_ != runs_.end(); |
437 } | 444 } |
438 | 445 |
439 bool TrackRunIterator::IsSampleValid() const { | 446 bool TrackRunIterator::IsSampleValid() const { |
440 return IsRunValid() && (sample_itr_ != run_itr_->samples.end()); | 447 return IsRunValid() && (sample_itr_ != run_itr_->samples.end()); |
441 } | 448 } |
442 | 449 |
443 // Because tracks are in sorted order and auxiliary information is cached when | 450 // Because tracks are in sorted order and auxiliary information is cached when |
444 // returning samples, it is guaranteed that no data will be required before the | 451 // returning samples, it is guaranteed that no data will be required before the |
445 // lesser of the minimum data offset of this track and the next in sequence. | 452 // lesser of the minimum data offset of this track and the next in sequence. |
446 // (The stronger condition - that no data is required before the minimum data | 453 // (The stronger condition - that no data is required before the minimum data |
447 // offset of this track alone - is not guaranteed, because the BMFF spec does | 454 // offset of this track alone - is not guaranteed, because the BMFF spec does |
448 // not have any inter-run ordering restrictions.) | 455 // not have any inter-run ordering restrictions.) |
449 int64 TrackRunIterator::GetMaxClearOffset() { | 456 int64_t TrackRunIterator::GetMaxClearOffset() { |
450 int64 offset = kint64max; | 457 int64_t offset = std::numeric_limits<int64_t>::max(); |
451 | 458 |
452 if (IsSampleValid()) { | 459 if (IsSampleValid()) { |
453 offset = std::min(offset, sample_offset_); | 460 offset = std::min(offset, sample_offset_); |
454 if (AuxInfoNeedsToBeCached()) | 461 if (AuxInfoNeedsToBeCached()) |
455 offset = std::min(offset, aux_info_offset()); | 462 offset = std::min(offset, aux_info_offset()); |
456 } | 463 } |
457 if (run_itr_ != runs_.end()) { | 464 if (run_itr_ != runs_.end()) { |
458 std::vector<TrackRunInfo>::const_iterator next_run = run_itr_ + 1; | 465 std::vector<TrackRunInfo>::const_iterator next_run = run_itr_ + 1; |
459 if (next_run != runs_.end()) { | 466 if (next_run != runs_.end()) { |
460 offset = std::min(offset, next_run->sample_start_offset); | 467 offset = std::min(offset, next_run->sample_start_offset); |
461 if (next_run->aux_info_total_size) | 468 if (next_run->aux_info_total_size) |
462 offset = std::min(offset, next_run->aux_info_start_offset); | 469 offset = std::min(offset, next_run->aux_info_start_offset); |
463 } | 470 } |
464 } | 471 } |
465 if (offset == kint64max) return 0; | 472 if (offset == std::numeric_limits<int64_t>::max()) |
| 473 return 0; |
466 return offset; | 474 return offset; |
467 } | 475 } |
468 | 476 |
469 uint32 TrackRunIterator::track_id() const { | 477 uint32_t TrackRunIterator::track_id() const { |
470 DCHECK(IsRunValid()); | 478 DCHECK(IsRunValid()); |
471 return run_itr_->track_id; | 479 return run_itr_->track_id; |
472 } | 480 } |
473 | 481 |
474 bool TrackRunIterator::is_encrypted() const { | 482 bool TrackRunIterator::is_encrypted() const { |
475 DCHECK(IsSampleValid()); | 483 DCHECK(IsSampleValid()); |
476 return IsSampleEncrypted(sample_itr_ - run_itr_->samples.begin()); | 484 return IsSampleEncrypted(sample_itr_ - run_itr_->samples.begin()); |
477 } | 485 } |
478 | 486 |
479 int64 TrackRunIterator::aux_info_offset() const { | 487 int64_t TrackRunIterator::aux_info_offset() const { |
480 return run_itr_->aux_info_start_offset; | 488 return run_itr_->aux_info_start_offset; |
481 } | 489 } |
482 | 490 |
483 int TrackRunIterator::aux_info_size() const { | 491 int TrackRunIterator::aux_info_size() const { |
484 return run_itr_->aux_info_total_size; | 492 return run_itr_->aux_info_total_size; |
485 } | 493 } |
486 | 494 |
487 bool TrackRunIterator::is_audio() const { | 495 bool TrackRunIterator::is_audio() const { |
488 DCHECK(IsRunValid()); | 496 DCHECK(IsRunValid()); |
489 return run_itr_->is_audio; | 497 return run_itr_->is_audio; |
490 } | 498 } |
491 | 499 |
492 const AudioSampleEntry& TrackRunIterator::audio_description() const { | 500 const AudioSampleEntry& TrackRunIterator::audio_description() const { |
493 DCHECK(is_audio()); | 501 DCHECK(is_audio()); |
494 DCHECK(run_itr_->audio_description); | 502 DCHECK(run_itr_->audio_description); |
495 return *run_itr_->audio_description; | 503 return *run_itr_->audio_description; |
496 } | 504 } |
497 | 505 |
498 const VideoSampleEntry& TrackRunIterator::video_description() const { | 506 const VideoSampleEntry& TrackRunIterator::video_description() const { |
499 DCHECK(!is_audio()); | 507 DCHECK(!is_audio()); |
500 DCHECK(run_itr_->video_description); | 508 DCHECK(run_itr_->video_description); |
501 return *run_itr_->video_description; | 509 return *run_itr_->video_description; |
502 } | 510 } |
503 | 511 |
504 int64 TrackRunIterator::sample_offset() const { | 512 int64_t TrackRunIterator::sample_offset() const { |
505 DCHECK(IsSampleValid()); | 513 DCHECK(IsSampleValid()); |
506 return sample_offset_; | 514 return sample_offset_; |
507 } | 515 } |
508 | 516 |
509 int TrackRunIterator::sample_size() const { | 517 int TrackRunIterator::sample_size() const { |
510 DCHECK(IsSampleValid()); | 518 DCHECK(IsSampleValid()); |
511 return sample_itr_->size; | 519 return sample_itr_->size; |
512 } | 520 } |
513 | 521 |
514 DecodeTimestamp TrackRunIterator::dts() const { | 522 DecodeTimestamp TrackRunIterator::dts() const { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 const FrameCENCInfo& cenc_info = cenc_info_[sample_idx]; | 560 const FrameCENCInfo& cenc_info = cenc_info_[sample_idx]; |
553 | 561 |
554 size_t total_size = 0; | 562 size_t total_size = 0; |
555 if (!cenc_info.subsamples.empty() && | 563 if (!cenc_info.subsamples.empty() && |
556 (!cenc_info.GetTotalSizeOfSubsamples(&total_size) || | 564 (!cenc_info.GetTotalSizeOfSubsamples(&total_size) || |
557 total_size != static_cast<size_t>(sample_size()))) { | 565 total_size != static_cast<size_t>(sample_size()))) { |
558 MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size."; | 566 MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size."; |
559 return scoped_ptr<DecryptConfig>(); | 567 return scoped_ptr<DecryptConfig>(); |
560 } | 568 } |
561 | 569 |
562 const std::vector<uint8>& kid = GetKeyId(sample_idx); | 570 const std::vector<uint8_t>& kid = GetKeyId(sample_idx); |
563 return scoped_ptr<DecryptConfig>(new DecryptConfig( | 571 return scoped_ptr<DecryptConfig>(new DecryptConfig( |
564 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), | 572 std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), |
565 std::string(reinterpret_cast<const char*>(cenc_info.iv), | 573 std::string(reinterpret_cast<const char*>(cenc_info.iv), |
566 arraysize(cenc_info.iv)), | 574 arraysize(cenc_info.iv)), |
567 cenc_info.subsamples)); | 575 cenc_info.subsamples)); |
568 } | 576 } |
569 | 577 |
570 uint32 TrackRunIterator::GetGroupDescriptionIndex(uint32 sample_index) const { | 578 uint32_t TrackRunIterator::GetGroupDescriptionIndex( |
| 579 uint32_t sample_index) const { |
571 DCHECK(IsRunValid()); | 580 DCHECK(IsRunValid()); |
572 DCHECK_LT(sample_index, run_itr_->samples.size()); | 581 DCHECK_LT(sample_index, run_itr_->samples.size()); |
573 return run_itr_->samples[sample_index].cenc_group_description_index; | 582 return run_itr_->samples[sample_index].cenc_group_description_index; |
574 } | 583 } |
575 | 584 |
576 bool TrackRunIterator::IsSampleEncrypted(size_t sample_index) const { | 585 bool TrackRunIterator::IsSampleEncrypted(size_t sample_index) const { |
577 uint32 index = GetGroupDescriptionIndex(sample_index); | 586 uint32_t index = GetGroupDescriptionIndex(sample_index); |
578 return (index == 0) | 587 return (index == 0) |
579 ? track_encryption().is_encrypted | 588 ? track_encryption().is_encrypted |
580 : GetSampleEncryptionInfoEntry(*run_itr_, index)->is_encrypted; | 589 : GetSampleEncryptionInfoEntry(*run_itr_, index)->is_encrypted; |
581 } | 590 } |
582 | 591 |
583 const std::vector<uint8>& TrackRunIterator::GetKeyId( | 592 const std::vector<uint8_t>& TrackRunIterator::GetKeyId( |
584 size_t sample_index) const { | 593 size_t sample_index) const { |
585 uint32 index = GetGroupDescriptionIndex(sample_index); | 594 uint32_t index = GetGroupDescriptionIndex(sample_index); |
586 return (index == 0) ? track_encryption().default_kid | 595 return (index == 0) ? track_encryption().default_kid |
587 : GetSampleEncryptionInfoEntry(*run_itr_, index)->key_id; | 596 : GetSampleEncryptionInfoEntry(*run_itr_, index)->key_id; |
588 } | 597 } |
589 | 598 |
590 uint8 TrackRunIterator::GetIvSize(size_t sample_index) const { | 599 uint8_t TrackRunIterator::GetIvSize(size_t sample_index) const { |
591 uint32 index = GetGroupDescriptionIndex(sample_index); | 600 uint32_t index = GetGroupDescriptionIndex(sample_index); |
592 return (index == 0) ? track_encryption().default_iv_size | 601 return (index == 0) ? track_encryption().default_iv_size |
593 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; | 602 : GetSampleEncryptionInfoEntry(*run_itr_, index)->iv_size; |
594 } | 603 } |
595 | 604 |
596 } // namespace mp4 | 605 } // namespace mp4 |
597 } // namespace media | 606 } // namespace media |
OLD | NEW |