vlc | branch: master | Francois Cartegnie <[email protected]> | Tue Sep 29 17:13:05 2020 +0200| [b752ffe13b605de5dfc40ff48ad4659dd4df0d15] | committer: Francois Cartegnie
es_out: fix flapping PREROLL flag on non dated packets Saves pts to perform preroll target comparison against. refs #25129 In some cases, the packets are sent interleaved with non dated packets SEND 1 SEND TS_INVALID (...) multiple times, simplified to 1 occurence PCR 1 SEND 719996 SEND TS_INVALID PCR 719996 SEND 1439992 SEND TS_INVALID PCR 1439992 SEND 2160008 SEND TS_INVALID PCR 2160008 Until preroll_end (file caching) is reached, all packets are flagged as PREROLL. Entering preroll has effect on audio output by flushing previous content, and silencing dropped buffers. Due to non dated interleaving, the stateless es_out keeps flipping PREROLL packets and triggering the in-stream PREROLL behaviour (like SET_NEXT_DISPLAY_TIME). The effect being (here with alsa) to re-enter preroll each time, extending decoder preroll until pts >= preroll_end and flushing decoders. Stream buffering done (1439 ms in 0 ms) ModuleThread_PlayAudio pts 1 preroll end -9223372036854775808 inserting 3840 zeroes / 80 ms cannot write samples: Relais brisé (pipe) ModuleThread_PlayAudio pts 120001 preroll end 9223372036854775807 (...) ModuleThread_PlayAudio pts 719996 preroll end 719996 end of audio preroll inserting 34804 zeroes / 725 ms 719996 ModuleThread_PlayAudio pts 839996 preroll end 9223372036854775807 (...) ModuleThread_PlayAudio pts 1439992 preroll end 1439992 end of audio preroll inserting 69172 zeroes / 1441 ms 1439992 ModuleThread_PlayAudio pts 1559992 preroll end 9223372036854775807 (...) ModuleThread_PlayAudio pts 2160008 preroll end 2160008 end of audio preroll inserting 103601 zeroes / 2158 ms 2160008 ModuleThread_PlayAudio pts 2280008 preroll end -9223372036854775808 (...) > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b752ffe13b605de5dfc40ff48ad4659dd4df0d15 --- src/input/es_out.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/input/es_out.c b/src/input/es_out.c index e4b840ed75..beae1e9b55 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -79,6 +79,8 @@ typedef struct vlc_clock_main_t *p_main_clock; vlc_clock_t *p_master_clock; + vlc_tick_t i_last_pcr; + vlc_meta_t *p_meta; struct vlc_list node; } es_out_pgrm_t; @@ -133,6 +135,7 @@ struct es_out_id_t /* Used by vlc_clock_cbs, need to be const during the lifetime of the clock */ bool master; + vlc_tick_t i_pts_level; vlc_tick_t delay; /* Fields for Video with CC */ @@ -896,6 +899,7 @@ static void EsOutChangePosition( es_out_t *out, bool b_flush ) input_SendEventCache( p_sys->p_input, 0.0 ); foreach_es_then_es_slaves(p_es) + { if( p_es->p_dec != NULL ) { if( b_flush ) @@ -907,12 +911,15 @@ static void EsOutChangePosition( es_out_t *out, bool b_flush ) vlc_input_decoder_StartWait( p_es->p_dec_record ); } } + p_es->i_pts_level = VLC_TICK_INVALID; + } es_out_pgrm_t *pgrm; vlc_list_foreach(pgrm, &p_sys->programs, node) { input_clock_Reset(pgrm->p_input_clock); vlc_clock_main_Reset(pgrm->p_main_clock); + pgrm->i_last_pcr = VLC_TICK_INVALID; } p_sys->b_buffering = true; @@ -1371,6 +1378,7 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in p_pgrm->i_es = 0; p_pgrm->b_selected = false; p_pgrm->b_scrambled = false; + p_pgrm->i_last_pcr = VLC_TICK_INVALID; p_pgrm->p_meta = NULL; p_pgrm->p_master_clock = NULL; @@ -2083,6 +2091,7 @@ static es_out_id_t *EsOutAddLocked( es_out_t *out, input_source_t *source, es->p_master = p_master; es->mouse_event_cb = NULL; es->mouse_event_userdata = NULL; + es->i_pts_level = VLC_TICK_INVALID; es->delay = INT64_MAX; vlc_list_append(&es->node, es->p_master ? &p_sys->es_slaves : &p_sys->es); @@ -2764,7 +2773,23 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) if( p_block->i_pts == VLC_TICK_INVALID ) i_date = p_block->i_dts; - if( i_date + p_block->i_length < p_sys->i_preroll_end ) + /* In some cases, the demuxer sends non dated packets. + We use interpolation, previous, or pcr value to compare with + preroll target timestamp */ + if( i_date == VLC_TICK_INVALID ) + { + if( es->i_pts_level != VLC_TICK_INVALID ) + i_date = es->i_pts_level; + else if( es->p_pgrm->i_last_pcr != VLC_TICK_INVALID ) + i_date = es->p_pgrm->i_last_pcr; + } + + if( i_date != VLC_TICK_INVALID ) + es->i_pts_level = i_date + p_block->i_length; + + /* If i_date is still invalid (first/all non dated), expect to be in preroll */ + if( i_date == VLC_TICK_INVALID || + es->i_pts_level < p_sys->i_preroll_end ) p_block->i_flags |= BLOCK_FLAG_PREROLL; } @@ -3169,6 +3194,8 @@ static int EsOutVaControlLocked( es_out_t *out, input_source_t *source, return VLC_EGENERIC; } + p_pgrm->i_last_pcr = i_pcr; + input_thread_private_t *priv = input_priv(p_sys->p_input); /* TODO do not use vlc_tick_now() but proper stream acquisition date */ _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
