[vlc-devel] [PATCH 1/2] [RFC] add a flush callback to decoders/packetizers

Steve Lhomme robux4 at videolabs.io
Thu Nov 19 11:19:15 CET 2015


I suppose we can also get rid of BLOCK_FLAG_CORE_PRIVATE_MASK and
BLOCK_FLAG_CORE_PRIVATE_SHIFT.

On Thu, Nov 19, 2015 at 11:13 AM, Steve Lhomme <robux4 at videolabs.io> wrote:
> When the decoder/packetizer doesn't provide a flush callback, a block with
> BLOCK_FLAG_DISCONTINUITY and BLOCK_FLAG_CORRUPTED is pushed downstream.
>
> --
> replaces https://patches.videolan.org/patch/10869/
>
> We do not push internally a fake block marked for flushing anymore.
>
> The legacy flush block is handled like a regular block via the normal processing.
>
> A separate patch where packetizers flush properly is needed (not all of them do).
> ---
>  include/vlc_codec.h |   1 +
>  src/input/decoder.c | 132 ++++++++++++++++++++++++++--------------------------
>  src/input/decoder.h |   2 -
>  3 files changed, 68 insertions(+), 67 deletions(-)
>
> diff --git a/include/vlc_codec.h b/include/vlc_codec.h
> index 1a2baa2..81090ba 100644
> --- a/include/vlc_codec.h
> +++ b/include/vlc_codec.h
> @@ -70,6 +70,7 @@ struct decoder_t
>      block_t *           ( * pf_decode_audio )( decoder_t *, block_t ** );
>      subpicture_t *      ( * pf_decode_sub)   ( decoder_t *, block_t ** );
>      block_t *           ( * pf_packetize )   ( decoder_t *, block_t ** );
> +    void                ( * pf_flush ) ( decoder_t * );
>
>      /* Closed Caption (CEA 608/708) extraction.
>       * If set, it *may* be called after pf_decode_video/pf_packetize
> diff --git a/src/input/decoder.c b/src/input/decoder.c
> index f0efdbe..101dda6 100644
> --- a/src/input/decoder.c
> +++ b/src/input/decoder.c
> @@ -147,6 +147,7 @@ static int LoadDecoder( decoder_t *p_dec, bool b_packetizer,
>      p_dec->pf_decode_sub = NULL;
>      p_dec->pf_get_cc = NULL;
>      p_dec->pf_packetize = NULL;
> +    p_dec->pf_flush = NULL;
>
>      es_format_Copy( &p_dec->fmt_in, p_fmt );
>      es_format_Init( &p_dec->fmt_out, UNKNOWN_ES, 0 );
> @@ -216,8 +217,7 @@ static block_t *DecoderBlockFlushNew()
>          return NULL;
>
>      p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY |
> -                       BLOCK_FLAG_CORRUPTED |
> -                       BLOCK_FLAG_CORE_FLUSH;
> +                       BLOCK_FLAG_CORRUPTED;
>      memset( p_null->p_buffer, 0, p_null->i_buffer );
>
>      return p_null;
> @@ -940,7 +940,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
>
>  /* This function process a video block
>   */
> -static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flush )
> +static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block )
>  {
>      decoder_owner_sys_t *p_owner = p_dec->p_owner;
>
> @@ -981,22 +981,11 @@ static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flus
>                  p_packetized_block = p_next;
>              }
>          }
> -        /* The packetizer does not output a block that tell the decoder to flush
> -         * do it ourself */
> -        if( b_flush )
> -        {
> -            block_t *p_null = DecoderBlockFlushNew();
> -            if( p_null )
> -                DecoderDecodeVideo( p_dec, p_null );
> -        }
>      }
>      else
>      {
>          DecoderDecodeVideo( p_dec, p_block );
>      }
> -
> -    if( b_flush && p_owner->p_vout )
> -        vout_Flush( p_owner->p_vout, VLC_TS_INVALID+1 );
>  }
>
>  static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
> @@ -1095,7 +1084,7 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
>
>  /* This function process a audio block
>   */
> -static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block, bool b_flush )
> +static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block )
>  {
>      decoder_owner_sys_t *p_owner = p_dec->p_owner;
>
> @@ -1133,22 +1122,11 @@ static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block, bool b_flus
>                  p_packetized_block = p_next;
>              }
>          }
> -        /* The packetizer does not output a block that tell the decoder to flush
> -         * do it ourself */
> -        if( b_flush )
> -        {
> -            block_t *p_null = DecoderBlockFlushNew();
> -            if( p_null )
> -                DecoderDecodeAudio( p_dec, p_null );
> -        }
>      }
>      else
>      {
>          DecoderDecodeAudio( p_dec, p_block );
>      }
> -
> -    if( b_flush && p_owner->p_aout )
> -        aout_DecFlush( p_owner->p_aout, false );
>  }
>
>  static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
> @@ -1190,7 +1168,7 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
>
>  /* This function process a subtitle block
>   */
> -static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush )
> +static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block )
>  {
>      decoder_owner_sys_t *p_owner = p_dec->p_owner;
>
> @@ -1229,17 +1207,6 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
>          if( p_vout )
>              vlc_object_release( p_vout );
>      }
> -
> -    if( b_flush && p_owner->p_spu_vout )
> -    {
> -        p_vout = input_resource_HoldVout( p_owner->p_resource );
> -
> -        if( p_vout && p_owner->p_spu_vout == p_vout )
> -            vout_FlushSubpictureChannel( p_vout, p_owner->i_spu_channel );
> -
> -        if( p_vout )
> -            vlc_object_release( p_vout );
> -    }
>  }
>
>  /**
> @@ -1252,7 +1219,6 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
>  static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
>  {
>      decoder_owner_sys_t *p_owner = p_dec->p_owner;
> -    const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH);
>
>      if( p_dec->b_error )
>      {
> @@ -1263,45 +1229,32 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
>
>      if( p_block && p_block->i_buffer <= 0 )
>      {
> -        assert( !b_flush_request );
>          block_Release( p_block );
>          return;
>      }
>
> +    if( p_block )
> +        DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
> +
>  #ifdef ENABLE_SOUT
>      if( p_owner->b_packetizer )
>      {
> -        if( p_block )
> -            p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK;
> -
>          DecoderProcessSout( p_dec, p_block );
>      }
>      else
>  #endif
>      {
> -        bool b_flush = false;
> -
> -        if( p_block )
> -        {
> -            const bool b_flushing = p_owner->i_preroll_end == INT64_MAX;
> -            DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
> -
> -            b_flush = !b_flushing && b_flush_request;
> -
> -            p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK;
> -        }
> -
>          if( p_dec->fmt_out.i_cat == AUDIO_ES )
>          {
> -            DecoderProcessAudio( p_dec, p_block, b_flush );
> +            DecoderProcessAudio( p_dec, p_block );
>          }
>          else if( p_dec->fmt_out.i_cat == VIDEO_ES )
>          {
> -            DecoderProcessVideo( p_dec, p_block, b_flush );
> +            DecoderProcessVideo( p_dec, p_block );
>          }
>          else if( p_dec->fmt_out.i_cat == SPU_ES )
>          {
> -            DecoderProcessSpu( p_dec, p_block, b_flush );
> +            DecoderProcessSpu( p_dec, p_block );
>          }
>          else
>          {
> @@ -1311,6 +1264,61 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
>      }
>  }
>
> +static void DecoderFlush( decoder_t *p_dec )
> +{
> +    if ( p_dec->pf_flush )
> +        p_dec->pf_flush( p_dec );
> +    else
> +    {
> +        /* legacy call, pass a CORRUPTED + DISCONTINUITY block */
> +        block_t *p_flush = DecoderBlockFlushNew();
> +        if( unlikely( p_flush == NULL ) )
> +        {
> +            msg_Err( p_dec, "cannot flush" );
> +            return;
> +        }
> +        DecoderProcess( p_dec, p_flush );
> +    }
> +}
> +
> +static void DecoderProcessFlush( decoder_t *p_dec )
> +{
> +    decoder_owner_sys_t *p_owner = p_dec->p_owner;
> +
> +    if( p_dec->b_error )
> +        return;
> +
> +    if ( p_owner->i_preroll_end == INT64_MAX )
> +        return;
> +
> +    if ( p_owner->p_packetizer )
> +        DecoderFlush( p_owner->p_packetizer );
> +    DecoderFlush( p_dec );
> +
> +    if( p_dec->fmt_out.i_cat == AUDIO_ES )
> +    {
> +        if( p_owner->p_aout )
> +            aout_DecFlush( p_owner->p_aout, false );
> +    }
> +    else if( p_dec->fmt_out.i_cat == VIDEO_ES )
> +    {
> +        if( p_owner->p_vout )
> +            vout_Flush( p_owner->p_vout, VLC_TS_INVALID+1 );
> +    }
> +    else if( p_dec->fmt_out.i_cat == SPU_ES )
> +    {
> +        if( p_owner->p_spu_vout )
> +        {
> +            vout_thread_t *p_vout = input_resource_HoldVout( p_owner->p_resource );
> +
> +            if( p_vout && p_owner->p_spu_vout == p_vout )
> +                vout_FlushSubpictureChannel( p_vout, p_owner->i_spu_channel );
> +
> +            if( p_vout )
> +                vlc_object_release( p_vout );
> +        }
> +    }
> +}
>
>  /**
>   * The decoding main loop
> @@ -1334,16 +1342,10 @@ static void *DecoderThread( void *p_data )
>               * for the sake of flushing (glitches could otherwise happen). */
>              int canc = vlc_savecancel();
>
> -            /* TODO: add a flush callback to decoder, do not depend on an
> -             * allocated block */
> -            block_t *dummy = DecoderBlockFlushNew();
> -            if( unlikely(dummy == NULL) )
> -                msg_Err( p_dec, "cannot flush" );
> -
>              vlc_fifo_Unlock( p_owner->p_fifo );
>
>              /* Flush the decoder (and the output) */
> -            DecoderProcess( p_dec, dummy );
> +            DecoderProcessFlush( p_dec );
>
>              vlc_fifo_Lock( p_owner->p_fifo );
>              vlc_restorecancel( canc );
> diff --git a/src/input/decoder.h b/src/input/decoder.h
> index 8508874..f773eb7 100644
> --- a/src/input/decoder.h
> +++ b/src/input/decoder.h
> @@ -28,8 +28,6 @@
>  #include <vlc_common.h>
>  #include <vlc_codec.h>
>
> -#define BLOCK_FLAG_CORE_FLUSH (1 <<BLOCK_FLAG_CORE_PRIVATE_SHIFT)
> -
>  decoder_t *input_DecoderNew( input_thread_t *, es_format_t *, input_clock_t *,
>                               sout_instance_t * ) VLC_USED;
>
> --
> 2.6.3
>


More information about the vlc-devel mailing list