[vlc-devel] [PATCH 5/6] es_out: add a new ES track identifier

Thomas Guillem thomas at gllm.fr
Wed Aug 29 17:55:21 CEST 2018



On Wed, Aug 29, 2018, at 14:24, Thomas Guillem wrote:
> Add the vlc_es_t structure representing an ES track.
> 
> This new struct will be used to fetch tracks information (via vlc_es_GetInfo())
> and to select/unselect/restart tracks.
> 
> Users will receive this new struct from input thread event callbacks. They will
> be able to hold/release it (and fetch tracks informations even after the track
> is terminated by the es_out).
> 
> ES Tracks will still be selectable via their i_id (for TS cases) and legacy
> track selection via "video-es"/"audio-es"/"spu-es" is still functional.
> ---
>  include/vlc_common.h |   1 +
>  include/vlc_es.h     |  75 +++++++++
>  include/vlc_input.h  |  18 ++-
>  src/input/es_out.c   | 353 ++++++++++++++++++++++++++++++-------------
>  src/input/event.c    |  58 +------
>  src/input/event.h    |   7 +-
>  src/input/var.c      |  35 +++--
>  7 files changed, 362 insertions(+), 185 deletions(-)
> 
> diff --git a/include/vlc_common.h b/include/vlc_common.h
> index 3be979dab5..6c32e0f232 100644
> --- a/include/vlc_common.h
> +++ b/include/vlc_common.h
> @@ -372,6 +372,7 @@ typedef struct video_format_t video_format_t;
>  typedef struct subs_format_t subs_format_t;
>  typedef struct es_format_t es_format_t;
>  typedef struct video_palette_t video_palette_t;
> +typedef struct vlc_es_t vlc_es_t;
>  
>  /* Audio */
>  typedef struct audio_output audio_output_t;
> diff --git a/include/vlc_es.h b/include/vlc_es.h
> index 7a14b9271f..187e9f4ec1 100644
> --- a/include/vlc_es.h
> +++ b/include/vlc_es.h
> @@ -680,4 +680,79 @@ static inline void es_format_Change( es_format_t 
> *fmt, int i_cat, vlc_fourcc_t i
>      es_format_Init( fmt, i_cat, i_codec );
>  }
>  
> +/**
> + * Structure filled by vlc_es_GetInfo()
> + *
> + * Clean it with vlc_es_info_Clean()
> + */
> +struct vlc_es_info
> +{
> +    /** Title of the ES track. Updated after a
> +     * vlc_input_event_es::VLC_INPUT_ES_UPDATED event */
> +    char *title;
> +    /** Format of the ES track. Updated after a
> +     * vlc_input_event_es::VLC_INPUT_ES_UPDATED event */
> +    es_format_t fmt;
> +    /** Selected state of the ES track. Updated after
> +     * vlc_input_event_es::VLC_INPUT_ES_SELECTED and
> +     * vlc_input_event_es::VLC_INPUT_ES_UNSELECTED events */
> +    bool selected;
> +    /** Terminated state, the ES track can't be selected if set to true.
> +     * Updated after a vlc_input_event_es::VLC_INPUT_ES_DELETED event. */
> +    bool terminated;
> +};
> +
> +/**
> + * Clean the ES track information filled by vlc_es_GetInfo()
> + *
> + * @param info pointer to the ES track information
> + */
> +static inline void vlc_es_info_Clean(struct vlc_es_info *info)
> +{
> +    free(info->title);
> +    es_format_Clean(&info->fmt);
> +}
> +
> +/**
> + * Increase the ES track reference count.
> + *
> + * Any held ES tracks must be released with vlc_es_Release().
> + *
> + * @param es pointer to the ES track
> + *
> + * @return the same ES pointer, for convenience
> + */
> +VLC_API vlc_es_t *
> +vlc_es_Hold(vlc_es_t *es);
> +
> +/**
> + * Decrease the ES track reference count.
> + *
> + * @param es pointer to the ES track
> + */
> +VLC_API void
> +vlc_es_Release(vlc_es_t *es);
> +
> +/**
> + * Get the ES track information.
> + *
> + * @param es pointer to the ES track
> + * @param info pre-allocated struct filled by this function, invalid in case of
> + * error, clean it with vlc_es_info_Clean() in case of success
> + *
> + * @return VLC_SUCCESS or VLC_ENOMEM in case of allocation error
> + */
> +VLC_API int vlc_es_GetInfo(vlc_es_t *es, struct vlc_es_info *info);
> +
> +/**
> + * Get the ES track id
> + *
> + * The returned id is the same than the vlc_es_info.fmt one returned by
> + * vlc_es_GetInfo()
> + *
> + * @param es pointer to the es track
> + * @return the es track id (always valid)
> + */
> +VLC_API int vlc_es_GetId(vlc_es_t *es);
> +
>  #endif
> diff --git a/include/vlc_input.h b/include/vlc_input.h
> index 890bcc8a6b..b03cb1092f 100644
> --- a/include/vlc_input.h
> +++ b/include/vlc_input.h
> @@ -426,14 +426,18 @@ struct vlc_input_event_program {
>  
>  struct vlc_input_event_es {
>      enum {
> -        VLC_INPUT_ES_ADDED,
> -        VLC_INPUT_ES_DELETED,
> -        VLC_INPUT_ES_UPDATED,
> -        VLC_INPUT_ES_SELECTED,
> -        VLC_INPUT_ES_UNSELECTED,
> +
> +        VLC_INPUT_ES_ADDED,     /**< A new ES was added, get the ES 
> track
> +                                     information with vlc_es_GetInfo() 
> */
> +        VLC_INPUT_ES_DELETED,   /**< vlc_es_info.terminated changed to 
> true */
> +        VLC_INPUT_ES_UPDATED,   /**< vlc_es_info.fmt or 
> vlc_es_info.title changed */
> +        VLC_INPUT_ES_SELECTED,  /**< vlc_es_info.selected changed to 
> true */
> +        VLC_INPUT_ES_UNSELECTED,/**< vlc_es_info.selected changed to 
> false */
>      } action;
> -    const char *title;
> -    const es_format_t *fmt;
> +    /**
> +     * ES track id: only valid from the event callback, unless the id 
> is held
> +     * by the user with vlc_es_Hold(). */
> +    vlc_es_t *id;
>  };
>  
>  struct vlc_input_event_signal {
> diff --git a/src/input/es_out.c b/src/input/es_out.c
> index aab4493976..02069eb57f 100644
> --- a/src/input/es_out.c
> +++ b/src/input/es_out.c
> @@ -76,10 +76,23 @@ typedef struct
>      struct vlc_list node;
>  } es_out_pgrm_t;
>  
> +
> +/**
> + * Opaque structure representing an ES (Elementary Stream) track.
> + *
> + * This structure is propagated via the vlc_input_event_es event
> + */
> +struct vlc_es_t
> +{
> +};
> +
>  struct es_out_id_t
>  {
> +    vlc_es_t id;
> +
>      /* ES ID */
>      int       i_id;
> +    size_t    i_pos; /* position, used to get the title of the track */
>      es_out_pgrm_t *p_pgrm;
>  
>      /* */
> @@ -88,10 +101,22 @@ struct es_out_id_t
>  
>      /* Channel in the track type */
>      int         i_channel;
> +
> +    vlc_atomic_rc_t rc;
> +
> +    /* Lock to protect the following variables. These variables can be read by
> +     * any threads via vlc_es_GetInfo(). */
> +    vlc_mutex_t lock;
>      es_format_t fmt;
>      char        *psz_language;
>      char        *psz_language_code;
>      bool         b_selected;
> +    bool         b_terminated;
> +
> +    /* Codec and original fourcc coming from the demuxer. Used by
> +     * EsOutUpdateInfo() */
> +    vlc_fourcc_t i_input_codec;
> +    vlc_fourcc_t i_input_original_fourcc;
>  
>      decoder_t   *p_dec;
>      decoder_t   *p_dec_record;
> @@ -192,7 +217,7 @@ static void         EsOutDel    ( es_out_t *, 
> es_out_id_t * );
>  
>  static void         EsOutTerminate( es_out_t * );
>  static void         EsOutSelect( es_out_t *, es_out_id_t *es, bool 
> b_force );
> -static void         EsOutUpdateInfo( es_out_t *, es_out_id_t *es, const 
> es_format_t *, const vlc_meta_t * );
> +static void         EsOutUpdateInfo( es_out_t *, es_out_id_t *es, const 
> vlc_meta_t * );
>  static int          EsOutSetRecord(  es_out_t *, bool b_record );
>  
>  static void EsOutSelectEs( es_out_t *out, es_out_id_t *es );
> @@ -205,6 +230,8 @@ static void EsOutProgramsChangeRate( es_out_t 
> *out );
>  static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced );
>  static void EsOutGlobalMeta( es_out_t *p_out, const vlc_meta_t 
> *p_meta );
>  static void EsOutMeta( es_out_t *p_out, const vlc_meta_t *p_meta, const 
> vlc_meta_t *p_progmeta );
> +static int EsOutEsUpdateFmt( es_out_t *out, es_out_id_t *es,
> +                             const es_format_t *fmt, bool 
> from_decoder );
>  
>  static char *LanguageGetName( const char *psz_code );
>  static char *LanguageGetCode( const char *psz_lang );
> @@ -338,7 +365,70 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, 
> int i_rate )
>   
> *****************************************************************************/
>  static void EsMarkSelected(es_out_id_t *es, bool b_selected)
>  {
> +    vlc_mutex_lock(&es->lock);
>      es->b_selected = b_selected;
> +    vlc_mutex_unlock(&es->lock);
> +}
> +
> +static void EsTerminate(es_out_id_t *es)
> +{
> +    vlc_list_remove(&es->node);
> +
> +    vlc_mutex_lock(&es->lock);
> +    es->b_terminated = true;
> +    vlc_mutex_unlock(&es->lock);
> +}
> +
> +static char *EsGetTitle( es_out_id_t *es )
> +{
> +    const es_format_t *fmt = &es->fmt;
> +    char *title;
> +
> +    /* Take care of the ES description */
> +    if( fmt->psz_description && *fmt->psz_description )
> +    {
> +        if( es->psz_language && *es->psz_language )
> +        {
> +            if( asprintf( &title, "%s - [%s]", fmt->psz_description,
> +                          es->psz_language ) == -1 )
> +                title = NULL;
> +        }
> +        else
> +            title = strdup( fmt->psz_description );
> +    }
> +    else
> +    {
> +        if( es->psz_language && *es->psz_language )
> +        {
> +            if( asprintf( &title, "%s %zu - [%s]", _("Track"),
> +                          es->i_pos, es->psz_language ) == -1 )
> +                title = NULL;
> +        }
> +        else
> +        {
> +            if( asprintf( &title, "%s %zu", _("Track"), es->i_pos ) == 
> -1 )
> +                title = NULL;
> +        }
> +    }
> +
> +    return title;
> +}
> +
> +static void EsRelease(es_out_id_t *es)
> +{
> +    if (vlc_atomic_rc_dec(&es->rc))
> +    {
> +        free(es->psz_language);
> +        free(es->psz_language_code);
> +        es_format_Clean(&es->fmt);
> +        vlc_mutex_destroy(&es->lock);
> +        free(es);
> +    }
> +}
> +
> +static void EsHold(es_out_id_t *es)
> +{
> +    vlc_atomic_rc_inc(&es->rc);
>  }
>  
>  static void EsOutDelete( es_out_t *out )
> @@ -370,11 +460,8 @@ static void EsOutTerminate( es_out_t *out )
>          if (es->p_dec != NULL)
>              input_DecoderDelete(es->p_dec);
>  
> -        free(es->psz_language);
> -        free(es->psz_language_code);
> -        es_format_Clean(&es->fmt);
> -        vlc_list_remove(&es->node);
> -        free(es);
> +        EsTerminate(es);
> +        EsRelease(es);
>      }
>  
>      /* FIXME duplicate work EsOutProgramDel (but we cannot use it) add 
> a EsOutProgramClean ? */
> @@ -923,62 +1010,22 @@ static vlc_tick_t EsOutGetBuffering( es_out_t 
> *out )
>      return i_delay;
>  }
>  
> -static void EsOutSendEsEventGeneric( es_out_t *out, int i_id,
> -                                     const es_format_t *fmt, const char 
> *psz_language,
> -                                     bool b_delete )
> +static void EsOutSendEsEvent( es_out_t *out, es_out_id_t *es, int 
> action )
>  {
>      es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
> -    input_thread_t    *p_input = p_sys->p_input;
> -    vlc_value_t       text;
> -    es_out_id_t       *es;
> -    size_t count = 0;
> -
> -    if( b_delete )
> -    {
> -        input_SendEventEsDel( p_input, fmt );
> -        return;
> -    }
> -
> -    /* Get the number of ES already added */
> -    foreach_es_then_es_slaves(es)
> -        if( es->fmt.i_cat == fmt->i_cat )
> -            count++;
> -
> -    /* Take care of the ES description */
> -    if( fmt->psz_description && *fmt->psz_description )
> -    {
> -        if( psz_language && *psz_language )
> -        {
> -            if( asprintf( &text.psz_string, "%s - [%s]", fmt-
> >psz_description,
> -                          psz_language ) == -1 )
> -                text.psz_string = NULL;
> -        }
> -        else text.psz_string = strdup( fmt->psz_description );
> -    }
> -    else
> +    input_thread_t *p_input = p_sys->p_input;
> +    if( action == VLC_INPUT_ES_ADDED )
>      {
> -        if( psz_language && *psz_language )
> -        {
> -            if( asprintf( &text.psz_string, "%s %zu - [%s]", 
> _("Track"), count,
> -                          psz_language ) == -1 )
> -                text.psz_string = NULL;
> -        }
> -        else
> -        {
> -            if( asprintf( &text.psz_string, "%s %zu", _("Track"), 
> count ) == -1 )
> -                text.psz_string = NULL;
> -        }
> +        input_thread_private_t *priv = input_priv(p_input);
> +        /*FIXME: see input_SlaveSourceAdd */
> +        priv->i_last_es_cat = es->fmt.i_cat;
> +        priv->i_last_es_id = es->fmt.i_id;
>      }
>  
> -    input_SendEventEsAdd( p_input, fmt, text.psz_string );
> -
> -    free( text.psz_string );
> -}
> -
> -static void EsOutSendEsEvent( es_out_t *out, es_out_id_t *es,
> -                           bool b_delete )
> -{
> -    EsOutSendEsEventGeneric( out, es->i_id, &es->fmt, es->psz_language, 
> b_delete );
> +    input_SendEventEs(p_input, &(struct vlc_input_event_es) {
> +        .action = action,
> +        .id = &es->id,
> +    });
>  }
>  
>  static bool EsOutIsProgramVisible( es_out_t *out, int i_group )
> @@ -1011,7 +1058,7 @@ static void EsOutProgramSelect( es_out_t *out, 
> es_out_pgrm_t *p_pgrm )
>               && p_sys->i_mode != ES_OUT_MODE_ALL)
>                  EsOutUnselectEs(out, es, true);
>              if (es->p_pgrm == old)
> -                input_SendEventEsDel( p_input, &es->fmt );
> +                EsOutSendEsEvent( out, es, VLC_INPUT_ES_DELETED );
>          }
>  
>          p_sys->audio.p_main_es = NULL;
> @@ -1037,8 +1084,8 @@ static void EsOutProgramSelect( es_out_t *out, 
> es_out_pgrm_t *p_pgrm )
>      {
>          if (es->p_pgrm == p_sys->p_pgrm)
>          {
> -            EsOutSendEsEvent(out, es, false);
> -            EsOutUpdateInfo(out, es, &es->fmt, NULL);
> +            EsOutSendEsEvent(out, es, VLC_INPUT_ES_ADDED);
> +            EsOutUpdateInfo(out, es, NULL);
>          }
>  
>          EsOutSelect(out, es, false);
> @@ -1539,6 +1586,13 @@ static es_out_id_t *EsOutAddSlaveLocked( es_out_t 
> *out, const es_format_t *fmt,
>          return NULL;
>      }
>  
> +    /* Get the number of ES already added in order to get the position 
> of the es */
> +    es->i_pos = 0;
> +    es_out_id_t *it;
> +    foreach_es_then_es_slaves(it)
> +        if( it->fmt.i_cat == fmt->i_cat )
> +            es->i_pos++;
> +
>      /* Increase ref count for program */
>      p_pgrm->i_es++;
>  
> @@ -1550,11 +1604,15 @@ static es_out_id_t 
> *EsOutAddSlaveLocked( es_out_t *out, const es_format_t *fmt,
>      if( !es->fmt.i_original_fourcc )
>          es->fmt.i_original_fourcc = es->fmt.i_codec;
>  
> +    es->i_input_original_fourcc = es->fmt.i_original_fourcc;
> +    es->i_input_codec = es->fmt.i_codec;
> +
>      es->i_id = es->fmt.i_id;
>      es->i_meta_id = p_sys->i_id++; /* always incremented */
>      es->b_scrambled = false;
>      es->b_forced = false;
>      es->b_selected = false;
> +    es->b_terminated = false;
>  
>      switch( es->fmt.i_cat )
>      {
> @@ -1624,10 +1682,13 @@ static es_out_id_t 
> *EsOutAddSlaveLocked( es_out_t *out, const es_format_t *fmt,
>  
>      vlc_list_append(&es->node, es->p_master ? &p_sys->es_slaves : &p_sys->es);
>  
> +    vlc_mutex_init(&es->lock);
> +    vlc_atomic_rc_init(&es->rc);
> +
>      if( es->p_pgrm == p_sys->p_pgrm )
> -        EsOutSendEsEvent( out, es, false );
> +        EsOutSendEsEvent( out, es, VLC_INPUT_ES_ADDED );
>  
> -    EsOutUpdateInfo( out, es, &es->fmt, NULL );
> +    EsOutUpdateInfo( out, es, NULL );
>      EsOutSelect( out, es, false );
>  
>      if( es->b_scrambled )
> @@ -1765,14 +1826,11 @@ static void EsOutSelectEs( es_out_t *out, 
> es_out_id_t *es )
>  
>      /* Mark it as selected */
>      EsMarkSelected(es, true);
> -    input_SendEventEsSelect( p_input, &es->fmt );
> +    EsOutSendEsEvent(out, es, VLC_INPUT_ES_SELECTED);
>  }
>  
>  static void EsDeleteCCChannels( es_out_t *out, es_out_id_t *parent )
>  {
> -    es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
> -    input_thread_t *p_input = p_sys->p_input;
> -
>      if( parent->cc.type == 0 )
>          return;
>  
> @@ -1789,7 +1847,7 @@ static void EsDeleteCCChannels( es_out_t *out, 
> es_out_id_t *parent )
>          {
>              /* Force unselection of the CC */
>              EsMarkSelected(parent->cc.pp_es[i], false);
> -            input_SendEventEsUnselect( p_input, &parent->cc.pp_es[i]-
> >fmt );
> +            EsOutSendEsEvent(out, parent->cc.pp_es[i], 
> VLC_INPUT_ES_UNSELECTED);
>          }
>          EsOutDelLocked( out, parent->cc.pp_es[i] );
>      }
> @@ -1831,7 +1889,7 @@ static void EsOutUnselectEs( es_out_t *out, 
> es_out_id_t *es, bool b_update )
>          return;
>  
>      /* Mark it as unselected */
> -    input_SendEventEsUnselect( p_input, &es->fmt );
> +    EsOutSendEsEvent(out, es, VLC_INPUT_ES_UNSELECTED);
>  }
>  
>  /**
> @@ -2103,7 +2161,11 @@ static int EsOutSend( es_out_t *out, es_out_id_t 
> *es, block_t *p_block )
>      vlc_meta_t  *p_meta_dsc;
>      if( input_DecoderHasFormatChanged( es->p_dec, &fmt_dsc, 
> &p_meta_dsc ) )
>      {
> -        EsOutUpdateInfo( out, es, &fmt_dsc, p_meta_dsc );
> +        fmt_dsc.i_id = es->i_id; /* decoder may overwrite it */
> +        if (EsOutEsUpdateFmt( out, es, &fmt_dsc, true) == VLC_SUCCESS)
> +            EsOutSendEsEvent(out, es, VLC_INPUT_ES_UPDATED);
> +
> +        EsOutUpdateInfo(out, es, p_meta_dsc);
>  
>          es_format_Clean( &fmt_dsc );
>          if( p_meta_dsc )
> @@ -2163,13 +2225,13 @@ static void EsOutDelLocked( es_out_t *out, 
> es_out_id_t *es )
>          EsOutUnselectEs( out, es, es->p_pgrm == p_sys->p_pgrm );
>      }
>  
> +    EsTerminate(es);
> +
>      if( es->p_pgrm == p_sys->p_pgrm )
> -        EsOutSendEsEvent( out, es, true );
> +        EsOutSendEsEvent( out, es, VLC_INPUT_ES_DELETED );
>  
>      EsOutDeleteInfoEs( out, es );
>  
> -    vlc_list_remove(&es->node);
> -
>      /* Update program */
>      es->p_pgrm->i_es--;
>      if( es->p_pgrm->i_es == 0 )
> @@ -2199,7 +2261,7 @@ static void EsOutDelLocked( es_out_t *out, 
> es_out_id_t *es )
>              {
>                  if (other->b_selected)
>                  {
> -                    input_SendEventEsSelect(p_sys->p_input, &es->fmt);
> +                    EsOutSendEsEvent(out, es, VLC_INPUT_ES_SELECTED);
>                      if( p_esprops->p_main_es == NULL )
>                          p_esprops->p_main_es = other;
>                  }
> @@ -2208,12 +2270,7 @@ static void EsOutDelLocked( es_out_t *out, 
> es_out_id_t *es )
>              }
>      }
>  
> -    free( es->psz_language );
> -    free( es->psz_language_code );
> -
> -    es_format_Clean( &es->fmt );
> -
> -    free( es );
> +    EsRelease(es);
>  }
>  
>  static void EsOutDel( es_out_t *out, es_out_id_t *es )
> @@ -2355,7 +2412,11 @@ static int EsOutVaControlLocked( es_out_t *out, 
> int i_query, va_list args )
>          else if( es == es_cat + SPU_ES )
>              i_cat = SPU_ES;
>          else
> +        {
> +            if (es->b_terminated)
> +                return VLC_EGENERIC;
>              i_cat = IGNORE_ES;
> +        }
>  
>          foreach_es_then_es_slaves(other)
>          {
> @@ -2398,6 +2459,8 @@ static int EsOutVaControlLocked( es_out_t *out, 
> int i_query, va_list args )
>      case ES_OUT_UNSET_ES:
>      {
>          es_out_id_t *es = va_arg( args, es_out_id_t * ), *other;
> +        if (es->b_terminated)
> +            return VLC_EGENERIC;
>          foreach_es_then_es_slaves(other)
>          {
>              if (es == other)
> @@ -2609,8 +2672,11 @@ static int EsOutVaControlLocked( es_out_t *out, 
> int i_query, va_list args )
>           || es->fmt.i_id != p_fmt->i_id )
>              return VLC_EGENERIC;
>  
> -        es_format_Clean( &es->fmt );
> -        es_format_Copy( &es->fmt, p_fmt );
> +        int ret = EsOutEsUpdateFmt( out, es, p_fmt, false );
> +        if( ret != VLC_SUCCESS )
> +            return ret;
> +
> +        EsOutSendEsEvent(out, es, VLC_INPUT_ES_UPDATED);
>  
>          if( es->p_dec )
>          {
> @@ -3113,50 +3179,84 @@ static int LanguageArrayIndex( char 
> **ppsz_langs, const char *psz_lang )
>      return -1;
>  }
>  
> -/
> ****************************************************************************
> - * EsOutUpdateInfo:
> - * - add meta info to the playlist item
> - 
> ****************************************************************************/
> -static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const 
> es_format_t *fmt, const vlc_meta_t *p_meta )
> +static int EsOutEsUpdateFmt( es_out_t *out, es_out_id_t *es,
> +                             const es_format_t *fmt, bool 
> from_decoder )
>  {
>      es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
>      input_thread_t *p_input = p_sys->p_input;
> -    const es_format_t *p_fmt_es = &es->fmt;
>  
> -    if( es->fmt.i_cat == fmt->i_cat )
> +    assert( es->fmt.i_cat == fmt->i_cat && es->fmt.i_id == fmt->i_id );
> +
> +    es_format_t update = *fmt;
> +
> +    vlc_mutex_lock( &es->lock );
> +
> +    /* Update infos that could have been lost by the decoder */
> +    if (from_decoder)
>      {
> -        es_format_t update = *fmt;
>          update.i_codec = es->fmt.i_codec;
>          update.i_original_fourcc = es->fmt.i_original_fourcc;
>  
> -        /* Update infos that could have been lost by the decoder (no need to
> -         * dup them since input_item_UpdateTracksInfo() will do it). */
>          if (update.psz_language == NULL)
> +        {
>              update.psz_language = es->fmt.psz_language;
> +            es->fmt.psz_language = NULL;
> +        }
> +        else
> +        {
> +            free( es->psz_language );
> +            free( es->psz_language_code );
> +        }
>          if (update.psz_description == NULL)
> +        {
>              update.psz_description = es->fmt.psz_description;
> +            es->fmt.psz_description = NULL;
> +        }
>          if (update.i_cat == SPU_ES)
>          {
>              if (update.subs.psz_encoding == NULL)
> +            {
>                  update.subs.psz_encoding = es->fmt.subs.psz_encoding;
> +                es->fmt.subs.psz_encoding = NULL;
> +            }
>          }
>          if (update.i_extra_languages == 0)
>          {
>              assert(update.p_extra_languages == NULL);
>              update.i_extra_languages = es->fmt.i_extra_languages;
>              update.p_extra_languages = es->fmt.p_extra_languages;
> +            es->fmt.i_extra_languages = 0;
> +            es->fmt.p_extra_languages = NULL;
>          }
> +    }
>  
> -        /* No need to update codec specific data */
> -        update.i_extra = 0;
> -        update.p_extra = NULL;
> +    es_format_Clean(&es->fmt);
> +    int ret = es_format_Copy(&es->fmt, &update);
> +    if (ret == VLC_SUCCESS)
> +    {
> +        free( es->psz_language );
> +        free( es->psz_language_code );
>  
> -        input_SendEventEsUpdate(p_input, &update);
> +        es->psz_language = LanguageGetName( es->fmt.psz_language );
> +        es->psz_language_code = LanguageGetCode( es->fmt.psz_language );
>  
> -        update.i_id = es->i_meta_id;
> -        input_item_UpdateTracksInfo(input_GetItem(p_input), &update);
> +        input_item_UpdateTracksInfo(input_GetItem(p_input), &es->fmt);
>      }
>  
> +    vlc_mutex_unlock( &es->lock );
> +    return ret;
> +}
> +
> +/
> ****************************************************************************
> + * EsOutUpdateInfo:
> + * - add meta info to the playlist item
> + 
> ****************************************************************************/
> +static void EsOutUpdateInfo( es_out_t *out, es_out_id_t *es, const 
> vlc_meta_t *p_meta )
> +{
> +    es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
> +    input_thread_t *p_input = p_sys->p_input;
> +    const es_format_t *fmt = &es->fmt;
> +
>      /* Create category */
>      char* psz_cat = EsInfoCategoryName( es );
>  
> @@ -3175,10 +3275,9 @@ static void EsOutUpdateInfo( es_out_t *out, 
> es_out_id_t *es, const es_format_t *
>          info_category_AddInfo( p_cat, _("Original ID"),
>                         "%d", es->i_id );
>  
> -    const vlc_fourcc_t i_codec_fourcc = ( p_fmt_es-
> >i_original_fourcc )?
> -                               p_fmt_es->i_original_fourcc : p_fmt_es-
> >i_codec;
> +    const vlc_fourcc_t i_codec_fourcc = es->i_input_original_fourcc;
>      const char *psz_codec_description =
> -        vlc_fourcc_GetDescription( p_fmt_es->i_cat, i_codec_fourcc );
> +        vlc_fourcc_GetDescription( fmt->i_cat, i_codec_fourcc );
>      if( psz_codec_description && *psz_codec_description )
>          info_category_AddInfo( p_cat, _("Codec"), "%s (%.4s)",
>                                 psz_codec_description, 
> (char*)&i_codec_fourcc );
> @@ -3212,7 +3311,7 @@ static void EsOutUpdateInfo( es_out_t *out, 
> es_out_id_t *es, const es_format_t *
>  
>          unsigned int i_bitspersample = fmt->audio.i_bitspersample;
>          if( i_bitspersample == 0 )
> -            i_bitspersample = aout_BitsPerSample( p_fmt_es->i_codec );
> +            i_bitspersample = aout_BitsPerSample( fmt->i_codec );
>          if( i_bitspersample != 0 )
>              info_category_AddInfo( p_cat, _("Bits per sample"), "%u",
>                                     i_bitspersample );
> @@ -3263,7 +3362,7 @@ static void EsOutUpdateInfo( es_out_t *out, 
> es_out_id_t *es, const es_format_t *
>                                        (double)fmt->video.i_frame_rate
>                                        / (double)fmt-
> >video.i_frame_rate_base );
>         }
> -       if( fmt->i_codec != p_fmt_es->i_codec )
> +       if( fmt->i_codec != es->i_input_codec )
>         {
>             const char *psz_chroma_description =
>                  vlc_fourcc_GetDescription( VIDEO_ES, fmt->i_codec );
> @@ -3489,3 +3588,53 @@ static void EsOutDeleteInfoEs( es_out_t *out, 
> es_out_id_t *es )
>          free( psz_info_category );
>      }
>  }
> +
> +static inline es_out_id_t *vlc_es_get_id( vlc_es_t *es )
> +{
> +    return container_of( es, es_out_id_t, id );
> +}
> +
> +vlc_es_t *
> +vlc_es_Hold(vlc_es_t *es)
> +{
> +    EsHold(vlc_es_get_id(es));
> +    return es;
> +}
> +
> +void
> +vlc_es_Release(vlc_es_t *es)
> +{
> +    EsRelease(vlc_es_get_id(es));
> +}
> +
> +int
> +vlc_es_GetInfo(vlc_es_t *es, struct vlc_es_info *info)
> +{
> +    es_out_id_t *esid = vlc_es_get_id(es);
> +
> +    vlc_mutex_lock(&esid->lock);
> +
> +    info->title = EsGetTitle(esid);
> +    int ret = es_format_Copy(&info->fmt, &esid->fmt);
> +    if (!info->title || ret != VLC_SUCCESS)
> +    {
> +        free(info->title);
> +        vlc_mutex_unlock(&esid->lock);
> +        return VLC_ENOMEM;
> +    }

I may remove this part, and all the new es->lock part. It'll depend of my new vlc_player_t implementation.
Indeed, I can just put the updated es_info in input events that will then be accessed when the es_out lock is held.

> +
> +    info->fmt.i_original_fourcc = esid->i_input_original_fourcc;
> +    info->selected = esid->b_selected;
> +    info->terminated = esid->b_terminated;
> +
> +    vlc_mutex_unlock(&esid->lock);
> +
> +    return VLC_SUCCESS;
> +}
> +
> +int
> +vlc_es_GetId(vlc_es_t *es)
> +{
> +    /* This variable is const, no lock required */
> +    return vlc_es_get_id(es)->i_id;
> +}
> diff --git a/src/input/event.c b/src/input/event.c
> index ba9f39b629..e15a0d9e76 100644
> --- a/src/input/event.c
> +++ b/src/input/event.c
> @@ -218,64 +218,12 @@ void 
> input_SendEventProgramScrambled( input_thread_t *p_input, int i_group, 
> bool
>      });
>  }
>  
> -void input_SendEventEsAdd( input_thread_t *p_input, const es_format_t 
> *p_fmt,
> -                           const char *psz_title)
> -{
> -    input_thread_private_t *priv = input_priv(p_input);
> -    priv->i_last_es_cat = p_fmt->i_cat;
> -    priv->i_last_es_id = p_fmt->i_id;
> -
> -    input_SendEvent( p_input, &(struct vlc_input_event) {
> -        .type = INPUT_EVENT_ES,
> -        .es = {
> -            .action = VLC_INPUT_ES_ADDED,
> -            .title = psz_title,
> -            .fmt = p_fmt,
> -        }
> -    });
> -}
> -void input_SendEventEsUpdate( input_thread_t *p_input, const 
> es_format_t *p_fmt )
> -{
> -    input_SendEvent( p_input, &(struct vlc_input_event) {
> -        .type = INPUT_EVENT_ES,
> -        .es = {
> -            .action = VLC_INPUT_ES_UPDATED,
> -            .fmt = p_fmt,
> -        }
> -    });
> -}
> -void input_SendEventEsDel( input_thread_t *p_input,
> -                           const es_format_t *p_fmt )
> +void input_SendEventEs( input_thread_t *p_input,
> +                        const struct vlc_input_event_es *es_event )
>  {
>      input_SendEvent( p_input, &(struct vlc_input_event) {
>          .type = INPUT_EVENT_ES,
> -        .es = {
> -            .action = VLC_INPUT_ES_DELETED,
> -            .fmt = p_fmt,
> -        }
> -    });
> -}
> -void input_SendEventEsSelect( input_thread_t *p_input,
> -                              const es_format_t *p_fmt )
> -{
> -    input_SendEvent( p_input, &(struct vlc_input_event) {
> -        .type = INPUT_EVENT_ES,
> -        .es = {
> -            .action = VLC_INPUT_ES_SELECTED,
> -            .fmt = p_fmt,
> -        }
> -    });
> -}
> -
> -void input_SendEventEsUnselect( input_thread_t *p_input,
> -                                const es_format_t *p_fmt )
> -{
> -    input_SendEvent( p_input, &(struct vlc_input_event) {
> -        .type = INPUT_EVENT_ES,
> -        .es = {
> -            .action = VLC_INPUT_ES_UNSELECTED,
> -            .fmt = p_fmt,
> -        }
> +        .es = *es_event,
>      });
>  }
>  
> diff --git a/src/input/event.h b/src/input/event.h
> index 5057458565..a2fcfe5541 100644
> --- a/src/input/event.h
> +++ b/src/input/event.h
> @@ -60,12 +60,7 @@ void input_SendEventProgramDel( input_thread_t 
> *p_input, int i_program );
>  void input_SendEventProgramSelect( input_thread_t *p_input, int 
> i_program );
>  void input_SendEventProgramScrambled( input_thread_t *p_input, int 
> i_group, bool b_scrambled );
>  
> -void input_SendEventEsDel( input_thread_t *p_input, const es_format_t 
> *fmt );
> -void input_SendEventEsAdd( input_thread_t *p_input,
> -                           const es_format_t *fmt, const char 
> *psz_title );
> -void input_SendEventEsUpdate( input_thread_t *p_input, const 
> es_format_t *fmt );
> -void input_SendEventEsSelect( input_thread_t *p_input, const 
> es_format_t *fmt );
> -void input_SendEventEsUnselect( input_thread_t *p_input, const 
> es_format_t *fmt );
> +void input_SendEventEs( input_thread_t *p_input, const struct 
> vlc_input_event_es *es_event );
>  
>  /
> *****************************************************************************
>   * Event for decoder.c
> diff --git a/src/input/var.c b/src/input/var.c
> index 9795785ef9..d2b401de15 100644
> --- a/src/input/var.c
> +++ b/src/input/var.c
> @@ -325,11 +325,15 @@ void input_LegacyEvents( input_thread_t *p_input, 
> void *user_data,
>              }
>              break;
>          case INPUT_EVENT_ES:
> +        {
> +            struct vlc_es_info info;
> +            if (vlc_es_GetInfo(event->es.id, &info) != VLC_SUCCESS)
> +                break;
>              switch (event->es.action)
>              {
>                  case VLC_INPUT_ES_ADDED:
>                  {
> -                    const char *varname = GetEsVarName( event->es.fmt-
> >i_cat );
> +                    const char *varname = 
> GetEsVarName( info.fmt.i_cat );
>                      if( varname )
>                      {
>                          size_t count;
> @@ -339,47 +343,48 @@ void input_LegacyEvents( input_thread_t *p_input, 
> void *user_data,
>                              /* First one, we need to add the "Disable" 
> choice */
>                              VarListAdd( p_input, varname, -1, 
> _("Disable") );
>                          }
> -                        VarListAdd( p_input, varname, event->es.fmt-
> >i_id,
> -                                    event->es.title );
> +                        VarListAdd( p_input, varname, info.fmt.i_id, 
> info.title );
>                      }
>  
> -                    if( EsFmtIsTeletext( event->es.fmt ) )
> +                    if( EsFmtIsTeletext( &info.fmt ) )
>                      {
>                          char psz_page[3+1];
>                          snprintf( psz_page, sizeof(psz_page), "%d
> %2.2x",
> -                                  event->es.fmt-
> >subs.teletext.i_magazine,
> -                                  event->es.fmt-
> >subs.teletext.i_page );
> -                        VarListAdd( p_input, "teletext-es", event-
> >es.fmt->i_id,
> -                                    event->es.fmt-
> >subs.teletext.i_magazine >= 0 ? psz_page : "" );
> +                                  info.fmt.subs.teletext.i_magazine,
> +                                  info.fmt.subs.teletext.i_page );
> +                        VarListAdd( p_input, "teletext-es", 
> info.fmt.i_id,
> +                                    info.fmt.subs.teletext.i_magazine 
> >= 0 ? psz_page : "" );
>                      }
>                      break;
>                  }
>                  case VLC_INPUT_ES_DELETED:
>                  {
> -                    const char *varname = GetEsVarName( event->es.fmt-
> >i_cat );
> +                    const char *varname = 
> GetEsVarName( info.fmt.i_cat );
>                      if( varname )
> -                        VarListDel( p_input, varname, event->es.fmt-
> >i_id );
> +                        VarListDel( p_input, varname, info.fmt.i_id );
>  
> -                    if( EsFmtIsTeletext( event->es.fmt ) )
> -                        VarListDel( p_input, "teletext-es", event-
> >es.fmt->i_id );
> +                    if( EsFmtIsTeletext( &info.fmt ) )
> +                        VarListDel( p_input, "teletext-es", 
> info.fmt.i_id );
>                      break;
>                  }
>                  case VLC_INPUT_ES_SELECTED:
>                  case VLC_INPUT_ES_UNSELECTED:
>                  {
>                      int i_id = event->es.action == 
> VLC_INPUT_ES_SELECTED
> -                             ? event->es.fmt->i_id : -1;
> -                    const char *varname = GetEsVarName( event->es.fmt-
> >i_cat );
> +                             ? info.fmt.i_id : -1;
> +                    const char *varname = 
> GetEsVarName( info.fmt.i_cat );
>                      if( varname )
>                          VarListSelect( p_input, varname, i_id );
> -                    if( EsFmtIsTeletext( event->es.fmt ) )
> +                    if( EsFmtIsTeletext( &info.fmt ) )
>                          VarListSelect( p_input, "teletext-es", i_id );
>                      break;
>                  }
>                  case VLC_INPUT_ES_UPDATED:
>                      break;
>              }
> +            vlc_es_info_Clean(&info);
>              break;
> +        }
>          case INPUT_EVENT_RECORD:
>              val.b_bool = event->record;
>              var_Change( p_input, "record", VLC_VAR_SETVALUE, val );
> -- 
> 2.18.0
> 
> _______________________________________________
> 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