1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-28 23:09:59 +02:00

decoder: update the state directly when creating an output

Threading changed, it is now possible.

This fixes the video or audio output that can render the first frames in
the initial state, leading to audio/video glitches (if a delay is
applied after).

For example, audio with clock-master=input:

[00007fc4a4311760] main decoder: vlc_input_decoder_ChangeDelay():
000055ad16120e60] main audio output error: Play in 133193
[000055ad16120e60] main audio output error: Play in 156331
[000055ad16120e60] main audio output error: Play in 179508
[000055ad16120e60] main audio output error: Play in 202699
[000055ad16120e60] main audio output error: Play in 225891
[00007fc4a4311760] main decoder: changing delay(2): -2000000
[000055ad16120e60] main audio output error: Play in -1750921

Refs #27918
This commit is contained in:
Thomas Guillem 2023-03-09 16:13:36 +01:00 committed by Jean-Baptiste Kempf
parent a89b5d6b61
commit 63488e047d

View File

@ -193,12 +193,11 @@ struct vlc_input_decoder_t
#define PREROLL_FORCED VLC_TICK_MAX
/* Pause & Rate */
bool reset_out_state;
vlc_tick_t pause_date;
vlc_tick_t delay;
vlc_tick_t delay, output_delay;
float rate, output_rate;
unsigned frames_countdown;
bool paused;
bool paused, output_paused;
bool error;
@ -284,6 +283,7 @@ static void Decoder_ChangeOutputPause( vlc_input_decoder_t *p_owner, bool paused
default:
vlc_assert_unreachable();
}
p_owner->output_paused = paused;
}
static void Decoder_ChangeOutputRate( vlc_input_decoder_t *p_owner, float rate )
@ -345,6 +345,19 @@ static void Decoder_ChangeOutputDelay( vlc_input_decoder_t *p_owner, vlc_tick_t
default:
vlc_assert_unreachable();
}
p_owner->output_delay = delay;
}
static void Decoder_UpdateOutState(vlc_input_decoder_t *owner)
{
if (owner->paused)
Decoder_ChangeOutputPause(owner, owner->paused, owner->pause_date);
if (owner->rate != 1.f)
Decoder_ChangeOutputRate(owner, owner->rate);
if (owner->delay != 0)
Decoder_ChangeOutputDelay(owner, owner->delay);
}
/**
@ -569,7 +582,7 @@ static int ModuleThread_UpdateAudioFormat( decoder_t *p_dec )
p_dec->fmt_out.audio.i_frame_length =
p_owner->fmt.audio.i_frame_length;
p_owner->reset_out_state = true;
Decoder_UpdateOutState( p_owner );
vlc_fifo_Unlock( p_owner->p_fifo );
}
return 0;
@ -660,7 +673,7 @@ static int ModuleThread_UpdateVideoFormat( decoder_t *p_dec, vlc_video_context *
if (vout_state == INPUT_RESOURCE_VOUT_STARTED)
{
p_owner->reset_out_state = true;
Decoder_UpdateOutState( p_owner );
vlc_fifo_Unlock(p_owner->p_fifo);
decoder_Notify(p_owner, on_vout_started, p_vout, p_owner->vout_order);
@ -1687,9 +1700,6 @@ static void DecoderThread_Flush( vlc_input_decoder_t *p_owner )
static void *DecoderThread( void *p_data )
{
vlc_input_decoder_t *p_owner = (vlc_input_decoder_t *)p_data;
float rate = 1.f;
vlc_tick_t delay = 0;
bool paused = false;
const char *thread_name;
switch (p_owner->dec.fmt_in->i_cat)
@ -1726,37 +1736,21 @@ static void *DecoderThread( void *p_data )
continue;
}
/* Reset the original pause/rate state when a new aout/vout is created:
* this will trigger the Decoder_ChangeOutputPause/Decoder_ChangeOutputRate code path
* if needed. */
if( p_owner->reset_out_state )
{
rate = 1.f;
paused = false;
delay = 0;
p_owner->reset_out_state = false;
}
if( paused != p_owner->paused )
if( p_owner->paused != p_owner->output_paused )
{ /* Update playing/paused status of the output */
vlc_tick_t date = p_owner->pause_date;
paused = p_owner->paused;
Decoder_ChangeOutputPause( p_owner, paused, date );
Decoder_ChangeOutputPause( p_owner, p_owner->paused, p_owner->pause_date );
continue;
}
if( rate != p_owner->rate )
if( p_owner->rate != p_owner->output_rate )
{
rate = p_owner->rate;
Decoder_ChangeOutputRate( p_owner, rate );
Decoder_ChangeOutputRate( p_owner, p_owner->rate );
continue;
}
if( delay != p_owner->delay )
if( p_owner->delay != p_owner->output_delay )
{
delay = p_owner->delay;
Decoder_ChangeOutputDelay( p_owner, delay );
Decoder_ChangeOutputDelay( p_owner, p_owner->delay );
continue;
}
@ -1892,10 +1886,9 @@ CreateDecoder( vlc_object_t *p_parent, const struct vlc_input_decoder_cfg *cfg )
p_owner->b_fmt_description = false;
p_owner->p_description = NULL;
p_owner->reset_out_state = false;
p_owner->delay = 0;
p_owner->output_delay = p_owner->delay = 0;
p_owner->output_rate = p_owner->rate = 1.f;
p_owner->paused = false;
p_owner->output_paused = p_owner->paused = false;
p_owner->pause_date = VLC_TICK_INVALID;
p_owner->frames_countdown = 0;