[vlc-commits] demux: mp4: use timescale helper
Francois Cartegnie
git at videolan.org
Mon Jan 16 20:49:49 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Jan 16 20:47:07 2017 +0100| [fcd0afcdba2c07e01e2839d651c747cbf37fc81c] | committer: Francois Cartegnie
demux: mp4: use timescale helper
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=fcd0afcdba2c07e01e2839d651c747cbf37fc81c
---
modules/demux/mp4/mp4.c | 143 ++++++++++++++++++++++++++----------------------
1 file changed, 78 insertions(+), 65 deletions(-)
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index c4f3b9b..283f7a1 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -169,6 +169,20 @@ static block_t * MP4_RTPHintToFrame( demux_t *p_demux, block_t *p_block, uint32_
/* Helpers */
+static int64_t MP4_rescale( int64_t i_value, uint32_t i_timescale, uint32_t i_newscale )
+{
+ if( i_timescale == i_newscale )
+ return i_value;
+
+ if( i_value <= INT64_MAX / i_newscale )
+ return i_value * i_newscale / i_timescale;
+
+ /* overflow */
+ int64_t q = i_value / i_timescale;
+ int64_t r = i_value % i_timescale;
+ return q * i_newscale + r * i_newscale / i_timescale;
+}
+
static uint32_t stream_ReadU32( stream_t *s, void *p_read, uint32_t i_toread )
{
ssize_t i_return = 0;
@@ -285,13 +299,12 @@ static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
}
/* add i_elst_time */
- i_dts += p_track->i_elst_time * p_track->i_timescale /
- p_sys->i_timescale;
+ i_dts += MP4_rescale( p_track->i_elst_time, p_sys->i_timescale, p_track->i_timescale );
if( i_dts < 0 ) i_dts = 0;
}
- return CLOCK_FREQ * i_dts / p_track->i_timescale;
+ return MP4_rescale( i_dts, p_track->i_timescale, CLOCK_FREQ );
}
static inline bool MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track,
@@ -312,8 +325,8 @@ static inline bool MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track,
{
if( i_sample < ck->p_sample_count_pts[i_index] )
{
- *pi_delta = ck->p_sample_offset_pts[i_index] * CLOCK_FREQ /
- (int64_t)p_track->i_timescale;
+ *pi_delta = MP4_rescale( ck->p_sample_offset_pts[i_index],
+ p_track->i_timescale, CLOCK_FREQ );
return true;
}
@@ -324,7 +337,7 @@ static inline bool MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track,
static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
{
- return CLOCK_FREQ * p_sys->i_time / p_sys->i_timescale;
+ return MP4_rescale( p_sys->i_time, p_sys->i_timescale, CLOCK_FREQ );
}
static void LoadChapter( demux_t *p_demux );
@@ -480,7 +493,7 @@ static void MP4_GetInterleaving( demux_t *p_demux, uint64_t *pi_max_contiguous,
if( tk != nexttk )
{
- i_duration = i_duration * CLOCK_FREQ / tk->i_timescale;
+ i_duration = MP4_rescale( i_duration, tk->i_timescale, CLOCK_FREQ );
if( i_duration > *pi_max_contiguous )
*pi_max_contiguous = i_duration;
i_duration = 0;
@@ -1355,7 +1368,7 @@ static int Seek( demux_t *p_demux, mtime_t i_date )
unsigned int i_track;
/* First update global time */
- p_sys->i_time = i_date * p_sys->i_timescale / CLOCK_FREQ;
+ p_sys->i_time = MP4_rescale( i_date, CLOCK_FREQ, p_sys->i_timescale );
p_sys->i_pcr = VLC_TS_INVALID;
/* Now for each stream try to go to this time */
@@ -1412,7 +1425,7 @@ static int LeafSeekIntoFragment( demux_t *p_demux, mp4_fragment_t *p_fragment )
{
stime_t i_tracktime = GetTrackFragmentTimeOffset( &p_sys->fragments, p_fragment,
p_sys->track[i_track].i_track_ID );
- p_sys->track[i_track].i_time = i_tracktime * p_sys->track[i_track].i_timescale / p_sys->i_timescale;
+ p_sys->track[i_track].i_time = MP4_rescale( i_tracktime, p_sys->i_timescale, p_sys->track[i_track].i_timescale );
i_time_base = __MIN( i_time_base, i_tracktime );
}
p_sys->i_time = i_time_base;
@@ -1468,9 +1481,9 @@ static int LeafSeekToTime( demux_t *p_demux, mtime_t i_nztime )
p_sys->context.p_fragment = NULL;
for( unsigned int i_track = 0; i_track < p_sys->i_tracks; i_track++ )
{
- p_sys->track[i_track].i_time = i_mooftime / CLOCK_FREQ * p_sys->track[i_track].i_timescale;
+ p_sys->track[i_track].i_time = MP4_rescale( i_mooftime, CLOCK_FREQ, p_sys->track[i_track].i_timescale );
}
- p_sys->i_time = i_mooftime / CLOCK_FREQ * p_sys->i_timescale;
+ p_sys->i_time = MP4_rescale( i_mooftime, CLOCK_FREQ, p_sys->i_timescale );
p_sys->i_pcr = VLC_TS_INVALID;
}
else
@@ -1502,8 +1515,8 @@ static int LeafSeekToPos( demux_t *p_demux, double f )
if ( p_sys->i_timescale && p_sys->i_overall_duration )
{
return LeafSeekToTime( p_demux,
- (mtime_t)( f * CLOCK_FREQ * p_sys->i_overall_duration /
- p_sys->i_timescale ) );
+ (mtime_t)( f *
+ MP4_rescale( p_sys->i_overall_duration, p_sys->i_timescale, CLOCK_FREQ ) ) );
}
if ( !p_sys->b_fragments_probed && !p_sys->b_index_probed && p_sys->b_seekable )
@@ -1618,9 +1631,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return MP4_frg_Seek( p_demux, f );
else if( p_sys->i_timescale > 0 )
{
- i64 = (int64_t)( f * CLOCK_FREQ *
- (double)p_sys->i_overall_duration /
- (double)p_sys->i_timescale );
+ i64 = (int64_t)( f * MP4_rescale( p_sys->i_overall_duration,
+ p_sys->i_timescale, CLOCK_FREQ ) );
return Seek( p_demux, i64 );
}
else return VLC_EGENERIC;
@@ -1629,9 +1641,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
pi64 = (int64_t*)va_arg( args, int64_t * );
if( p_sys->i_timescale > 0 )
{
- *pi64 = CLOCK_FREQ *
- (mtime_t)p_sys->i_time /
- (mtime_t)p_sys->i_timescale;
+ *pi64 = MP4_rescale( p_sys->i_time,
+ p_sys->i_timescale, CLOCK_FREQ );
}
else *pi64 = 0;
return VLC_SUCCESS;
@@ -1647,9 +1658,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
pi64 = (int64_t*)va_arg( args, int64_t * );
if( p_sys->i_timescale > 0 )
{
- *pi64 = CLOCK_FREQ *
- (mtime_t)p_sys->i_overall_duration /
- (mtime_t)p_sys->i_timescale;
+ *pi64 = MP4_rescale( p_sys->i_overall_duration,
+ p_sys->i_timescale, CLOCK_FREQ );
}
else *pi64 = 0;
return VLC_SUCCESS;
@@ -1864,8 +1874,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
if ( (p_load = MP4_BoxGet( p_sys->track[i].p_track, "load" )) &&
BOXDATA(p_load)->i_duration > 0 )
{
- *va_arg(args, int64_t *) = BOXDATA(p_load)->i_duration *
- CLOCK_FREQ / p_sys->track[i].i_timescale;
+ *va_arg(args, int64_t *) =
+ MP4_rescale( BOXDATA(p_load)->i_duration,
+ p_sys->track[i].i_timescale, CLOCK_FREQ );
return VLC_SUCCESS;
}
}
@@ -2049,8 +2060,9 @@ static void LoadChapter( demux_t *p_demux )
/* Add duration if titles are enabled */
if( p_sys->p_title )
{
- p_sys->p_title->i_length = CLOCK_FREQ *
- (uint64_t)p_sys->i_overall_duration / (uint64_t)p_sys->i_timescale;
+ p_sys->p_title->i_length =
+ MP4_rescale( p_sys->i_overall_duration,
+ p_sys->i_timescale, CLOCK_FREQ );
}
}
@@ -2753,11 +2765,11 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
if( p_track->p_elst && p_track->BOXDATA(p_elst)->i_entry_count > 0 )
{
MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
- int64_t i_mvt= i_start * p_sys->i_timescale / CLOCK_FREQ;
+ int64_t i_mvt= MP4_rescale( i_start, CLOCK_FREQ, p_sys->i_timescale );
/* now calculate i_start for this elst */
/* offset */
- i_start -= p_track->i_elst_time * CLOCK_FREQ / p_sys->i_timescale;
+ i_start -= MP4_rescale( p_track->i_elst_time, p_sys->i_timescale, CLOCK_FREQ );
if( i_start < 0 )
{
*pi_chunk = 0;
@@ -2766,7 +2778,7 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
return VLC_SUCCESS;
}
/* to track time scale */
- i_start = i_start * p_track->i_timescale / CLOCK_FREQ;
+ i_start = MP4_rescale( i_start, CLOCK_FREQ, p_track->i_timescale );
/* add elst offset */
if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
@@ -2777,13 +2789,13 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
msg_Dbg( p_demux, "elst (%d) gives %"PRId64"ms (movie)-> %"PRId64
"ms (track)", p_track->i_elst,
- i_mvt * 1000 / p_sys->i_timescale,
- i_start * 1000 / p_track->i_timescale );
+ MP4_rescale( i_mvt, p_sys->i_timescale, 1000 ),
+ MP4_rescale( i_start, p_track->i_timescale, 1000 ) );
}
else
{
/* convert absolute time to in timescale unit */
- i_start = i_start * p_track->i_timescale / CLOCK_FREQ;
+ i_start = MP4_rescale( i_start, CLOCK_FREQ, p_track->i_timescale );
}
/* we start from sample 0/chunk 0, hope it won't take too much time */
@@ -2981,7 +2993,7 @@ static void MP4_TrackRestart( demux_t *p_demux, mp4_track_t *p_track,
/* Restore fragmented pos */
p_track->cchunk = cchunk_backup;
p_track->i_sample = i_sample_pos_backup;
- p_track->i_time = time_backup * (uint64_t) p_track->i_timescale / timescale_backup;
+ p_track->i_time = MP4_rescale( time_backup, timescale_backup, p_track->i_timescale );
}
/****************************************************************************
@@ -3122,10 +3134,10 @@ static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
{
msg_Dbg( p_demux, " - [%d] duration=%"PRId64"ms media time=%"PRId64
"ms) rate=%d.%d", i,
- elst->i_segment_duration[i] * 1000 / p_sys->i_timescale,
+ MP4_rescale( elst->i_segment_duration[i], p_sys->i_timescale, 1000 ),
elst->i_media_time[i] >= 0 ?
- (int64_t)(elst->i_media_time[i] * 1000 / p_track->i_timescale) :
- INT64_C(-1),
+ MP4_rescale( elst->i_media_time[i], p_track->i_timescale, 1000 ) :
+ INT64_C(-1),
elst->i_media_rate_integer[i],
elst->i_media_rate_fraction[i] );
}
@@ -3658,9 +3670,8 @@ static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track, uint32_t
{
demux_sys_t *p_sys = p_demux->p_sys;
MP4_Box_data_elst_t *elst = p_track->BOXDATA(p_elst);
- uint64_t i_mvt = MP4_TrackGetDTS( p_demux, p_track ) *
- p_sys->i_timescale / CLOCK_FREQ;
-
+ uint64_t i_mvt = MP4_rescale( MP4_TrackGetDTS( p_demux, p_track ),
+ CLOCK_FREQ, p_sys->i_timescale );
if( (unsigned int)p_track->i_elst < elst->i_entry_count &&
i_mvt >= p_track->i_elst_time +
elst->i_segment_duration[p_track->i_elst] )
@@ -3685,7 +3696,7 @@ static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
if( tk->p_elst && tk->BOXDATA(p_elst)->i_entry_count > 0 )
{
MP4_Box_data_elst_t *elst = tk->BOXDATA(p_elst);
- int64_t i_mvt= i_time * p_sys->i_timescale / CLOCK_FREQ;
+ int64_t i_mvt= MP4_rescale( i_time, CLOCK_FREQ, p_sys->i_timescale );
for( tk->i_elst = 0; (unsigned int)tk->i_elst < elst->i_entry_count; tk->i_elst++ )
{
@@ -4097,9 +4108,8 @@ int DemuxFrg( demux_t *p_demux )
p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
if( p_sys->i_timescale > 0 )
{
- int64_t i_length = CLOCK_FREQ *
- (mtime_t)p_sys->i_overall_duration /
- (mtime_t)p_sys->i_timescale;
+ int64_t i_length = MP4_rescale( p_sys->i_overall_duration,
+ p_sys->i_timescale, CLOCK_FREQ );
if( MP4_GetMoviePTS( p_sys ) >= i_length )
return VLC_DEMUXER_EOF;
return VLC_DEMUXER_SUCCESS;
@@ -4424,8 +4434,8 @@ static bool AddFragment( demux_t *p_demux, MP4_Box_t *p_moox )
i_trafs_total_size += i_traf_total_size;
p_new->p_durations[i_durationindex].i_track_ID = BOXDATA(p_tfhd)->i_track_ID;
- p_new->p_durations[i_durationindex++].i_duration = i_traf_duration * p_sys->i_timescale / i_track_timescale;
-
+ p_new->p_durations[i_durationindex++].i_duration = MP4_rescale( i_traf_duration,
+ i_track_timescale, p_sys->i_timescale );
p_traf = p_traf->p_next;
i_traf++;
}
@@ -4449,7 +4459,8 @@ static bool AddFragment( demux_t *p_demux, MP4_Box_t *p_moox )
else
p_sys->i_overall_duration = BOXDATA(p_mehd)->i_fragment_duration;
- msg_Dbg( p_demux, "total fragments duration %"PRId64, CLOCK_FREQ * p_sys->i_overall_duration / p_sys->i_timescale );
+ msg_Dbg( p_demux, "total fragments duration %"PRId64, MP4_rescale( p_sys->i_overall_duration,
+ p_sys->i_timescale, CLOCK_FREQ ) );
return true;
}
@@ -4547,13 +4558,12 @@ static int LeafParseTRUN( demux_t *p_demux, mp4_track_t *p_track,
uint32_t dur = 0, len;
uint32_t chunk_size = 0;
- mtime_t i_nzdts = CLOCK_FREQ * p_track->i_time / p_track->i_timescale;
-
+ mtime_t i_nzdts = MP4_rescale( p_track->i_time, p_track->i_timescale, CLOCK_FREQ );
mtime_t i_nzpts;
for( uint32_t i = 0; i < p_trun->i_sample_count; i++)
{
- i_nzdts += CLOCK_FREQ * dur / p_track->i_timescale;
+ i_nzdts += MP4_rescale( dur, p_track->i_timescale, CLOCK_FREQ );
i_nzpts = i_nzdts;
if( p_trun->i_flags & MP4_TRUN_SAMPLE_DURATION )
@@ -4566,11 +4576,14 @@ static int LeafParseTRUN( demux_t *p_demux, mp4_track_t *p_track,
if( p_trun->i_flags & MP4_TRUN_SAMPLE_TIME_OFFSET )
{
if ( p_trun->i_version == 1 )
- i_nzpts += CLOCK_FREQ * (int32_t) p_trun->p_samples[i].i_composition_time_offset / p_track->i_timescale;
+ i_nzpts += MP4_rescale( (int32_t) p_trun->p_samples[i].i_composition_time_offset,
+ p_track->i_timescale, CLOCK_FREQ );
else if( p_trun->p_samples[i].i_composition_time_offset < 0xFF000000 )
- i_nzpts += CLOCK_FREQ * p_trun->p_samples[i].i_composition_time_offset / p_track->i_timescale;
+ i_nzpts += MP4_rescale( p_trun->p_samples[i].i_composition_time_offset,
+ p_track->i_timescale, CLOCK_FREQ );
else /* version 0 with negative */
- i_nzpts += CLOCK_FREQ * (int32_t) p_trun->p_samples[i].i_composition_time_offset / p_track->i_timescale;
+ i_nzpts += MP4_rescale( (int32_t) p_trun->p_samples[i].i_composition_time_offset,
+ p_track->i_timescale, CLOCK_FREQ );
}
if( p_trun->i_flags & MP4_TRUN_SAMPLE_SIZE )
@@ -4617,7 +4630,7 @@ static int LeafParseTRUN( demux_t *p_demux, mp4_track_t *p_track,
p_block->i_pts = VLC_TS_INVALID;
else
p_block->i_pts = VLC_TS_0 + i_nzpts;
- p_block->i_length = CLOCK_FREQ * dur / p_track->i_timescale;
+ p_block->i_length = MP4_rescale( dur, p_track->i_timescale, CLOCK_FREQ );
MP4_Block_Send( p_demux, p_track, p_block );
}
else block_Release( p_block );
@@ -4837,7 +4850,7 @@ static int LeafParseMDATwithMOOV( demux_t *p_demux )
mtime_t i_time = LeafGetMOOVTimeInChunk( p_chunk, i_nb_samples );
i_time += p_chunk->i_first_dts;
p_track->i_time = i_time;
- p_block->i_dts = VLC_TS_0 + CLOCK_FREQ * i_time / p_track->i_timescale;
+ p_block->i_dts = VLC_TS_0 + MP4_rescale( i_time, p_track->i_timescale, CLOCK_FREQ ) ;
/* pts */
int64_t i_delta;
@@ -4852,7 +4865,7 @@ static int LeafParseMDATwithMOOV( demux_t *p_demux )
if ( p_demux->p_sys->i_pcr < VLC_TS_0 )
{
- p_sys->i_time = p_track->i_time * p_sys->i_timescale / p_track->i_timescale;
+ p_sys->i_time = MP4_rescale( p_track->i_time, p_track->i_timescale, p_sys->i_timescale );
p_demux->p_sys->i_pcr = MP4_GetMoviePTS( p_demux->p_sys );
es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_demux->p_sys->i_pcr );
}
@@ -5006,13 +5019,13 @@ static int LeafIndexGetMoofPosByTime( demux_t *p_demux, const mtime_t i_target_t
i_offset = p_data->p_moof_offset[i];
}
- if ( CLOCK_FREQ * i_time / p_track->i_timescale >= i_target_time )
+ if ( MP4_rescale( i_time, p_track->i_timescale, CLOCK_FREQ ) >= i_target_time )
{
if ( i_pos == -1 ) /* Not in this traf */
break;
*pi_pos = (uint64_t) i_pos;
- *pi_mooftime = CLOCK_FREQ * i_time / p_track->i_timescale;
+ *pi_mooftime = MP4_rescale( i_time, p_track->i_timescale, CLOCK_FREQ );
if ( p_track->fmt.i_cat == AUDIO_ES )
*pi_mooftime -= CLOCK_FREQ / p_track->fmt.audio.i_rate * p_data->p_sample_number[i];
else
@@ -5227,8 +5240,8 @@ static int DemuxAsLeaf( demux_t *p_demux )
MP4_Box_t *p_tfdt = MP4_BoxGet( p_traf, "tfdt" );
if( p_tfdt )
{
- p_track->i_time = BOXDATA(p_tfdt)->i_base_media_decode_time *
- p_track->i_timescale / p_sys->i_timescale;
+ p_track->i_time = MP4_rescale( BOXDATA(p_tfdt)->i_base_media_decode_time,
+ p_sys->i_timescale, p_track->i_timescale );
b_has_base_media_decode_time = true;
}
}
@@ -5243,11 +5256,11 @@ static int DemuxAsLeaf( demux_t *p_demux )
for( unsigned int i_track = 0; i_track < p_sys->i_tracks; i_track++ )
{
- p_sys->track[i_track].i_time = i_time_base * p_sys->track[i_track].i_timescale /
- BOXDATA(p_sidx)->i_timescale;
+ p_sys->track[i_track].i_time = MP4_rescale( i_time_base, BOXDATA(p_sidx)->i_timescale,
+ p_sys->track[i_track].i_timescale );
}
- p_sys->i_time = i_time_base * p_sys->i_timescale / BOXDATA(p_sidx)->i_timescale;
+ p_sys->i_time = MP4_rescale( i_time_base, BOXDATA(p_sidx)->i_timescale, p_sys->i_timescale );
p_sys->i_pcr = VLC_TS_INVALID;
}
}
@@ -5310,12 +5323,12 @@ static int DemuxAsLeaf( demux_t *p_demux )
if( !p_track->b_selected || ( p_track->fmt.i_cat != VIDEO_ES && p_track->fmt.i_cat != AUDIO_ES ) )
continue;
- i_lowest_time = __MIN( i_lowest_time, p_track->i_time * p_sys->i_timescale / p_track->i_timescale );
+ i_lowest_time = __MIN( i_lowest_time, MP4_rescale( p_track->i_time, p_track->i_timescale, p_sys->i_timescale ) );
if ( i_lowest_dts == VLC_TS_INVALID )
- i_lowest_dts = CLOCK_FREQ * p_track->i_time / p_track->i_timescale;
+ i_lowest_dts = MP4_rescale( p_track->i_time, p_track->i_timescale, CLOCK_FREQ );
else
- i_lowest_dts = __MIN( i_lowest_dts, CLOCK_FREQ * p_track->i_time / p_track->i_timescale );
+ i_lowest_dts = __MIN( i_lowest_dts, MP4_rescale( p_track->i_time, p_track->i_timescale, CLOCK_FREQ ) );
}
p_sys->i_time = i_lowest_time;
More information about the vlc-commits
mailing list