[vlc-devel] [PATCH] decoder: remove input thread and ES dependency

Thomas Guillem thomas at gllm.fr
Thu Jun 20 14:15:47 CEST 2019


LGTM.

On Thu, Jun 20, 2019, at 13:56, Romain Vimont wrote:
> As suggested by RĂ©mi:
> 
> > the decoder should use opaque callbacks provided by the ES out rather
> > than "see" the input and the ES.
> 
> <https://mailman.videolan.org/pipermail/vlc-devel/2019-May/125088.html>
> ---
>  src/input/decoder.c | 118 ++++++++++++----------------------
>  src/input/decoder.h |  28 +++++++-
>  src/input/es_out.c  | 152 ++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 213 insertions(+), 85 deletions(-)
> 
> diff --git a/src/input/decoder.c b/src/input/decoder.c
> index 3b19b51d66..e8b74cb84f 100644
> --- a/src/input/decoder.c
> +++ b/src/input/decoder.c
> @@ -45,10 +45,8 @@
>  
>  #include "audio_output/aout_internal.h"
>  #include "stream_output/stream_output.h"
> -#include "input_internal.h"
>  #include "../clock/clock.h"
>  #include "decoder.h"
> -#include "event.h"
>  #include "resource.h"
>  
>  #include "../video_output/vout_internal.h"
> @@ -66,11 +64,12 @@ enum reload
>  struct decoder_owner
>  {
>      decoder_t        dec;
> -    input_thread_t  *p_input;
> -    vlc_es_id_t     *id;
>      input_resource_t*p_resource;
>      vlc_clock_t     *p_clock;
>  
> +    const struct decoder_callbacks *cbs;
> +    void *cbs_userdata;
> +
>      ssize_t          i_spu_channel;
>      int64_t          i_spu_order;
>  
> @@ -156,6 +155,11 @@ struct decoder_owner
>  #define DECODER_SPU_VOUT_WAIT_DURATION   VLC_TICK_FROM_MS(200)
>  #define BLOCK_FLAG_CORE_PRIVATE_RELOADED (1 << BLOCK_FLAG_CORE_PRIVATE_SHIFT)
>  
> +#define decoder_Notify(decoder_priv, event, ...) \
> +    if (decoder_priv->cbs && decoder_priv->cbs->event) \
> +        decoder_priv->cbs->event(&decoder_priv->dec, ##__VA_ARGS__, \
> +                                 decoder_priv->cbs_userdata);
> +
>  static inline struct decoder_owner *dec_get_owner( decoder_t *p_dec )
>  {
>      return container_of( p_dec, struct decoder_owner, dec );
> @@ -542,13 +546,8 @@ static int vout_update_format( decoder_t *p_dec )
>                  .dpb_size = dpb_size + p_dec->i_extra_picture_buffers + 1,
>                  .mouse_event = MouseEvent, .mouse_opaque = p_dec
>              } );
> -        if (p_vout && p_owner->p_input)
> -            input_SendEventVout(p_owner->p_input,
> -                &(struct vlc_input_event_vout) {
> -                    .action = VLC_INPUT_EVENT_VOUT_ADDED,
> -                    .vout = p_vout,
> -                    .id = p_owner->id,
> -                });
> +        if (p_vout)
> +            decoder_Notify(p_owner, on_vout_added, p_vout);
>  
>          vlc_mutex_lock( &p_owner->lock );
>          p_owner->p_vout = p_vout;
> @@ -664,12 +663,11 @@ static int DecoderGetInputAttachments( decoder_t *p_dec,
>                                         int *pi_attachment )
>  {
>      struct decoder_owner *p_owner = dec_get_owner( p_dec );
> -    input_thread_t *p_input = p_owner->p_input;
> -
> -    if( unlikely(p_input == NULL) )
> +    if (!p_owner->cbs || !p_owner->cbs->get_attachments)
>          return VLC_ENOOBJ;
>  
> -    int ret = input_GetAttachments( p_input, ppp_attachment );
> +    int ret = p_owner->cbs->get_attachments(p_dec, ppp_attachment,
> +                                            p_owner->cbs_userdata);
>      if (ret < 0)
>          return VLC_EGENERIC;
>      *pi_attachment = ret;
> @@ -1059,13 +1057,8 @@ discard:
>  static void DecoderUpdateStatVideo( struct decoder_owner *p_owner,
>                                      unsigned decoded, unsigned lost )
>  {
> -    input_thread_t *p_input = p_owner->p_input;
>      unsigned displayed = 0;
>  
> -    /* Update ugly stat */
> -    if( p_input == NULL )
> -        return;
> -
>      if( p_owner->p_vout != NULL )
>      {
>          unsigned vout_lost = 0;
> @@ -1074,17 +1067,7 @@ static void DecoderUpdateStatVideo( struct 
> decoder_owner *p_owner,
>          lost += vout_lost;
>      }
>  
> -    struct input_stats *stats = input_priv(p_input)->stats;
> -
> -    if( stats != NULL )
> -    {
> -        atomic_fetch_add_explicit(&stats->decoded_video, decoded,
> -                                  memory_order_relaxed);
> -        atomic_fetch_add_explicit(&stats->lost_pictures, lost,
> -                                  memory_order_relaxed);
> -        atomic_fetch_add_explicit(&stats->displayed_pictures, displayed,
> -                                  memory_order_relaxed);
> -    }
> +    decoder_Notify(p_owner, on_new_video_stats, decoded, lost, displayed);
>  }
>  
>  static void DecoderQueueVideo( decoder_t *p_dec, picture_t *p_pic )
> @@ -1119,11 +1102,7 @@ static void DecoderQueueThumbnail( decoder_t 
> *p_dec, picture_t *p_pic )
>      struct decoder_owner *p_owner = dec_get_owner( p_dec );
>      if( p_owner->b_first )
>      {
> -        assert(p_owner->p_input);
> -        input_SendEvent(p_owner->p_input, &(struct vlc_input_event) {
> -            .type = INPUT_EVENT_THUMBNAIL_READY,
> -            .thumbnail = p_pic
> -        });
> +        decoder_Notify(p_owner, on_thumbnail_ready, p_pic);
>          p_owner->b_first = false;
>      }
>      picture_Release( p_pic );
> @@ -1209,13 +1188,8 @@ static void DecoderPlayAudio( decoder_t *p_dec, 
> block_t *p_audio,
>  static void DecoderUpdateStatAudio( struct decoder_owner *p_owner,
>                                      unsigned decoded, unsigned lost )
>  {
> -    input_thread_t *p_input = p_owner->p_input;
>      unsigned played = 0;
>  
> -    /* Update ugly stat */
> -    if( p_input == NULL )
> -        return;
> -
>      if( p_owner->p_aout != NULL )
>      {
>          unsigned aout_lost;
> @@ -1224,17 +1198,7 @@ static void DecoderUpdateStatAudio( struct 
> decoder_owner *p_owner,
>          lost += aout_lost;
>      }
>  
> -    struct input_stats *stats = input_priv(p_input)->stats;
> -
> -    if( stats != NULL )
> -    {
> -        atomic_fetch_add_explicit(&stats->lost_abuffers, lost,
> -                                  memory_order_relaxed);
> -        atomic_fetch_add_explicit(&stats->played_abuffers, played,
> -                                  memory_order_relaxed);
> -        atomic_fetch_add_explicit(&stats->decoded_audio, decoded,
> -                                  memory_order_relaxed);
> -    }
> +    decoder_Notify(p_owner, on_new_audio_stats, decoded, lost, played);
>  }
>  
>  static void DecoderQueueAudio( decoder_t *p_dec, block_t *p_aout_buf )
> @@ -1782,10 +1746,11 @@ static const struct decoder_owner_callbacks 
> dec_spu_cbs =
>   * \return the decoder object
>   */
>  static decoder_t * CreateDecoder( vlc_object_t *p_parent,
> -                                  input_thread_t *p_input, vlc_es_id_t 
> *id,
>                                    const es_format_t *fmt, vlc_clock_t 
> *p_clock,
>                                    input_resource_t *p_resource,
> -                                  sout_instance_t *p_sout )
> +                                  sout_instance_t *p_sout, bool 
> b_thumbnailing,
> +                                  const struct decoder_callbacks *cbs,
> +                                  void *cbs_userdata )
>  {
>      decoder_t *p_dec;
>      struct decoder_owner *p_owner;
> @@ -1795,11 +1760,11 @@ static decoder_t * CreateDecoder( vlc_object_t 
> *p_parent,
>          return NULL;
>      p_dec = &p_owner->dec;
>  
> -    p_owner->id = id;
>      p_owner->p_clock = p_clock;
>      p_owner->i_preroll_end = (vlc_tick_t)INT64_MIN;
> -    p_owner->p_input = p_input;
>      p_owner->p_resource = p_resource;
> +    p_owner->cbs = cbs;
> +    p_owner->cbs_userdata = cbs_userdata;
>      p_owner->p_aout = NULL;
>      p_owner->p_vout = NULL;
>      p_owner->i_spu_channel = -1;
> @@ -1872,7 +1837,7 @@ static decoder_t * CreateDecoder( vlc_object_t 
> *p_parent,
>      switch( fmt->i_cat )
>      {
>          case VIDEO_ES:
> -            if( !p_input || !input_priv( p_input )->b_thumbnailing )
> +            if( !b_thumbnailing )
>                  p_dec->cbs = &dec_video_cbs;
>              else
>                  p_dec->cbs = &dec_thumbnailer_cbs;
> @@ -1974,13 +1939,7 @@ static void DeleteDecoder( decoder_t * p_dec )
>                  /* Reset the cancel state that was set before joining 
> the decoder
>                   * thread */
>                  vout_Cancel(vout, false);
> -                if (p_owner->p_input)
> -                    input_SendEventVout(p_owner->p_input,
> -                        &(struct vlc_input_event_vout) {
> -                            .action = VLC_INPUT_EVENT_VOUT_DELETED,
> -                            .vout = vout,
> -                            .id = p_owner->id,
> -                        });
> +                decoder_Notify(p_owner, on_vout_deleted, vout);
>                  input_resource_PutVout(p_owner->p_resource, vout);
>              }
>              break;
> @@ -2038,17 +1997,19 @@ static void DecoderUnsupportedCodec( decoder_t 
> *p_dec, const es_format_t *fmt, b
>  }
>  
>  /* TODO: pass p_sout through p_resource? -- Courmisch */
> -static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t 
> *p_input,
> -                               vlc_es_id_t *id, const es_format_t *fmt,
> +static decoder_t *decoder_New( vlc_object_t *p_parent, const 
> es_format_t *fmt,
>                                 vlc_clock_t *p_clock, input_resource_t 
> *p_resource,
> -                               sout_instance_t *p_sout  )
> +                               sout_instance_t *p_sout, bool 
> thumbnailing,
> +                               const struct decoder_callbacks *cbs,
> +                               void *userdata)
>  {
>      decoder_t *p_dec = NULL;
>      const char *psz_type = p_sout ? N_("packetizer") : N_("decoder");
>      int i_priority;
>  
>      /* Create the decoder configuration structure */
> -    p_dec = CreateDecoder( p_parent, p_input, id, fmt, p_clock, 
> p_resource, p_sout );
> +    p_dec = CreateDecoder( p_parent, fmt, p_clock, p_resource, p_sout,
> +                           thumbnailing, cbs, userdata );
>      if( p_dec == NULL )
>      {
>          msg_Err( p_parent, "could not create %s", psz_type );
> @@ -2107,13 +2068,14 @@ static decoder_t *decoder_New( vlc_object_t 
> *p_parent, input_thread_t *p_input,
>   * \param p_es the es descriptor
>   * \return the spawned decoder object
>   */
> -decoder_t *input_DecoderNew( input_thread_t *p_input, vlc_es_id_t *id,
> -                             es_format_t *fmt, vlc_clock_t *p_clock,
> -                             sout_instance_t *p_sout  )
> +decoder_t *input_DecoderNew( vlc_object_t *parent, es_format_t *fmt,
> +                             vlc_clock_t *p_clock, input_resource_t 
> *resource,
> +                             sout_instance_t *p_sout, bool 
> thumbnailing,
> +                             const struct decoder_callbacks *cbs,
> +                             void *cbs_userdata)
>  {
> -    assert(p_input && id);
> -    return decoder_New( VLC_OBJECT(p_input), p_input, id, fmt, p_clock,
> -                        input_priv(p_input)->p_resource, p_sout );
> +    return decoder_New( parent, fmt, p_clock, resource, p_sout, 
> thumbnailing,
> +                        cbs, cbs_userdata );
>  }
>  
>  /**
> @@ -2122,7 +2084,8 @@ decoder_t *input_DecoderNew( input_thread_t 
> *p_input, vlc_es_id_t *id,
>  decoder_t *input_DecoderCreate( vlc_object_t *p_parent, const 
> es_format_t *fmt,
>                                  input_resource_t *p_resource )
>  {
> -    return decoder_New( p_parent, NULL, NULL, fmt, NULL, p_resource, 
> NULL );
> +    return decoder_New( p_parent, fmt, NULL, p_resource, NULL, false, 
> NULL,
> +                        NULL );
>  }
>  
>  
> @@ -2342,8 +2305,9 @@ int input_DecoderSetCcState( decoder_t *p_dec, 
> vlc_fourcc_t codec,
>          es_format_Init( &fmt, SPU_ES, codec );
>          fmt.subs.cc.i_channel = i_channel;
>          fmt.subs.cc.i_reorder_depth = p_owner->cc.desc.i_reorder_depth;
> -        p_cc = input_DecoderNew( p_owner->p_input, p_owner->id, &fmt,
> -                                 p_owner->p_clock, p_owner->p_sout );
> +        p_cc = input_DecoderNew( VLC_OBJECT(p_dec), &fmt, 
> p_owner->p_clock,
> +                                 p_owner->p_resource, p_owner->p_sout, 
> false,
> +                                 NULL, NULL );
>          if( !p_cc )
>          {
>              msg_Err( p_dec, "could not create decoder" );
> diff --git a/src/input/decoder.h b/src/input/decoder.h
> index fbb266e139..3ffb8e8fe3 100644
> --- a/src/input/decoder.h
> +++ b/src/input/decoder.h
> @@ -28,8 +28,32 @@
>  #include <vlc_codec.h>
>  #include <vlc_mouse.h>
>  
> -decoder_t *input_DecoderNew( input_thread_t *, vlc_es_id_t *, 
> es_format_t *,
> -                             vlc_clock_t *, sout_instance_t * ) 
> VLC_USED;
> +struct decoder_callbacks {
> +    /* notifications */
> +    void (*on_vout_added)(decoder_t *decoder, vout_thread_t *vout,
> +                          void *userdata);
> +    void (*on_vout_deleted)(decoder_t *decoder, vout_thread_t *vout,
> +                            void *userdata);
> +    void (*on_thumbnail_ready)(decoder_t *decoder, picture_t *pic,
> +                               void *userdata);
> +
> +    void (*on_new_video_stats)(decoder_t *decoder, unsigned decoded,
> +                               unsigned lost, unsigned displayed,
> +                               void *userdata);
> +    void (*on_new_audio_stats)(decoder_t *decoder, unsigned decoded,
> +                               unsigned lost, unsigned played, void 
> *userdata);
> +
> +    /* requests */
> +    int (*get_attachments)(decoder_t *decoder,
> +                           input_attachment_t ***ppp_attachment,
> +                           void *userdata);
> +};
> +
> +decoder_t *input_DecoderNew( vlc_object_t *parent, es_format_t *, 
> vlc_clock_t *,
> +                             input_resource_t *, sout_instance_t *,
> +                             bool thumbnailing,
> +                             const struct decoder_callbacks *cbs,
> +                             void *userdata ) VLC_USED;
>  
>  /**
>   * This function changes the pause state.
> diff --git a/src/input/es_out.c b/src/input/es_out.c
> index 981160479e..d4d91173b4 100644
> --- a/src/input/es_out.c
> +++ b/src/input/es_out.c
> @@ -259,6 +259,138 @@ static inline int EsOutGetClosedCaptionsChannel( 
> const es_format_t *p_fmt )
>      for( int fetes_i=0; fetes_i<2; fetes_i++ ) \
>          vlc_list_foreach( pos, (!fetes_i ? &p_sys->es : 
> &p_sys->es_slaves), node )
>  
> +static vlc_es_id_t *
> +FindEsIdFromDecoder(es_out_sys_t *p_sys, decoder_t *decoder)
> +{
> +    es_out_id_t *es;
> +    foreach_es_then_es_slaves(es)
> +        if (es->p_dec == decoder)
> +            return &es->id;
> +    return NULL;
> +}
> +
> +static void
> +decoder_on_vout_added(decoder_t *decoder, vout_thread_t *vout, void 
> *userdata)
> +{
> +    es_out_sys_t *priv = userdata;
> +    if (!priv->p_input)
> +        return;
> +
> +    vlc_es_id_t *id = FindEsIdFromDecoder(priv, decoder);
> +    assert(id);
> +
> +    struct vlc_input_event_vout event = {
> +        .action = VLC_INPUT_EVENT_VOUT_ADDED,
> +        .vout = vout,
> +        .id = id,
> +    };
> +
> +    input_SendEventVout(priv->p_input, &event);
> +}
> +
> +static void
> +decoder_on_vout_deleted(decoder_t *decoder, vout_thread_t *vout, void 
> *userdata)
> +{
> +    es_out_sys_t *priv = userdata;
> +    if (!priv->p_input)
> +        return;
> +
> +    vlc_es_id_t *id = FindEsIdFromDecoder(priv, decoder);
> +    assert(id);
> +
> +    struct vlc_input_event_vout event = {
> +        .action = VLC_INPUT_EVENT_VOUT_DELETED,
> +        .vout = vout,
> +        .id = id,
> +    };
> +
> +    input_SendEventVout(priv->p_input, &event);
> +}
> +
> +static void
> +decoder_on_thumbnail_ready(decoder_t *decoder, picture_t *pic, void 
> *userdata)
> +{
> +    es_out_sys_t *priv = userdata;
> +    if (!priv->p_input)
> +        return;
> +
> +    vlc_es_id_t *id = FindEsIdFromDecoder(priv, decoder);
> +    assert(id);
> +
> +    struct vlc_input_event event = {
> +        .type = INPUT_EVENT_THUMBNAIL_READY,
> +        .thumbnail = pic,
> +    };
> +
> +    input_SendEvent(priv->p_input, &event);
> +}
> +
> +static void
> +decoder_on_new_video_stats(decoder_t *decoder, unsigned decoded, 
> unsigned lost,
> +                           unsigned displayed, void *userdata)
> +{
> +    (void) decoder;
> +
> +    es_out_sys_t *priv = userdata;
> +    if (!priv->p_input)
> +        return;
> +
> +    struct input_stats *stats = input_priv(priv->p_input)->stats;
> +    if (!stats)
> +        return;
> +
> +    atomic_fetch_add_explicit(&stats->decoded_video, decoded,
> +                              memory_order_relaxed);
> +    atomic_fetch_add_explicit(&stats->lost_pictures, lost,
> +                              memory_order_relaxed);
> +    atomic_fetch_add_explicit(&stats->displayed_pictures, displayed,
> +                              memory_order_relaxed);
> +}
> +
> +static void
> +decoder_on_new_audio_stats(decoder_t *decoder, unsigned decoded, 
> unsigned lost,
> +                           unsigned played, void *userdata)
> +{
> +    (void) decoder;
> +
> +    es_out_sys_t *priv = userdata;
> +    if (!priv->p_input)
> +        return;
> +
> +    struct input_stats *stats = input_priv(priv->p_input)->stats;
> +    if (!stats)
> +        return;
> +
> +    atomic_fetch_add_explicit(&stats->decoded_audio, decoded,
> +                              memory_order_relaxed);
> +    atomic_fetch_add_explicit(&stats->lost_abuffers, lost,
> +                              memory_order_relaxed);
> +    atomic_fetch_add_explicit(&stats->played_abuffers, played,
> +                              memory_order_relaxed);
> +}
> +
> +static int
> +decoder_get_attachments(decoder_t *decoder,
> +                        input_attachment_t ***ppp_attachment,
> +                        void *userdata)
> +{
> +    (void) decoder;
> +
> +    es_out_sys_t *priv = userdata;
> +    if (!priv->p_input)
> +        return -1;
> +
> +    return input_GetAttachments(priv->p_input, ppp_attachment);
> +}
> +
> +static const struct decoder_callbacks decoder_cbs = {
> +    .on_vout_added = decoder_on_vout_added,
> +    .on_vout_deleted = decoder_on_vout_deleted,
> +    .on_thumbnail_ready = decoder_on_thumbnail_ready,
> +    .on_new_video_stats = decoder_on_new_video_stats,
> +    .on_new_audio_stats = decoder_on_new_audio_stats,
> +    .get_attachments = decoder_get_attachments,
> +};
>  
>  /*****************************************************************************
>   * Es category specific structs
> @@ -640,8 +772,12 @@ static int EsOutSetRecord(  es_out_t *out, bool b_record )
>              if( !p_es->p_dec )
>                  continue;
>  
> -            p_es->p_dec_record = input_DecoderNew( p_input, &p_es->id, 
> &p_es->fmt,
> -                                                   NULL, 
> p_sys->p_sout_record );
> +            p_es->p_dec_record =
> +                input_DecoderNew( VLC_OBJECT(p_input), &p_es->fmt, 
> NULL,
> +                                  input_priv(p_input)->p_resource,
> +                                  p_sys->p_sout_record, false,
> +                                  &decoder_cbs, p_sys );
> +
>              if( p_es->p_dec_record && p_sys->b_buffering )
>                  input_DecoderStartWait( p_es->p_dec_record );
>          }
> @@ -1844,8 +1980,10 @@ static void EsOutCreateDecoder( es_out_t *out, 
> es_out_id_t *p_es )
>      if( !p_es->p_clock )
>          return;
>  
> -    dec = input_DecoderNew( p_input, &p_es->id, &p_es->fmt, 
> p_es->p_clock,
> -                            input_priv(p_input)->p_sout );
> +    input_thread_private_t *priv = input_priv(p_input);
> +    dec = input_DecoderNew( VLC_OBJECT(p_input), &p_es->fmt, 
> p_es->p_clock,
> +                            priv->p_resource, priv->p_sout,
> +                            priv->b_thumbnailing, &decoder_cbs, p_sys 
> );
>      if( dec != NULL )
>      {
>          input_DecoderChangeRate( dec, p_sys->rate );
> @@ -1855,8 +1993,10 @@ static void EsOutCreateDecoder( es_out_t *out, 
> es_out_id_t *p_es )
>  
>          if( !p_es->p_master && p_sys->p_sout_record )
>          {
> -            p_es->p_dec_record = input_DecoderNew( p_input, &p_es->id, 
> &p_es->fmt,
> -                                                   NULL, 
> p_sys->p_sout_record );
> +            p_es->p_dec_record =
> +                input_DecoderNew( VLC_OBJECT(p_input), &p_es->fmt, 
> NULL,
> +                                  priv->p_resource, 
> p_sys->p_sout_record, false,
> +                                  &decoder_cbs, p_sys );
>              if( p_es->p_dec_record && p_sys->b_buffering )
>                  input_DecoderStartWait( p_es->p_dec_record );
>          }
> -- 
> 2.20.1
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list