2
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
use num_traits:: { CheckedAdd , CheckedSub , PrimInt , Zero } ;
5
- use std:: ops:: { Add , Neg , Sub } ;
5
+ use std:: { ops:: { Add , Neg , Sub } , convert :: TryInto } ;
6
6
7
7
use super :: * ;
8
8
@@ -139,6 +139,7 @@ pub struct Indice {
139
139
pub fn create_sample_table (
140
140
track : & Track ,
141
141
track_offset_time : CheckedInteger < i64 > ,
142
+ optional_available_size : Option < usize > ,
142
143
) -> Option < TryVec < Indice > > {
143
144
let timescale = match track. timescale {
144
145
Some ( ref t) => TrackTimeScale :: < i64 > ( t. 0 as i64 , t. 1 ) ,
@@ -153,16 +154,44 @@ pub fn create_sample_table(
153
154
// According to spec, no sync table means every sample is sync sample.
154
155
let has_sync_table = matches ! ( track. stss, Some ( _) ) ;
155
156
156
- let mut sample_size_iter = stsz. sample_sizes . iter ( ) ;
157
-
158
157
// Get 'stsc' iterator for (chunk_id, chunk_sample_count) and calculate the sample
159
158
// offset address.
160
159
161
160
// With large numbers of samples, the cost of many allocations dominates,
162
161
// so it's worth iterating twice to allocate sample_table just once.
163
- let total_sample_count = sample_to_chunk_iter ( & stsc. samples , & stco. offsets )
164
- . map ( |( _, sample_counts) | sample_counts. to_usize ( ) )
165
- . try_fold ( 0usize , usize:: checked_add) ?;
162
+ let total_sample_count = {
163
+ let mut sample_size_iter = stsz. sample_sizes . iter ( ) ;
164
+ let mut sample_number: usize = 0 ;
165
+ for ( chunk_id, sample_counts) in sample_to_chunk_iter ( & stsc. samples , & stco. offsets ) {
166
+ match optional_available_size {
167
+ Some ( available_size) => {
168
+ let mut end_offset = match stco. offsets . get ( chunk_id as usize ) {
169
+ Some ( v) => * v as usize ,
170
+ None => return None ,
171
+ } ;
172
+ for _ in 0 ..sample_counts {
173
+ match ( stsz. sample_size , sample_size_iter. next ( ) ) {
174
+ ( _, Some ( single_sample_size) ) => end_offset += * single_sample_size as usize ,
175
+ ( sample_size, _) if sample_size > 0 => end_offset += sample_size as usize ,
176
+ _ => return None ,
177
+ }
178
+ if end_offset > available_size {
179
+ break ;
180
+ }
181
+ sample_number = match sample_number. checked_add ( 1 ) {
182
+ Some ( v) => v,
183
+ None => return None ,
184
+ } ;
185
+ }
186
+ }
187
+ None => sample_number += sample_counts as usize ,
188
+ }
189
+ }
190
+ sample_number
191
+ } ;
192
+
193
+ let mut sample_size_iter = stsz. sample_sizes . iter ( ) ;
194
+
166
195
let mut sample_table = TryVec :: with_capacity ( total_sample_count) . ok ( ) ?;
167
196
168
197
for i in sample_to_chunk_iter ( & stsc. samples , & stco. offsets ) {
@@ -174,11 +203,15 @@ pub fn create_sample_table(
174
203
} ;
175
204
for _ in 0 ..sample_counts {
176
205
let start_offset = cur_position;
177
- let end_offset = match ( stsz. sample_size , sample_size_iter. next ( ) ) {
206
+ let end_offset: CheckedInteger < u64 > = match ( stsz. sample_size , sample_size_iter. next ( ) ) {
178
207
( _, Some ( t) ) => ( start_offset + * t) ?,
179
208
( t, _) if t > 0 => ( start_offset + t) ?,
180
209
_ => 0 . into ( ) ,
181
210
} ;
211
+ match optional_available_size. map ( TryInto :: try_into) . and_then ( Result :: ok) {
212
+ Some ( available_size) if end_offset. 0 > available_size => continue ,
213
+ _ => ( ) ,
214
+ }
182
215
if end_offset == 0 {
183
216
return None ;
184
217
}
0 commit comments