[vlc-devel] [RFC PATCH 2/2] decoder: interruptible mwait

Thomas Guillem thomas at gllm.fr
Mon Nov 30 18:01:45 CET 2015



On Mon, Nov 30, 2015, at 18:00, Thomas Guillem wrote:
> mwait (called from Audio and SPU DecoderThread) can now be interrupted
> when
> flushing or closing.
> 
> This fixes a too long closing/flushing time when the next spu or audio
> block is
> too distant.
> ---
>  src/input/decoder.c | 34 +++++++++++++++++++++++++++++-----
>  1 file changed, 29 insertions(+), 5 deletions(-)
> 
> diff --git a/src/input/decoder.c b/src/input/decoder.c
> index 0f08198..314b00f 100644
> --- a/src/input/decoder.c
> +++ b/src/input/decoder.c
> @@ -30,6 +30,7 @@
>  # include "config.h"
>  #endif
>  #include <assert.h>
> +#include <errno.h>
>  
>  #include <vlc_common.h>
>  
> @@ -107,6 +108,7 @@ struct decoder_owner_sys_t
>      bool b_waiting;
>      bool b_first;
>      bool b_has_data;
> +    bool b_abort_timedwait;

Maybe b_abort_timedwait can be merged with flushing, but then you have
to set it to true when closing the decoder.

>  
>      /* Flushing */
>      bool flushing;
> @@ -619,6 +621,21 @@ static void DecoderWaitUnblock( decoder_t *p_dec )
>      }
>  }
>  
> +/* DecoderTimedWait: Interruptible wait
> + * Returns VLC_SUCCESS if wait was not interrupted, and VLC_EGENERIC
> otherwise */
> +static int DecoderTimedWait( decoder_t *p_dec, mtime_t deadline )
> +{
> +    decoder_owner_sys_t *p_owner = p_dec->p_owner;
> +
> +    vlc_fifo_Lock( p_owner->p_fifo );
> +    int ret = 0;
> +    while( !p_owner->b_abort_timedwait && ret != ETIMEDOUT )
> +        ret = vlc_fifo_TimedWait( p_owner->p_fifo, deadline );
> +    vlc_fifo_Unlock( p_owner->p_fifo );
> +
> +    return ret == ETIMEDOUT ? VLC_SUCCESS : VLC_EGENERIC;
> +}
> +
>  static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const
>  block_t *p )
>  {
>      if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )
> @@ -1022,7 +1039,8 @@ static void DecoderPlayAudio( decoder_t *p_dec,
> block_t *p_audio,
>  
>      if( p_aout == NULL || p_audio->i_pts <= VLC_TS_INVALID
>       || i_rate < INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE
> -     || i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
> +     || i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE
> +     || DecoderTimedWait( p_dec, p_audio->i_pts - AOUT_MAX_PREPARE_TIME
> ) )
>      {
>          msg_Dbg( p_dec, "discarded audio buffer" );
>          *pi_lost_sum += 1;
> @@ -1030,8 +1048,6 @@ static void DecoderPlayAudio( decoder_t *p_dec,
> block_t *p_audio,
>          return;
>      }
>  
> -    mwait( p_audio->i_pts - AOUT_MAX_PREPARE_TIME );
> -
>      if( aout_DecPlay( p_aout, p_audio, i_rate ) == 0 )
>          *pi_played_sum += 1;
>  
> @@ -1156,13 +1172,13 @@ static void DecoderPlaySpu( decoder_t *p_dec,
> subpicture_t *p_subpic )
>                    NULL, INT64_MAX );
>      vlc_mutex_unlock( &p_owner->lock );
>  
> -    if( p_subpic->i_start <= VLC_TS_INVALID )
> +    if( p_subpic->i_start <= VLC_TS_INVALID
> +     || DecoderTimedWait( p_dec, p_subpic->i_start -
> SPU_MAX_PREPARE_TIME ) )
>      {
>          subpicture_Delete( p_subpic );
>          return;
>      }
>  
> -    mwait( p_subpic->i_start - SPU_MAX_PREPARE_TIME );
>      vout_PutSubpicture( p_vout, p_subpic );
>  }
>  
> @@ -1351,6 +1367,7 @@ static void *DecoderThread( void *p_data )
>               * is called again. This will avoid a second useless flush
>               (but
>               * harmless). */
>              p_owner->flushing = false;
> +            p_owner->b_abort_timedwait = false;
>  
>              continue;
>          }
> @@ -1483,6 +1500,7 @@ static decoder_t * CreateDecoder( vlc_object_t
> *p_parent,
>      p_owner->b_draining = false;
>      atomic_init( &p_owner->drained, false );
>      p_owner->b_idle = false;
> +    p_owner->b_abort_timedwait = false;
>  
>      es_format_Init( &p_owner->fmt, UNKNOWN_ES, 0 );
>  
> @@ -1757,6 +1775,11 @@ void input_DecoderDelete( decoder_t *p_dec )
>  
>      vlc_cancel( p_owner->thread );
>  
> +    vlc_fifo_Lock( p_owner->p_fifo );
> +    p_owner->b_abort_timedwait = true;
> +    vlc_fifo_Signal( p_owner->p_fifo );
> +    vlc_fifo_Unlock( p_owner->p_fifo );
> +
>      /* Make sure we aren't waiting/decoding anymore */
>      vlc_mutex_lock( &p_owner->lock );
>      p_owner->b_waiting = false;
> @@ -1881,6 +1904,7 @@ void input_DecoderFlush( decoder_t *p_dec )
>       * dequeued by DecoderThread and there is no need to flush a second
>       time in
>       * a row. */
>      p_owner->flushing = true;
> +    p_owner->b_abort_timedwait = true;
>  
>      /* Flushing video decoder when paused: increment frames_countdown in
>      order
>       * to display one frame */
> -- 
> 2.1.4
> 


More information about the vlc-devel mailing list