22// License, v. 2.0. If a copy of the MPL was not distributed with this
33// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44use num_traits:: { CheckedAdd , CheckedSub , PrimInt , Zero } ;
5- use std:: ops:: { Add , Neg , Sub } ;
5+ use std:: { ops:: { Add , Neg , Sub } , convert :: TryInto } ;
66
77use super :: * ;
88
@@ -139,6 +139,7 @@ pub struct Indice {
139139pub fn create_sample_table (
140140 track : & Track ,
141141 track_offset_time : CheckedInteger < i64 > ,
142+ optional_available_size : Option < usize > ,
142143) -> Option < TryVec < Indice > > {
143144 let timescale = match track. timescale {
144145 Some ( ref t) => TrackTimeScale :: < i64 > ( t. 0 as i64 , t. 1 ) ,
@@ -153,16 +154,44 @@ pub fn create_sample_table(
153154 // According to spec, no sync table means every sample is sync sample.
154155 let has_sync_table = matches ! ( track. stss, Some ( _) ) ;
155156
156- let mut sample_size_iter = stsz. sample_sizes . iter ( ) ;
157-
158157 // Get 'stsc' iterator for (chunk_id, chunk_sample_count) and calculate the sample
159158 // offset address.
160159
161160 // With large numbers of samples, the cost of many allocations dominates,
162161 // 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+
166195 let mut sample_table = TryVec :: with_capacity ( total_sample_count) . ok ( ) ?;
167196
168197 for i in sample_to_chunk_iter ( & stsc. samples , & stco. offsets ) {
@@ -174,11 +203,15 @@ pub fn create_sample_table(
174203 } ;
175204 for _ in 0 ..sample_counts {
176205 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 ( ) ) {
178207 ( _, Some ( t) ) => ( start_offset + * t) ?,
179208 ( t, _) if t > 0 => ( start_offset + t) ?,
180209 _ => 0 . into ( ) ,
181210 } ;
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+ }
182215 if end_offset == 0 {
183216 return None ;
184217 }
0 commit comments