@@ -5,6 +5,7 @@ use std::io::{Read, Seek, SeekFrom, Write};
5
5
use std:: time:: Duration ;
6
6
7
7
use crate :: mp4box:: trak:: TrakBox ;
8
+ use crate :: mp4box:: traf:: TrafBox ;
8
9
use crate :: mp4box:: * ;
9
10
use crate :: mp4box:: {
10
11
avc1:: Avc1Box ,
@@ -88,12 +89,16 @@ impl From<TtxtConfig> for TrackConfig {
88
89
#[ derive( Debug ) ]
89
90
pub struct Mp4Track {
90
91
pub trak : TrakBox ,
92
+ pub trafs : Vec < TrafBox > ,
93
+
94
+ // Fragmented Tracks Defaults.
95
+ pub default_sample_duration : u32 ,
91
96
}
92
97
93
98
impl Mp4Track {
94
99
pub ( crate ) fn from ( trak : & TrakBox ) -> Self {
95
100
let trak = trak. clone ( ) ;
96
- Self { trak }
101
+ Self { trak, trafs : Vec :: new ( ) , default_sample_duration : 0 , }
97
102
}
98
103
99
104
pub fn track_id ( & self ) -> u32 {
@@ -215,7 +220,17 @@ impl Mp4Track {
215
220
}
216
221
217
222
pub fn sample_count ( & self ) -> u32 {
218
- self . trak . mdia . minf . stbl . stsz . sample_count
223
+ if self . trafs . len ( ) > 0 {
224
+ let mut sample_count = 0u32 ;
225
+ for traf in self . trafs . iter ( ) {
226
+ if let Some ( ref trun) = traf. trun {
227
+ sample_count += trun. sample_count ;
228
+ }
229
+ }
230
+ sample_count
231
+ } else {
232
+ self . trak . mdia . minf . stbl . stsz . sample_count
233
+ }
219
234
}
220
235
221
236
pub fn video_profile ( & self ) -> Result < AvcProfile > {
@@ -330,18 +345,39 @@ impl Mp4Track {
330
345
}
331
346
332
347
fn sample_size ( & self , sample_id : u32 ) -> Result < u32 > {
333
- let stsz = & self . trak . mdia . minf . stbl . stsz ;
334
- if stsz. sample_size > 0 {
335
- return Ok ( stsz. sample_size ) ;
336
- }
337
- if let Some ( size) = stsz. sample_sizes . get ( sample_id as usize - 1 ) {
338
- Ok ( * size)
348
+ if self . trafs . len ( ) > 0 {
349
+ let sample_sizes_count = self . sample_count ( ) / self . trafs . len ( ) as u32 ;
350
+ let traf_idx = ( sample_id - 1 ) / sample_sizes_count;
351
+ if let Some ( trun) = & self . trafs [ traf_idx as usize ] . trun {
352
+ if let Some ( size) = trun. sample_sizes . get ( ( sample_id - ( sample_sizes_count * traf_idx) ) as usize - 1 ) {
353
+ Ok ( * size)
354
+ } else {
355
+ return Err ( Error :: EntryInTrunNotFound (
356
+ self . track_id ( ) ,
357
+ BoxType :: TrunBox ,
358
+ sample_id,
359
+ ) ) ;
360
+ }
361
+ } else {
362
+ return Err ( Error :: BoxInTrafNotFound (
363
+ self . track_id ( ) ,
364
+ BoxType :: TrafBox ,
365
+ ) ) ;
366
+ }
339
367
} else {
340
- return Err ( Error :: EntryInStblNotFound (
341
- self . track_id ( ) ,
342
- BoxType :: StszBox ,
343
- sample_id,
344
- ) ) ;
368
+ let stsz = & self . trak . mdia . minf . stbl . stsz ;
369
+ if stsz. sample_size > 0 {
370
+ return Ok ( stsz. sample_size ) ;
371
+ }
372
+ if let Some ( size) = stsz. sample_sizes . get ( sample_id as usize - 1 ) {
373
+ Ok ( * size)
374
+ } else {
375
+ return Err ( Error :: EntryInStblNotFound (
376
+ self . track_id ( ) ,
377
+ BoxType :: StszBox ,
378
+ sample_id,
379
+ ) ) ;
380
+ }
345
381
}
346
382
}
347
383
@@ -359,27 +395,33 @@ impl Mp4Track {
359
395
}
360
396
361
397
fn sample_offset ( & self , sample_id : u32 ) -> Result < u64 > {
362
- let stsc_index = self . stsc_index ( sample_id) ;
398
+ if self . trafs . len ( ) > 0 {
399
+ let sample_sizes_count = self . sample_count ( ) / self . trafs . len ( ) as u32 ;
400
+ let traf_idx = ( sample_id - 1 ) / sample_sizes_count;
401
+ Ok ( self . trafs [ ( sample_id - ( sample_sizes_count * traf_idx) ) as usize ] . tfhd . base_data_offset as u64 )
402
+ } else {
403
+ let stsc_index = self . stsc_index ( sample_id) ;
363
404
364
- let stsc = & self . trak . mdia . minf . stbl . stsc ;
365
- let stsc_entry = stsc. entries . get ( stsc_index) . unwrap ( ) ;
405
+ let stsc = & self . trak . mdia . minf . stbl . stsc ;
406
+ let stsc_entry = stsc. entries . get ( stsc_index) . unwrap ( ) ;
366
407
367
- let first_chunk = stsc_entry. first_chunk ;
368
- let first_sample = stsc_entry. first_sample ;
369
- let samples_per_chunk = stsc_entry. samples_per_chunk ;
408
+ let first_chunk = stsc_entry. first_chunk ;
409
+ let first_sample = stsc_entry. first_sample ;
410
+ let samples_per_chunk = stsc_entry. samples_per_chunk ;
370
411
371
- let chunk_id = first_chunk + ( sample_id - first_sample) / samples_per_chunk;
412
+ let chunk_id = first_chunk + ( sample_id - first_sample) / samples_per_chunk;
372
413
373
- let chunk_offset = self . chunk_offset ( chunk_id) ?;
414
+ let chunk_offset = self . chunk_offset ( chunk_id) ?;
374
415
375
- let first_sample_in_chunk = sample_id - ( sample_id - first_sample) % samples_per_chunk;
416
+ let first_sample_in_chunk = sample_id - ( sample_id - first_sample) % samples_per_chunk;
376
417
377
- let mut sample_offset = 0 ;
378
- for i in first_sample_in_chunk..sample_id {
379
- sample_offset += self . sample_size ( i) ?;
380
- }
418
+ let mut sample_offset = 0 ;
419
+ for i in first_sample_in_chunk..sample_id {
420
+ sample_offset += self . sample_size ( i) ?;
421
+ }
381
422
382
- Ok ( chunk_offset + sample_offset as u64 )
423
+ Ok ( chunk_offset + sample_offset as u64 )
424
+ }
383
425
}
384
426
385
427
fn sample_time ( & self , sample_id : u32 ) -> Result < ( u64 , u32 ) > {
@@ -388,22 +430,27 @@ impl Mp4Track {
388
430
let mut sample_count = 1 ;
389
431
let mut elapsed = 0 ;
390
432
391
- for entry in stts. entries . iter ( ) {
392
- if sample_id <= sample_count + entry. sample_count - 1 {
393
- let start_time =
394
- ( sample_id - sample_count) as u64 * entry. sample_delta as u64 + elapsed;
395
- return Ok ( ( start_time, entry. sample_delta ) ) ;
433
+ if self . trafs . len ( ) > 0 {
434
+ let start_time = ( ( sample_id - 1 ) * self . default_sample_duration ) as u64 ;
435
+ return Ok ( ( start_time, self . default_sample_duration ) )
436
+ } else {
437
+ for entry in stts. entries . iter ( ) {
438
+ if sample_id <= sample_count + entry. sample_count - 1 {
439
+ let start_time =
440
+ ( sample_id - sample_count) as u64 * entry. sample_delta as u64 + elapsed;
441
+ return Ok ( ( start_time, entry. sample_delta ) ) ;
442
+ }
443
+
444
+ sample_count += entry. sample_count ;
445
+ elapsed += entry. sample_count as u64 * entry. sample_delta as u64 ;
396
446
}
397
447
398
- sample_count += entry. sample_count ;
399
- elapsed += entry. sample_count as u64 * entry. sample_delta as u64 ;
448
+ return Err ( Error :: EntryInStblNotFound (
449
+ self . track_id ( ) ,
450
+ BoxType :: SttsBox ,
451
+ sample_id,
452
+ ) ) ;
400
453
}
401
-
402
- return Err ( Error :: EntryInStblNotFound (
403
- self . track_id ( ) ,
404
- BoxType :: SttsBox ,
405
- sample_id,
406
- ) ) ;
407
454
}
408
455
409
456
fn sample_rendering_offset ( & self , sample_id : u32 ) -> i32 {
@@ -417,6 +464,11 @@ impl Mp4Track {
417
464
}
418
465
419
466
fn is_sync_sample ( & self , sample_id : u32 ) -> bool {
467
+ if self . trafs . len ( ) > 0 {
468
+ let sample_sizes_count = self . sample_count ( ) / self . trafs . len ( ) as u32 ;
469
+ return sample_id == 1 || sample_id % sample_sizes_count == 0
470
+ }
471
+
420
472
if let Some ( ref stss) = self . trak . mdia . minf . stbl . stss {
421
473
match stss. entries . binary_search ( & sample_id) {
422
474
Ok ( _) => true ,
0 commit comments