Commit 28e9ed29 authored by Gildas Bazin's avatar Gildas Bazin

* modules/demux/mp4/mp4.c: a couple of fixes for track selection when seeking.

parent 85f1cd8a
...@@ -496,7 +496,8 @@ static int Demux( demux_t *p_demux ) ...@@ -496,7 +496,8 @@ static int Demux( demux_t *p_demux )
unsigned int i_track_selected; unsigned int i_track_selected;
/* check for newly selected/unselected track */ /* check for newly selected/unselected track */
for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks; i_track++ ) for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks;
i_track++ )
{ {
mp4_track_t *tk = &p_sys->track[i_track]; mp4_track_t *tk = &p_sys->track[i_track];
...@@ -641,8 +642,8 @@ static int Demux( demux_t *p_demux ) ...@@ -641,8 +642,8 @@ static int Demux( demux_t *p_demux )
} }
/***************************************************************************** /*****************************************************************************
* Seek: Got to i_date * Seek: Got to i_date
******************************************************************************/ ******************************************************************************/
static int Seek ( demux_t *p_demux, mtime_t i_date ) static int Seek( demux_t *p_demux, mtime_t i_date )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
unsigned int i_track; unsigned int i_track;
...@@ -655,13 +656,9 @@ static int Seek ( demux_t *p_demux, mtime_t i_date ) ...@@ -655,13 +656,9 @@ static int Seek ( demux_t *p_demux, mtime_t i_date )
for( i_track = 0; i_track < p_sys->i_tracks; i_track++ ) for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
{ {
mp4_track_t *tk = &p_sys->track[i_track]; mp4_track_t *tk = &p_sys->track[i_track];
MP4_TrackSeek( p_demux, tk, i_date );
if( tk->b_ok && tk->b_selected )
{
MP4_TrackSeek( p_demux, tk, i_date );
}
} }
return( 1 ); return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
...@@ -1019,8 +1016,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux, ...@@ -1019,8 +1016,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
} }
msg_Dbg( p_demux, msg_Dbg( p_demux, "track[Id 0x%x] read %d samples length:"I64Fd"s",
"track[Id 0x%x] read %d samples length:"I64Fd"s",
p_demux_track->i_track_ID, p_demux_track->i_track_ID,
p_demux_track->i_sample_count, p_demux_track->i_sample_count,
i_last_dts / p_demux_track->i_timescale ); i_last_dts / p_demux_track->i_timescale );
...@@ -1030,12 +1026,10 @@ static int TrackCreateSamplesIndex( demux_t *p_demux, ...@@ -1030,12 +1026,10 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
/* /*
* TrackCreateES: * TrackCreateES:
* Create ES and PES to init decoder if needed, for a track starting at i_chunk * Create ES and PES to init decoder if needed, for a track starting at i_chunk
*/ */
static int TrackCreateES ( demux_t *p_demux, static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
mp4_track_t *p_track, unsigned int i_chunk, es_out_id_t **pp_es )
unsigned int i_chunk,
es_out_id_t **pp_es )
{ {
MP4_Box_t *p_sample; MP4_Box_t *p_sample;
MP4_Box_t *p_esds; MP4_Box_t *p_esds;
...@@ -1305,11 +1299,9 @@ static int TrackCreateES ( demux_t *p_demux, ...@@ -1305,11 +1299,9 @@ static int TrackCreateES ( demux_t *p_demux,
/* given a time it return sample/chunk /* given a time it return sample/chunk
* it also update elst field of the track * it also update elst field of the track
*/ */
static int TrackTimeToSampleChunk( demux_t *p_demux, static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
mp4_track_t *p_track, int64_t i_start, uint32_t *pi_chunk,
int64_t i_start, uint32_t *pi_sample )
uint32_t *pi_chunk,
uint32_t *pi_sample )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
MP4_Box_t *p_stss; MP4_Box_t *p_stss;
...@@ -1333,7 +1325,7 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, ...@@ -1333,7 +1325,7 @@ static int TrackTimeToSampleChunk( demux_t *p_demux,
/* now calculate i_start for this elst */ /* now calculate i_start for this elst */
/* offset */ /* offset */
i_start -= p_track->i_elst_time * (int64_t)1000000 / p_sys->i_timescale; i_start -= p_track->i_elst_time * I64C(1000000) / p_sys->i_timescale;
if( i_start < 0 ) if( i_start < 0 )
{ {
*pi_chunk = 0; *pi_chunk = 0;
...@@ -1351,8 +1343,8 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, ...@@ -1351,8 +1343,8 @@ static int TrackTimeToSampleChunk( demux_t *p_demux,
i_start += elst->i_media_time[p_track->i_elst]; i_start += elst->i_media_time[p_track->i_elst];
} }
msg_Dbg( p_demux, "elst (%d) gives "I64Fd"ms (movie)-> "I64Fd"ms (track)", msg_Dbg( p_demux, "elst (%d) gives "I64Fd"ms (movie)-> "I64Fd
p_track->i_elst, "ms (track)", p_track->i_elst,
i_mvt * 1000 / p_sys->i_timescale, i_mvt * 1000 / p_sys->i_timescale,
i_start * 1000 / p_track->i_timescale ); i_start * 1000 / p_track->i_timescale );
} }
...@@ -1403,15 +1395,16 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, ...@@ -1403,15 +1395,16 @@ static int TrackTimeToSampleChunk( demux_t *p_demux,
{ {
break; break;
} }
i_sample += ( i_start - i_dts ) / p_track->chunk[i_chunk].p_sample_delta_dts[i_index]; i_sample += ( i_start - i_dts ) /
p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
break; break;
} }
} }
if( i_sample >= p_track->i_sample_count ) if( i_sample >= p_track->i_sample_count )
{ {
msg_Warn( p_demux, msg_Warn( p_demux, "track[Id 0x%x] will be disabled "
"track[Id 0x%x] will be disabled (seeking too far) chunk=%d sample=%d", "(seeking too far) chunk=%d sample=%d",
p_track->i_track_ID, i_chunk, i_sample ); p_track->i_track_ID, i_chunk, i_sample );
return( VLC_EGENERIC ); return( VLC_EGENERIC );
} }
...@@ -1450,7 +1443,7 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, ...@@ -1450,7 +1443,7 @@ static int TrackTimeToSampleChunk( demux_t *p_demux,
/* new i_sample is more than old so i_chunk can only increased */ /* new i_sample is more than old so i_chunk can only increased */
while( i_chunk < p_track->i_chunk_count - 1 && while( i_chunk < p_track->i_chunk_count - 1 &&
i_sample >= p_track->chunk[i_chunk].i_sample_first + i_sample >= p_track->chunk[i_chunk].i_sample_first +
p_track->chunk[i_chunk].i_sample_count ) p_track->chunk[i_chunk].i_sample_count )
{ {
i_chunk++; i_chunk++;
} }
...@@ -1461,9 +1454,8 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, ...@@ -1461,9 +1454,8 @@ static int TrackTimeToSampleChunk( demux_t *p_demux,
} }
else else
{ {
msg_Dbg( p_demux, msg_Dbg( p_demux, "track[Id 0x%x] does not provide Sync "
"track[Id 0x%x] does not provide Sync Sample Box (stss)", "Sample Box (stss)", p_track->i_track_ID );
p_track->i_track_ID );
} }
*pi_chunk = i_chunk; *pi_chunk = i_chunk;
...@@ -1472,30 +1464,28 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, ...@@ -1472,30 +1464,28 @@ static int TrackTimeToSampleChunk( demux_t *p_demux,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int TrackGotoChunkSample( demux_t *p_demux, static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
mp4_track_t *p_track, unsigned int i_chunk, unsigned int i_sample )
unsigned int i_chunk,
unsigned int i_sample )
{ {
vlc_bool_t b_reselect = VLC_FALSE; vlc_bool_t b_reselect = VLC_FALSE;
/* now see if actual es is ok */ /* now see if actual es is ok */
if( p_track->i_chunk < 0 || if( p_track->i_chunk < 0 ||
p_track->i_chunk >= p_track->i_chunk_count || p_track->i_chunk >= p_track->i_chunk_count - 1 ||
p_track->chunk[p_track->i_chunk].i_sample_description_index != p_track->chunk[p_track->i_chunk].i_sample_description_index !=
p_track->chunk[i_chunk].i_sample_description_index ) p_track->chunk[i_chunk].i_sample_description_index )
{ {
msg_Warn( p_demux, "recreate ES" ); msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
p_track->i_track_ID );
es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, p_track->p_es, &b_reselect ); es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
p_track->p_es, &b_reselect );
es_out_Del( p_demux->out, p_track->p_es ); es_out_Del( p_demux->out, p_track->p_es );
p_track->p_es = NULL; p_track->p_es = NULL;
if( TrackCreateES( p_demux, if( TrackCreateES( p_demux, p_track, i_chunk, &p_track->p_es ) )
p_track, i_chunk,
&p_track->p_es ) )
{ {
msg_Err( p_demux, "cannot create es for track[Id 0x%x]", msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
p_track->i_track_ID ); p_track->i_track_ID );
...@@ -1524,9 +1514,8 @@ static int TrackGotoChunkSample( demux_t *p_demux, ...@@ -1524,9 +1514,8 @@ static int TrackGotoChunkSample( demux_t *p_demux,
* Parse track information and create all needed data to run a track * Parse track information and create all needed data to run a track
* If it succeed b_ok is set to 1 else to 0 * If it succeed b_ok is set to 1 else to 0
****************************************************************************/ ****************************************************************************/
static void MP4_TrackCreate( demux_t *p_demux, static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
mp4_track_t *p_track, MP4_Box_t *p_box_trak )
MP4_Box_t * p_box_trak )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
...@@ -1707,7 +1696,9 @@ static void MP4_TrackCreate( demux_t *p_demux, ...@@ -1707,7 +1696,9 @@ static void MP4_TrackCreate( demux_t *p_demux,
int i; int i;
for( i = 0; i < p_track->i_chunk_count; i++ ) for( i = 0; i < p_track->i_chunk_count; i++ )
{ {
fprintf( stderr, "%-5d sample_count=%d pts=%lld\n", i, p_track->chunk[i].i_sample_count, p_track->chunk[i].i_first_dts ); fprintf( stderr, "%-5d sample_count=%d pts=%lld\n",
i, p_track->chunk[i].i_sample_count,
p_track->chunk[i].i_first_dts );
} }
} }
...@@ -1720,8 +1711,7 @@ static void MP4_TrackCreate( demux_t *p_demux, ...@@ -1720,8 +1711,7 @@ static void MP4_TrackCreate( demux_t *p_demux,
**************************************************************************** ****************************************************************************
* Destroy a track created by MP4_TrackCreate. * Destroy a track created by MP4_TrackCreate.
****************************************************************************/ ****************************************************************************/
static void MP4_TrackDestroy( demux_t *p_demux, static void MP4_TrackDestroy( demux_t *p_demux, mp4_track_t *p_track )
mp4_track_t *p_track )
{ {
unsigned int i_chunk; unsigned int i_chunk;
...@@ -1747,9 +1737,8 @@ static void MP4_TrackDestroy( demux_t *p_demux, ...@@ -1747,9 +1737,8 @@ static void MP4_TrackDestroy( demux_t *p_demux,
} }
} }
static int MP4_TrackSelect ( demux_t *p_demux, static int MP4_TrackSelect( demux_t *p_demux, mp4_track_t *p_track,
mp4_track_t *p_track, mtime_t i_start )
mtime_t i_start )
{ {
if( !p_track->b_ok ) if( !p_track->b_ok )
{ {
...@@ -1758,8 +1747,7 @@ static int MP4_TrackSelect ( demux_t *p_demux, ...@@ -1758,8 +1747,7 @@ static int MP4_TrackSelect ( demux_t *p_demux,
if( p_track->b_selected ) if( p_track->b_selected )
{ {
msg_Warn( p_demux, msg_Warn( p_demux, "track[Id 0x%x] already selected",
"track[Id 0x%x] already selected",
p_track->i_track_ID ); p_track->i_track_ID );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -1767,8 +1755,7 @@ static int MP4_TrackSelect ( demux_t *p_demux, ...@@ -1767,8 +1755,7 @@ static int MP4_TrackSelect ( demux_t *p_demux,
return MP4_TrackSeek( p_demux, p_track, i_start ); return MP4_TrackSeek( p_demux, p_track, i_start );
} }
static void MP4_TrackUnselect(demux_t *p_demux, static void MP4_TrackUnselect( demux_t *p_demux, mp4_track_t *p_track )
mp4_track_t *p_track )
{ {
if( !p_track->b_ok ) if( !p_track->b_ok )
{ {
...@@ -1777,22 +1764,21 @@ static void MP4_TrackUnselect(demux_t *p_demux, ...@@ -1777,22 +1764,21 @@ static void MP4_TrackUnselect(demux_t *p_demux,
if( !p_track->b_selected ) if( !p_track->b_selected )
{ {
msg_Warn( p_demux, msg_Warn( p_demux, "track[Id 0x%x] already unselected",
"track[Id 0x%x] already unselected",
p_track->i_track_ID ); p_track->i_track_ID );
return; return;
} }
if( p_track->p_es ) if( p_track->p_es )
{ {
es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, p_track->p_es, VLC_FALSE ); es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE,
p_track->p_es, VLC_FALSE );
} }
p_track->b_selected = VLC_FALSE; p_track->b_selected = VLC_FALSE;
} }
static int MP4_TrackSeek ( demux_t *p_demux, static int MP4_TrackSeek( demux_t *p_demux, mp4_track_t *p_track,
mp4_track_t *p_track, mtime_t i_start )
mtime_t i_start )
{ {
uint32_t i_chunk; uint32_t i_chunk;
uint32_t i_sample; uint32_t i_sample;
...@@ -1802,21 +1788,22 @@ static int MP4_TrackSeek ( demux_t *p_demux, ...@@ -1802,21 +1788,22 @@ static int MP4_TrackSeek ( demux_t *p_demux,
return( VLC_EGENERIC ); return( VLC_EGENERIC );
} }
if( TrackTimeToSampleChunk( p_demux, p_track->b_selected = VLC_FALSE;
p_track, i_start,
if( TrackTimeToSampleChunk( p_demux, p_track, i_start,
&i_chunk, &i_sample ) ) &i_chunk, &i_sample ) )
{ {
msg_Warn( p_demux, msg_Warn( p_demux, "cannot select track[Id 0x%x]",
"cannot select track[Id 0x%x]",
p_track->i_track_ID ); p_track->i_track_ID );
return( VLC_EGENERIC ); return( VLC_EGENERIC );
} }
p_track->b_selected = VLC_TRUE; p_track->b_selected = VLC_TRUE;
if( TrackGotoChunkSample( p_demux, p_track, i_chunk, i_sample ) ) if( TrackGotoChunkSample( p_demux, p_track, i_chunk, i_sample ) ==
VLC_SUCCESS )
{ {
p_track->b_selected = VLC_FALSE; p_track->b_selected = VLC_TRUE;
} }
return( p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC ); return( p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC );
} }
...@@ -1827,7 +1814,7 @@ static int MP4_TrackSeek ( demux_t *p_demux, ...@@ -1827,7 +1814,7 @@ static int MP4_TrackSeek ( demux_t *p_demux,
* *
*/ */
#define QT_V0_MAX_SAMPLES 1500 #define QT_V0_MAX_SAMPLES 1500
static int MP4_TrackSampleSize( mp4_track_t *p_track ) static int MP4_TrackSampleSize( mp4_track_t *p_track )
{ {
int i_size; int i_size;
MP4_Box_data_sample_soun_t *p_soun; MP4_Box_data_sample_soun_t *p_soun;
...@@ -1954,12 +1941,11 @@ static int MP4_TrackNextSample( demux_t *p_demux, ...@@ -1954,12 +1941,11 @@ static int MP4_TrackNextSample( demux_t *p_demux,
p_track->chunk[p_track->i_chunk].i_sample_first + p_track->chunk[p_track->i_chunk].i_sample_first +
p_track->chunk[p_track->i_chunk].i_sample_count ) p_track->chunk[p_track->i_chunk].i_sample_count )
{ {
if( TrackGotoChunkSample( p_demux, if( TrackGotoChunkSample( p_demux, p_track, p_track->i_chunk + 1,
p_track,
p_track->i_chunk + 1,
p_track->i_sample ) ) p_track->i_sample ) )
{ {
msg_Warn( p_demux, "track[0x%x] will be disabled (cannot restart decoder)", p_track->i_track_ID ); msg_Warn( p_demux, "track[0x%x] will be disabled "
"(cannot restart decoder)", p_track->i_track_ID );
MP4_TrackUnselect( p_demux, p_track ); MP4_TrackUnselect( p_demux, p_track );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -1970,19 +1956,23 @@ static int MP4_TrackNextSample( demux_t *p_demux, ...@@ -1970,19 +1956,23 @@ static int MP4_TrackNextSample( demux_t *p_demux,
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst; MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
int64_t i_mvt = MP4_TrackGetPTS( p_demux, p_track ) * p_sys->i_timescale / (int64_t)1000000; int64_t i_mvt = MP4_TrackGetPTS( p_demux, p_track ) *
p_sys->i_timescale / (int64_t)1000000;
if( p_track->i_elst < elst->i_entry_count && if( p_track->i_elst < elst->i_entry_count &&
i_mvt >= p_track->i_elst_time + elst->i_segment_duration[p_track->i_elst] ) i_mvt >= p_track->i_elst_time +
elst->i_segment_duration[p_track->i_elst] )
{ {
MP4_TrackSetELST( p_demux, p_track, MP4_TrackGetPTS( p_demux, p_track ) ); MP4_TrackSetELST( p_demux, p_track,
MP4_TrackGetPTS( p_demux, p_track ) );
} }
} }
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk, int64_t i_time ) static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
int64_t i_time )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
int i_elst_last = tk->i_elst; int i_elst_last = tk->i_elst;
...@@ -2024,4 +2014,3 @@ static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk, int64_t i_time ...@@ -2024,4 +2014,3 @@ static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk, int64_t i_time
msg_Warn( p_demux, "elst old=%d new=%d", i_elst_last, tk->i_elst ); msg_Warn( p_demux, "elst old=%d new=%d", i_elst_last, tk->i_elst );
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment