[vlc-commits] [Git][videolan/vlc][3.0.x] 5 commits: input: add a workaround for next-frame
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Thu Feb 16 13:18:00 UTC 2023
Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC
Commits:
feaa1eea by Thomas Guillem at 2023-02-16T13:06:01+00:00
input: add a workaround for next-frame
Don't hack the buffering values, but fake the buffering state: tell the
input_thread to demux() until the vout has a picture.
Fixes #2951
(cherry picked from commit ea93b2c847880581b55c433b3aa0f315c6449cf3)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>
- - - - -
87b7b422 by Thomas Guillem at 2023-02-16T13:06:01+00:00
es_out: don't decode paused decoders
This avoid to fill up the decoder FIFO for nothing (ESes will be flushed
on resume).
(cherry picked from commit ff1316724f3520ae0220fd693b6b589d56240561)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>
- - - - -
cf041857 by Thomas Guillem at 2023-02-16T13:06:01+00:00
es_out: report timing when using next-frame
- - - - -
e9cf9077 by Thomas Guillem at 2023-02-16T13:06:01+00:00
es_out: don't pace when using next-frame
This fixes hiccups after few seconds when hitting next-frame in repeat mode.
- - - - -
8f30d641 by Thomas Guillem at 2023-02-16T13:06:01+00:00
input: seek to the current time when resuming from next-frame
This fixes video glitches. It won't work for all input sources (but it's
not critical).
- - - - -
3 changed files:
- src/input/es_out.c
- src/input/input.c
- src/input/input_internal.h
Changes:
=====================================
src/input/es_out.c
=====================================
@@ -163,6 +163,7 @@ struct es_out_sys_t
/* */
bool b_paused;
+ es_out_id_t *p_next_frame_es;
vlc_tick_t i_pause_date;
/* Current preroll */
@@ -198,6 +199,7 @@ static void EsDeleteInfo( es_out_t *, es_out_id_t *es );
static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update );
static void EsOutDecoderChangeDelay( es_out_t *out, es_out_id_t *p_es );
static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, vlc_tick_t i_date );
+static void EsOutChangePosition( es_out_t *out );
static void EsOutProgramChangePause( es_out_t *out, bool b_paused, vlc_tick_t i_date );
static void EsOutProgramsChangeRate( es_out_t *out );
static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced );
@@ -313,6 +315,7 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
p_sys->p_input = p_input;
p_sys->b_active = false;
+ p_sys->p_next_frame_es = NULL;
p_sys->i_mode = ES_OUT_MODE_NONE;
TAB_INIT( p_sys->i_pgrm, p_sys->pgrm );
@@ -410,7 +413,8 @@ static vlc_tick_t EsOutGetWakeup( es_out_t *out )
* to avoid too heavy buffering */
if( !input_priv(p_input)->b_can_pace_control ||
input_priv(p_input)->b_out_pace_control ||
- p_sys->b_buffering )
+ p_sys->b_buffering ||
+ p_sys->p_next_frame_es != NULL )
return 0;
return input_clock_GetWakeup( p_sys->p_pgrm->p_clock );
@@ -552,6 +556,16 @@ static int EsOutSetRecord( es_out_t *out, bool b_record )
return VLC_SUCCESS;
}
+
+static void EsOutStopNextFrame( es_out_t *out )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+ assert( p_sys->p_next_frame_es != NULL );
+ /* Flush every ES except the video one */
+ EsOutChangePosition( out );
+ p_sys->p_next_frame_es = NULL;
+}
+
static void EsOutChangePause( es_out_t *out, bool b_paused, vlc_tick_t i_date )
{
es_out_sys_t *p_sys = out->p_sys;
@@ -564,6 +578,9 @@ static void EsOutChangePause( es_out_t *out, bool b_paused, vlc_tick_t i_date )
}
else
{
+ if( p_sys->p_next_frame_es != NULL )
+ EsOutStopNextFrame( out );
+
if( p_sys->i_buffering_extra_initial > 0 )
{
vlc_tick_t i_stream_start;
@@ -808,71 +825,35 @@ static void EsOutProgramsChangeRate( es_out_t *out )
static void EsOutFrameNext( es_out_t *out )
{
es_out_sys_t *p_sys = out->p_sys;
- es_out_id_t *p_es_video = NULL;
-
- if( p_sys->b_buffering )
- {
- msg_Warn( p_sys->p_input, "buffering, ignoring 'frame next'" );
- return;
- }
assert( p_sys->b_paused );
- for( int i = 0; i < p_sys->i_es; i++ )
+ if( p_sys->p_next_frame_es == NULL )
{
- es_out_id_t *p_es = p_sys->es[i];
-
- if( p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
+ /* Don't use 'foreach_es_then_es_slaves': next-frame is not implemented
+ * on ES slaves */
+ for( int i = 0; i < p_sys->i_es; i++ )
{
- p_es_video = p_es;
- break;
+ es_out_id_t *p_es = p_sys->es[i];
+
+ if( p_es->p_master == NULL && p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
+ {
+ p_sys->p_next_frame_es = p_es;
+ break;
+ }
}
- }
- if( !p_es_video )
- {
- msg_Warn( p_sys->p_input, "No video track selected, ignoring 'frame next'" );
- return;
+ if( p_sys->p_next_frame_es == NULL )
+ {
+ msg_Warn( p_sys->p_input, "No video track selected, ignoring 'frame next'" );
+ return;
+ }
}
vlc_tick_t i_duration;
- input_DecoderFrameNext( p_es_video->p_dec, &i_duration );
+ input_DecoderFrameNext( p_sys->p_next_frame_es->p_dec, &i_duration );
msg_Dbg( out->p_sys->p_input, "EsOutFrameNext consummed %d ms", (int)(i_duration/1000) );
-
- if( i_duration <= 0 )
- i_duration = 40*1000;
-
- /* FIXME it is not a clean way ? */
- if( p_sys->i_buffering_extra_initial <= 0 )
- {
- vlc_tick_t i_stream_start;
- vlc_tick_t i_system_start;
- vlc_tick_t i_stream_duration;
- vlc_tick_t i_system_duration;
- int i_ret;
-
- i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
- &i_stream_start, &i_system_start,
- &i_stream_duration, &i_system_duration );
- if( i_ret )
- return;
-
- p_sys->i_buffering_extra_initial = 1 + i_stream_duration - p_sys->i_pts_delay; /* FIXME < 0 ? */
- p_sys->i_buffering_extra_system =
- p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial;
- }
-
- const int i_rate = input_clock_GetRate( p_sys->p_pgrm->p_clock );
-
- p_sys->b_buffering = true;
- p_sys->i_buffering_extra_system += i_duration;
- p_sys->i_buffering_extra_stream = p_sys->i_buffering_extra_initial +
- ( p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial ) *
- INPUT_RATE_DEFAULT / i_rate;
-
- p_sys->i_preroll_end = -1;
- p_sys->i_prev_stream_level = -1;
}
static vlc_tick_t EsOutGetBuffering( es_out_t *out )
{
@@ -1834,6 +1815,9 @@ static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update )
return;
}
+ if( p_sys->p_next_frame_es == es )
+ EsOutStopNextFrame( out );
+
if( es->p_master )
{
if( es->p_master->p_dec )
@@ -2083,6 +2067,14 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
vlc_mutex_lock( &p_sys->lock );
+ /* Drop all ESes except the video one in case of next-frame */
+ if( p_sys->p_next_frame_es != NULL && p_sys->p_next_frame_es != es )
+ {
+ block_Release( p_block );
+ vlc_mutex_unlock( &p_sys->lock );
+ return VLC_SUCCESS;
+ }
+
/* Mark preroll blocks */
if( p_sys->i_preroll_end >= 0 )
{
@@ -2538,6 +2530,9 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
}
else if( p_pgrm == p_sys->p_pgrm )
{
+ if( p_sys->p_next_frame_es != NULL )
+ return VLC_SUCCESS;
+
if( b_late && ( !input_priv(p_sys->p_input)->p_sout ||
!input_priv(p_sys->p_input)->b_out_pace_control ) )
{
@@ -2753,6 +2748,19 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
{
bool *pb = va_arg( args, bool* );
*pb = p_sys->b_buffering;
+ if( p_sys->b_buffering )
+ *pb = true;
+ else if( p_sys->p_next_frame_es != NULL )
+ {
+ /* The input thread will continue to call demux() if this control
+ * returns true. In case of next-frame, ask the input thread to
+ * continue to demux() until the vout has a picture to display. */
+ assert( p_sys->b_paused );
+ *pb = p_sys->p_next_frame_es->p_dec != NULL
+ && input_DecoderIsEmpty( p_sys->p_next_frame_es->p_dec );
+ }
+ else
+ *pb = false;
return VLC_SUCCESS;
}
@@ -2822,13 +2830,17 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
input_SendEventLength( p_sys->p_input, i_length );
- if( !p_sys->b_buffering )
+ if( !p_sys->b_buffering || p_sys->p_next_frame_es != NULL )
{
+ /* Also report times in next-frame mode without taking into
+ * account the buffering. */
+
vlc_tick_t i_delay;
/* Fix for buffering delay */
- if( !input_priv(p_sys->p_input)->p_sout ||
- !input_priv(p_sys->p_input)->b_out_pace_control )
+ if( p_sys->p_next_frame_es == NULL
+ && (!input_priv(p_sys->p_input)->p_sout ||
+ !input_priv(p_sys->p_input)->b_out_pace_control ) )
i_delay = EsOutGetBuffering( out );
else
i_delay = 0;
=====================================
src/input/input.c
=====================================
@@ -319,6 +319,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
priv->is_running = false;
priv->is_stopped = false;
priv->b_recording = false;
+ priv->b_next_frame = false;
priv->i_rate = INPUT_RATE_DEFAULT;
memset( &priv->bookmark, 0, sizeof(priv->bookmark) );
TAB_INIT( priv->i_bookmark, priv->pp_bookmark );
@@ -1803,6 +1804,17 @@ static void ControlUnpause( input_thread_t *p_input, vlc_tick_t i_control_date )
/* Switch to play */
input_ChangeState( p_input, PLAYING_S );
es_out_SetPauseState( input_priv(p_input)->p_es_out, false, false, i_control_date );
+
+ if( input_priv(p_input)->b_next_frame )
+ {
+ input_priv(p_input)->b_next_frame = false;
+ int64_t i_time;
+ if( demux_Control( input_priv(p_input)->master->p_demux, DEMUX_GET_TIME, &i_time ) == 0)
+ {
+ vlc_value_t val = { .i_int = i_time };
+ Control( p_input, INPUT_CONTROL_SET_TIME, val );
+ }
+ }
}
static void ViewpointApply( input_thread_t *p_input )
@@ -2365,6 +2377,7 @@ static bool Control( input_thread_t *p_input,
case INPUT_CONTROL_SET_FRAME_NEXT:
if( input_priv(p_input)->i_state == PAUSE_S )
{
+ input_priv(p_input)->b_next_frame = true;
es_out_SetFrameNext( input_priv(p_input)->p_es_out );
}
else if( input_priv(p_input)->i_state == PLAYING_S )
=====================================
src/input/input_internal.h
=====================================
@@ -97,6 +97,7 @@ typedef struct input_thread_private_t
bool is_running;
bool is_stopped;
bool b_recording;
+ bool b_next_frame;
int i_rate;
/* Playtime configuration and state */
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/62ccae7d09fa58cd65c5c2d2cab8f58017157468...8f30d6411fa95b60bf821f5fd02c4d7dcae34286
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/62ccae7d09fa58cd65c5c2d2cab8f58017157468...8f30d6411fa95b60bf821f5fd02c4d7dcae34286
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list