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:: {
6
+ convert:: TryInto ,
7
+ ops:: { Add , Neg , Sub } ,
8
+ } ;
6
9
7
10
use super :: * ;
8
11
@@ -139,6 +142,7 @@ pub struct Indice {
139
142
pub fn create_sample_table (
140
143
track : & Track ,
141
144
track_offset_time : CheckedInteger < i64 > ,
145
+ optional_available_size : Option < usize > ,
142
146
) -> Option < TryVec < Indice > > {
143
147
let timescale = match track. timescale {
144
148
Some ( ref t) => TrackTimeScale :: < i64 > ( t. 0 as i64 , t. 1 ) ,
@@ -153,16 +157,48 @@ pub fn create_sample_table(
153
157
// According to spec, no sync table means every sample is sync sample.
154
158
let has_sync_table = matches ! ( track. stss, Some ( _) ) ;
155
159
156
- let mut sample_size_iter = stsz. sample_sizes . iter ( ) ;
157
-
158
160
// Get 'stsc' iterator for (chunk_id, chunk_sample_count) and calculate the sample
159
161
// offset address.
160
162
161
163
// With large numbers of samples, the cost of many allocations dominates,
162
164
// 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) ?;
165
+ let total_sample_count = {
166
+ let mut sample_size_iter = stsz. sample_sizes . iter ( ) ;
167
+ let mut sample_number: usize = 0 ;
168
+ for ( chunk_id, sample_counts) in sample_to_chunk_iter ( & stsc. samples , & stco. offsets ) {
169
+ match optional_available_size {
170
+ Some ( available_size) => {
171
+ let mut end_offset = match stco. offsets . get ( chunk_id as usize ) {
172
+ Some ( v) => * v as usize ,
173
+ None => return None ,
174
+ } ;
175
+ for _ in 0 ..sample_counts {
176
+ match ( stsz. sample_size , sample_size_iter. next ( ) ) {
177
+ ( _, Some ( single_sample_size) ) => {
178
+ end_offset += * single_sample_size as usize
179
+ }
180
+ ( sample_size, _) if sample_size > 0 => {
181
+ end_offset += sample_size as usize
182
+ }
183
+ _ => return None ,
184
+ }
185
+ if end_offset > available_size {
186
+ continue ;
187
+ }
188
+ sample_number = match sample_number. checked_add ( 1 ) {
189
+ Some ( v) => v,
190
+ None => return None ,
191
+ } ;
192
+ }
193
+ }
194
+ None => sample_number += sample_counts as usize ,
195
+ }
196
+ }
197
+ sample_number
198
+ } ;
199
+
200
+ let mut sample_size_iter = stsz. sample_sizes . iter ( ) ;
201
+
166
202
let mut sample_table = TryVec :: with_capacity ( total_sample_count) . ok ( ) ?;
167
203
168
204
for i in sample_to_chunk_iter ( & stsc. samples , & stco. offsets ) {
@@ -174,11 +210,19 @@ pub fn create_sample_table(
174
210
} ;
175
211
for _ in 0 ..sample_counts {
176
212
let start_offset = cur_position;
177
- let end_offset = match ( stsz. sample_size , sample_size_iter. next ( ) ) {
213
+ let end_offset: CheckedInteger < u64 > = match ( stsz. sample_size , sample_size_iter. next ( ) )
214
+ {
178
215
( _, Some ( t) ) => ( start_offset + * t) ?,
179
216
( t, _) if t > 0 => ( start_offset + t) ?,
180
217
_ => 0 . into ( ) ,
181
218
} ;
219
+ match optional_available_size
220
+ . map ( TryInto :: try_into)
221
+ . and_then ( Result :: ok)
222
+ {
223
+ Some ( available_size) if end_offset. 0 > available_size => continue ,
224
+ _ => ( ) ,
225
+ }
182
226
if end_offset == 0 {
183
227
return None ;
184
228
}
0 commit comments