[vlc-devel] [RFC PATCH] decoder: remove input_DecoderWait
Thomas Guillem
thomas at gllm.fr
Wed Dec 16 17:39:46 CET 2015
The big issue when removing input_DecoderWait is that
input_clock_ChangeSystemOrigin is called right after the buffering stops
without waiting for all decoders. This leads to a desync between all decoders.
So, input_clock_ChangeSystemOrigin has to be called when all decoders are ready
to output something. The other big issue is that I don't really understand VLC
clocks functions.
My (crazy?) solution: instead of having the input thread waiting for all
decoders when pf_demux send a ES_OUT_SET_PCR control. The input thread will
test (in a non blocking way) if all decoders are ready. If they are not, the
input thread will continue (and pf_demux will be called again). If they are
ready, the input thread will call input_clock_ChangeSystemOrigin, and signal
all decoders to stop waiting.
Improvements:
- No more deadlocks (?)
- VLC now quits instantaneously when seeking
Regressions:
- This don't behave very well when the input is paused (but it's WIP).
- MKVs take more time to seek (input thread is waiting in ControlPop).
- /!\ record and timeshifting not tested
---
src/input/decoder.c | 146 +++++++++++++++++++++++-----------------------------
src/input/decoder.h | 10 ++--
src/input/es_out.c | 106 ++++++++++++++++++++++++++++----------
3 files changed, 150 insertions(+), 112 deletions(-)
diff --git a/src/input/decoder.c b/src/input/decoder.c
index e054b16..23d3555 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -87,8 +87,7 @@ struct decoder_owner_sys_t
/* Lock for communication with decoder thread */
vlc_mutex_t lock;
vlc_cond_t wait_request;
- vlc_cond_t wait_acknowledge;
- vlc_cond_t wait_fifo; /* TODO: merge with wait_acknowledge */
+ vlc_cond_t wait_fifo;
vlc_cond_t wait_timed;
/* -- These variables need locking on write(only) -- */
@@ -106,14 +105,13 @@ struct decoder_owner_sys_t
/* Waiting */
bool b_waiting;
- bool b_first;
- bool b_has_data;
+ bool b_ready;
+ bool b_has_input;
/* Flushing */
bool flushing;
bool b_draining;
atomic_bool drained;
- bool b_idle;
/* CC */
struct
@@ -603,18 +601,29 @@ void decoder_AbortPictures( decoder_t *p_dec, bool b_abort )
vlc_mutex_unlock( &p_owner->lock );
}
-static void DecoderWaitUnblock( decoder_t *p_dec )
+/* DecoderWaitUnblock: Wait for input_DecoderStopWait
+ * Returns VLC_SUCCESS if wait was not interrupted, and VLC_EGENERIC otherwise */
+static int DecoderWaitUnblock( decoder_t *p_dec )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vlc_assert_locked( &p_owner->lock );
- for( ;; )
+ if( !p_owner->b_has_input )
{
- if( !p_owner->b_waiting || !p_owner->b_has_data )
- break;
- vlc_cond_wait( &p_owner->wait_request, &p_owner->lock );
+ /* b_has_input is false. Therefore, the processed output is old
+ * corresponds to an input that was sent to the decoder before
+ * input_DecoderStartWait. The output should be discarded. */
+ return VLC_EGENERIC;
}
+
+ /* Signal that the Decoder is ready */
+ p_owner->b_ready = true;
+
+ while( p_owner->b_waiting && p_owner->b_ready )
+ vlc_cond_wait( &p_owner->wait_request, &p_owner->lock );
+
+ return p_owner->b_ready && p_owner->b_has_input ? VLC_SUCCESS : VLC_EGENERIC;
}
/* DecoderTimedWait: Interruptible wait
@@ -704,12 +713,6 @@ static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_waiting )
- {
- p_owner->b_has_data = true;
- vlc_cond_signal( &p_owner->wait_acknowledge );
- }
-
DecoderWaitUnblock( p_dec );
DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
&p_sout_block->i_length, NULL, INT64_MAX );
@@ -844,21 +847,14 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
/* */
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_waiting && !p_owner->b_first )
- {
- p_owner->b_has_data = true;
- vlc_cond_signal( &p_owner->wait_acknowledge );
- }
- bool b_first_after_wait = p_owner->b_waiting && p_owner->b_has_data;
-
- DecoderWaitUnblock( p_dec );
+ bool b_was_first = !p_owner->b_ready;
- if( p_owner->b_waiting )
+ if( DecoderWaitUnblock( p_dec ) )
{
- assert( p_owner->b_first );
- msg_Dbg( p_dec, "Received first picture" );
- p_owner->b_first = false;
- p_picture->b_force = true;
+ *pi_lost_sum += 1;
+ picture_Release( p_picture );
+ vlc_mutex_unlock( &p_owner->lock );
+ return;
}
const bool b_dated = p_picture->date > VLC_TS_INVALID;
@@ -866,6 +862,12 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
&i_rate, DECODER_BOGUS_VIDEO_DELAY );
+ if( b_was_first )
+ {
+ msg_Dbg( p_dec, "Received first picture" );
+ p_picture->b_force = true;
+ }
+
vlc_mutex_unlock( &p_owner->lock );
/* FIXME: The *input* FIFO should not be locked here. This will not work
@@ -879,7 +881,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
if( p_picture->b_force || p_picture->date > VLC_TS_INVALID )
/* FIXME: VLC_TS_INVALID -- verify video_output */
{
- if( i_rate != p_owner->i_last_rate || b_first_after_wait )
+ if( i_rate != p_owner->i_last_rate || b_was_first )
{
/* Be sure to not display old picture after our own */
vout_Flush( p_vout, p_picture->date );
@@ -1061,18 +1063,20 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
/* */
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_waiting )
- {
- p_owner->b_has_data = true;
- vlc_cond_signal( &p_owner->wait_acknowledge );
- }
/* */
int i_rate = INPUT_RATE_DEFAULT;
- DecoderWaitUnblock( p_dec );
+ if( DecoderWaitUnblock( p_dec ) )
+ {
+ *pi_lost_sum += 1;
+ block_Release( p_audio );
+ vlc_mutex_unlock( &p_owner->lock );
+ return;
+ }
DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length,
&i_rate, AOUT_MAX_ADVANCE_TIME );
+
vlc_mutex_unlock( &p_owner->lock );
audio_output_t *p_aout = p_owner->p_aout;
@@ -1242,13 +1246,12 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
/* */
vlc_mutex_lock( &p_owner->lock );
- if( p_owner->b_waiting )
+ if( DecoderWaitUnblock( p_dec ) )
{
- p_owner->b_has_data = true;
- vlc_cond_signal( &p_owner->wait_acknowledge );
+ subpicture_Delete( p_subpic );
+ vlc_mutex_unlock( &p_owner->lock );
+ return;
}
-
- DecoderWaitUnblock( p_dec );
DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
NULL, INT64_MAX );
vlc_mutex_unlock( &p_owner->lock );
@@ -1331,6 +1334,11 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
{
if( p_block )
block_Release( p_block );
+
+ /* In case of error, signal to the owner to don't wait for us */
+ vlc_mutex_lock( &p_owner->lock );
+ p_owner->b_ready = true;
+ vlc_mutex_unlock( &p_owner->lock );
return;
}
@@ -1343,6 +1351,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
if( p_block )
{
vlc_mutex_lock( &p_owner->lock );
+ p_owner->b_has_input = true;
DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
vlc_mutex_unlock( &p_owner->lock );
}
@@ -1478,9 +1487,7 @@ static void *DecoderThread( void *p_data )
if( p_owner->paused && p_owner->frames_countdown == 0 )
{ /* Wait for resumption from pause */
- p_owner->b_idle = true;
vlc_fifo_Wait( p_owner->p_fifo );
- p_owner->b_idle = false;
continue;
}
@@ -1492,9 +1499,7 @@ static void *DecoderThread( void *p_data )
{
if( likely(!p_owner->b_draining) )
{ /* Wait for a block to decode (or a request to drain) */
- p_owner->b_idle = true;
vlc_fifo_Wait( p_owner->p_fifo );
- p_owner->b_idle = false;
continue;
}
/* We have emptied the FIFO and there is a pending request to
@@ -1519,10 +1524,7 @@ static void *DecoderThread( void *p_data )
* sufficient. TODO? Wait for draining instead of polling. */
atomic_store( &p_owner->drained, (p_block == NULL) );
- vlc_mutex_lock( &p_owner->lock );
vlc_fifo_Lock( p_owner->p_fifo );
- vlc_cond_signal( &p_owner->wait_acknowledge );
- vlc_mutex_unlock( &p_owner->lock );
}
vlc_cleanup_pop();
vlc_assert_unreachable();
@@ -1577,13 +1579,12 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_owner->frames_countdown = 0;
p_owner->b_waiting = false;
- p_owner->b_first = true;
- p_owner->b_has_data = false;
+ p_owner->b_ready = false;
+ p_owner->b_has_input = false;
p_owner->flushing = false;
p_owner->b_draining = false;
atomic_init( &p_owner->drained, false );
- p_owner->b_idle = false;
es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
@@ -1598,7 +1599,6 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
vlc_mutex_init( &p_owner->lock );
vlc_cond_init( &p_owner->wait_request );
- vlc_cond_init( &p_owner->wait_acknowledge );
vlc_cond_init( &p_owner->wait_fifo );
vlc_cond_init( &p_owner->wait_timed );
@@ -1749,7 +1749,6 @@ static void DeleteDecoder( decoder_t * p_dec )
vlc_cond_destroy( &p_owner->wait_timed );
vlc_cond_destroy( &p_owner->wait_fifo );
- vlc_cond_destroy( &p_owner->wait_acknowledge );
vlc_cond_destroy( &p_owner->wait_request );
vlc_mutex_destroy( &p_owner->lock );
@@ -1959,6 +1958,17 @@ bool input_DecoderIsEmpty( decoder_t * p_dec )
return b_empty;
}
+bool input_DecoderIsReady( decoder_t * p_dec )
+{
+ decoder_owner_sys_t *p_owner = p_dec->p_owner;
+
+ vlc_mutex_lock( &p_owner->lock );
+ bool b_ready = p_owner->b_ready;
+ vlc_mutex_unlock( &p_owner->lock );
+
+ return b_ready;
+}
+
/**
* Signals that there are no further blocks to decode, and requests that the
* decoder drain all pending buffers. This is used to ensure that all
@@ -2121,8 +2131,8 @@ void input_DecoderStartWait( decoder_t *p_dec )
assert( !p_owner->b_waiting );
vlc_mutex_lock( &p_owner->lock );
- p_owner->b_first = true;
- p_owner->b_has_data = false;
+ p_owner->b_has_input = false;
+ p_owner->b_ready = false;
p_owner->b_waiting = true;
vlc_cond_signal( &p_owner->wait_request );
vlc_mutex_unlock( &p_owner->lock );
@@ -2140,32 +2150,6 @@ void input_DecoderStopWait( decoder_t *p_dec )
vlc_mutex_unlock( &p_owner->lock );
}
-void input_DecoderWait( decoder_t *p_dec )
-{
- decoder_owner_sys_t *p_owner = p_dec->p_owner;
-
- assert( p_owner->b_waiting );
-
- vlc_mutex_lock( &p_owner->lock );
- while( !p_owner->b_has_data )
- {
- /* Don't need to lock p_owner->paused since it's only modified by the
- * owner */
- if( p_owner->paused )
- break;
- vlc_fifo_Lock( p_owner->p_fifo );
- if( p_owner->b_idle && vlc_fifo_IsEmpty( p_owner->p_fifo ) )
- {
- msg_Err( p_dec, "buffer deadlock prevented" );
- vlc_fifo_Unlock( p_owner->p_fifo );
- break;
- }
- vlc_fifo_Unlock( p_owner->p_fifo );
- vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
- }
- vlc_mutex_unlock( &p_owner->lock );
-}
-
void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
diff --git a/src/input/decoder.h b/src/input/decoder.h
index f773eb7..3c2af36 100644
--- a/src/input/decoder.h
+++ b/src/input/decoder.h
@@ -49,11 +49,6 @@ void input_DecoderChangeDelay( decoder_t *, mtime_t i_delay );
void input_DecoderStartWait( decoder_t * );
/**
- * This function waits for the decoder to actually receive data.
- */
-void input_DecoderWait( decoder_t * );
-
-/**
* This function exits the waiting mode of the decoder.
*/
void input_DecoderStopWait( decoder_t * );
@@ -64,6 +59,11 @@ void input_DecoderStopWait( decoder_t * );
bool input_DecoderIsEmpty( decoder_t * );
/**
+ * This function returns true if the decoder is ready to output something.
+ */
+bool input_DecoderIsReady( decoder_t * );
+
+/**
* This function activates the request closed caption channel.
*/
int input_DecoderSetCcState( decoder_t *, bool b_decode, int i_channel );
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 72dbbde..dbd1e86 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -92,6 +92,7 @@ struct es_out_id_t
decoder_t *p_dec;
decoder_t *p_dec_record;
+ bool b_has_data;
/* Fields for Video with CC */
bool pb_cc_present[4];
@@ -162,9 +163,11 @@ struct es_out_sys_t
/* Used for buffering */
bool b_buffering;
+ bool b_decoders_waiting;
mtime_t i_buffering_extra_initial;
mtime_t i_buffering_extra_stream;
mtime_t i_buffering_extra_system;
+ mtime_t i_buffering_duration;
/* Record */
sout_instance_t *p_sout_record;
@@ -192,6 +195,7 @@ static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_da
static void EsOutProgramChangePause( es_out_t *out, bool b_paused, mtime_t i_date );
static void EsOutProgramsChangeRate( es_out_t *out );
static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced );
+static void EsOutDecodersWaitBuffering( es_out_t *out );
static char *LanguageGetName( const char *psz_code );
static char *LanguageGetCode( const char *psz_lang );
@@ -296,9 +300,12 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
p_sys->i_rate = i_rate;
p_sys->b_buffering = true;
+ p_sys->b_decoders_waiting = true;
p_sys->i_preroll_end = -1;
p_sys->i_prev_stream_level = -1;
+ p_sys->i_buffering_duration = 0;
+
return out;
}
@@ -368,6 +375,12 @@ static void EsOutTerminate( es_out_t *out )
input_SendEventMetaEpg( p_sys->p_input );
}
+static bool EsOutBuffering( es_out_t *out )
+{
+ es_out_sys_t *p_sys = out->p_sys;
+ return p_sys->b_buffering || p_sys->b_decoders_waiting;
+}
+
static mtime_t EsOutGetWakeup( es_out_t *out )
{
es_out_sys_t *p_sys = out->p_sys;
@@ -416,6 +429,22 @@ static bool EsOutDecodersIsEmpty( es_out_t *out )
return true;
}
+ if( p_sys->b_decoders_waiting )
+ {
+ for( int i = 0; i < p_sys->i_es; i++ )
+ {
+ es_out_id_t *p_es = p_sys->es[i];
+
+ if( !p_es->p_dec )
+ continue;
+
+ input_DecoderStopWait( p_es->p_dec );
+ if( p_es->p_dec_record )
+ input_DecoderStopWait( p_es->p_dec_record );
+ }
+ p_sys->b_decoders_waiting = false;
+ }
+
for( int i = 0; i < p_sys->i_es; i++ )
{
es_out_id_t *es = p_sys->es[i];
@@ -572,6 +601,7 @@ static void EsOutChangePosition( es_out_t *out )
es_out_sys_t *p_sys = out->p_sys;
input_SendEventCache( p_sys->p_input, 0.0 );
+ p_sys->i_buffering_duration = 0;
for( int i = 0; i < p_sys->i_es; i++ )
{
@@ -579,13 +609,20 @@ static void EsOutChangePosition( es_out_t *out )
if( p_es->p_dec != NULL )
{
- input_DecoderFlush( p_es->p_dec );
- if( !p_sys->b_buffering )
+ /* Stop waiting before flush to unblock decoders that are waiting */
+ if( p_sys->b_decoders_waiting )
{
- input_DecoderStartWait( p_es->p_dec );
+ input_DecoderStopWait( p_es->p_dec );
if( p_es->p_dec_record != NULL )
- input_DecoderStartWait( p_es->p_dec_record );
+ input_DecoderStopWait( p_es->p_dec_record );
}
+
+ input_DecoderFlush( p_es->p_dec );
+ p_es->b_has_data = false;
+
+ input_DecoderStartWait( p_es->p_dec );
+ if( p_es->p_dec_record != NULL )
+ input_DecoderStartWait( p_es->p_dec_record );
}
}
@@ -593,6 +630,7 @@ static void EsOutChangePosition( es_out_t *out )
input_clock_Reset( p_sys->pgrm[i]->p_clock );
p_sys->b_buffering = true;
+ p_sys->b_decoders_waiting = true;
p_sys->i_buffering_extra_initial = 0;
p_sys->i_buffering_extra_stream = 0;
p_sys->i_buffering_extra_system = 0;
@@ -600,8 +638,6 @@ static void EsOutChangePosition( es_out_t *out )
p_sys->i_prev_stream_level = -1;
}
-
-
static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
{
es_out_sys_t *p_sys = out->p_sys;
@@ -648,6 +684,15 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
p_sys->b_buffering = false;
p_sys->i_preroll_end = -1;
p_sys->i_prev_stream_level = -1;
+ p_sys->i_buffering_duration = i_buffering_duration;
+}
+
+/* EsOutDecodersWaitBuffering: Non blocking function that will signal all
+ * decoders to stop waiting when they are all ready to output.
+ */
+static void EsOutDecodersWaitBuffering( es_out_t *out )
+{
+ es_out_sys_t *p_sys = out->p_sys;
if( p_sys->i_buffering_extra_initial > 0 )
{
@@ -655,20 +700,18 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
return;
}
- const mtime_t i_decoder_buffering_start = mdate();
- for( int i = 0; i < p_sys->i_es; i++ )
+ /* Return if decoders are not ready */
+ if( !p_sys->b_paused )
{
- es_out_id_t *p_es = p_sys->es[i];
-
- if( !p_es->p_dec || p_es->fmt.i_cat == SPU_ES )
- continue;
- input_DecoderWait( p_es->p_dec );
- if( p_es->p_dec_record )
- input_DecoderWait( p_es->p_dec_record );
+ for( int i = 0; i < p_sys->i_es; i++ )
+ {
+ es_out_id_t *id = p_sys->es[i];
+ if( id->p_dec != NULL && id->b_has_data && !input_DecoderIsReady( id->p_dec ) )
+ return;
+ }
}
- msg_Dbg( p_sys->p_input, "Decoder wait done in %d ms",
- (int)(mdate() - i_decoder_buffering_start)/1000 );
+ msg_Dbg( p_sys->p_input, "Decoder wait done" );
/* Here is a good place to destroy unused vout with every demuxer */
input_resource_TerminateVout( p_sys->p_input->p->p_resource );
@@ -678,7 +721,7 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
const mtime_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : mdate();
input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_clock, true,
- i_current_date + i_wakeup_delay - i_buffering_duration );
+ i_current_date + i_wakeup_delay - p_sys->i_buffering_duration );
for( int i = 0; i < p_sys->i_es; i++ )
{
@@ -691,7 +734,9 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
if( p_es->p_dec_record )
input_DecoderStopWait( p_es->p_dec_record );
}
+ p_sys->b_decoders_waiting = false;
}
+
static void EsOutDecodersChangePause( es_out_t *out, bool b_paused, mtime_t i_date )
{
es_out_sys_t *p_sys = out->p_sys;
@@ -773,7 +818,7 @@ 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 )
+ if( EsOutBuffering( out ) )
{
msg_Warn( p_sys->p_input, "buffering, ignoring 'frame next'" );
return;
@@ -856,7 +901,7 @@ static mtime_t EsOutGetBuffering( es_out_t *out )
mtime_t i_delay;
- if( p_sys->b_buffering && p_sys->i_buffering_extra_initial <= 0 )
+ if( EsOutBuffering( out ) && p_sys->i_buffering_extra_initial <= 0 )
{
i_delay = i_stream_duration;
}
@@ -1503,6 +1548,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, const es_format_t *fmt )
es->psz_language = LanguageGetName( es->fmt.psz_language ); /* remember so we only need to do it once */
es->psz_language_code = LanguageGetCode( es->fmt.psz_language );
es->p_dec = NULL;
+ es->b_has_data = false;
es->p_dec_record = NULL;
for( i = 0; i < 4; i++ )
es->pb_cc_present[i] = false;
@@ -1558,6 +1604,7 @@ static bool EsIsSelected( es_out_id_t *es )
return es->p_dec != NULL;
}
}
+
static void EsCreateDecoder( es_out_t *out, es_out_id_t *p_es )
{
es_out_sys_t *p_sys = out->p_sys;
@@ -1988,6 +2035,8 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
}
/* Decode */
+ if( !( p_block->i_flags & BLOCK_FLAG_PREROLL ))
+ es->b_has_data = true;
if( es->p_dec_record )
{
block_t *p_dup = block_Duplicate( p_block );
@@ -2341,7 +2390,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
bool b_late;
input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input),
&b_late,
- p_sys->p_input->p->b_can_pace_control || p_sys->b_buffering,
+ p_sys->p_input->p->b_can_pace_control || EsOutBuffering( out ),
EsOutIsExtraBufferingAllowed( out ),
i_pcr, mdate() );
@@ -2353,7 +2402,12 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
/* Check buffering state on master clock update */
EsOutDecodersStopBuffering( out, false );
}
- else if( p_pgrm == p_sys->p_pgrm )
+ if( !p_sys->b_buffering && p_sys->b_decoders_waiting )
+ {
+ EsOutDecodersWaitBuffering( out );
+ }
+ if( !p_sys->b_buffering && !p_sys->b_decoders_waiting
+ && p_pgrm == p_sys->p_pgrm )
{
if( b_late && ( !p_sys->p_input->p->p_sout ||
!p_sys->p_input->p->b_out_pace_control ) )
@@ -2554,7 +2608,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
case ES_OUT_GET_BUFFERING:
{
bool *pb = va_arg( args, bool* );
- *pb = p_sys->b_buffering;
+ *pb = EsOutBuffering( out );
return VLC_SUCCESS;
}
@@ -2624,7 +2678,7 @@ 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( !EsOutBuffering( out ) )
{
mtime_t i_delay;
@@ -2671,7 +2725,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
case ES_OUT_GET_PCR_SYSTEM:
{
- if( p_sys->b_buffering )
+ if( EsOutBuffering( out ) )
return VLC_EGENERIC;
es_out_pgrm_t *p_pgrm = p_sys->p_pgrm;
@@ -2686,7 +2740,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
case ES_OUT_MODIFY_PCR_SYSTEM:
{
- if( p_sys->b_buffering )
+ if( EsOutBuffering( out ) )
return VLC_EGENERIC;
es_out_pgrm_t *p_pgrm = p_sys->p_pgrm;
--
2.1.4
More information about the vlc-devel
mailing list