[vlc-devel] [PATCH 17/17] video_output: restart display after filter change

Thomas Guillem thomas at gllm.fr
Fri Nov 20 21:12:57 CET 2020


Your commit log say that it is restarted when the filter format change.

Looking at the diff, the display is actually restarted before displaying the picture that need a format change, am I right?

On Fri, Nov 20, 2020, at 15:45, Steve Lhomme wrote:
> This is done in the vout thread loop, immediately after the filter output
> change is detected, before processing pictures coming out of the filters. The
> filters are untouched (not flushed).
> 
> The new display module is created with the format coming out of the last
> filter.
> ---
>  src/video_output/video_output.c | 106 ++++++++++++++++++++++++++++----
>  1 file changed, 93 insertions(+), 13 deletions(-)
> 
> diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
> index 563a7b18122..d83c859adfb 100644
> --- a/src/video_output/video_output.c
> +++ b/src/video_output/video_output.c
> @@ -163,6 +163,7 @@ typedef struct vout_thread_sys_t
>      vout_display_cfg_t display_cfg;
>      vout_display_t *display;
>      vlc_mutex_t     display_lock;
> +    bool            display_restart; // only accessed in vout thread
>  
>      /* Video filter2 chain */
>      struct {
> @@ -942,9 +943,13 @@ typedef struct {
>      config_chain_t *cfg;
>  } vout_filter_t;
>  
> -static void ThreadChangeFilters(vout_thread_sys_t *vout)
> +static bool ThreadChangeFilters(vout_thread_sys_t *vout)
>  {
>      vout_thread_sys_t *sys = vout;
> +
> +    es_format_t prev_es_fmt;
> +    es_format_Copy(&prev_es_fmt, 
> filter_chain_GetFmtOut(sys->filter.chain_interactive));
> +
>      ThreadFilterFlush(vout, true);
>      ThreadDelAllFilterCallbacks(vout);
>  
> @@ -1034,20 +1039,20 @@ static void ThreadChangeFilters(vout_thread_sys_t *vout)
>          vlc_array_clear(array);
>      }
>  
> -    if (!es_format_IsSimilar(p_fmt_current, &fmt_target)) {
> -        msg_Dbg(&vout->obj, "Adding a filter to compensate for format 
> changes");
> -        if (filter_chain_AppendConverter(sys->filter.chain_interactive,
> -                                         &fmt_target) != 0) {
> -            msg_Err(&vout->obj, "Failed to compensate for the format 
> changes, removing all filters");
> -            ThreadDelAllFilterCallbacks(vout);
> -            filter_chain_Reset(sys->filter.chain_static,      
> &fmt_target, vctx_target, &fmt_target);
> -            filter_chain_Reset(sys->filter.chain_interactive, 
> &fmt_target, vctx_target, &fmt_target);
> -        }
> +    sys->filter.changed = false;
> +
> +    if (!es_format_IsSimilar(p_fmt_current, &prev_es_fmt)) {
> +        // we need a new display+converter
> +        msg_Dbg(&vout->obj, "filter output  format change detected");
> +        es_format_Clean(&fmt_target);
> +        es_format_Clean(&prev_es_fmt);
> +        return true;
>      }
>  
>      es_format_Clean(&fmt_target);
> +    es_format_Clean(&prev_es_fmt);
>  
> -    sys->filter.changed = false;
> +    return false;
>  }
>  
>  
> @@ -1068,7 +1073,12 @@ static bool 
> ThreadDisplayPrerenderNext(vout_thread_sys_t *vout, bool reuse_decod
>              sys->private.interlacing.has_deint != 
> sys->filter.new_interlaced)
>          {
>              sys->private.interlacing.has_deint = 
> sys->filter.new_interlaced;
> -            ThreadChangeFilters(vout);
> +            if (ThreadChangeFilters(vout))
> +            {
> +                // we can't use the display, trigger a restart
> +                sys->display_restart = true;
> +                break;
> +            }
>          }
>  
>          picture_t *decoded;
> @@ -1139,7 +1149,7 @@ static bool 
> ThreadDisplayPrerenderNext(vout_thread_sys_t *vout, bool reuse_decod
>  
>  
>          if (sys->filter.changed)
> -            continue; // filter+display update needed, we keep 
> displayed.decoded
> +            break; // filter+display update needed, we keep 
> displayed.decoded
>  
>          picture_Hold(sys->displayed.decoded);
>          picture = filter_chain_VideoFilter(sys->filter.chain_static, 
> sys->displayed.decoded);
> @@ -1535,6 +1545,8 @@ static int ThreadDisplayPicture(vout_thread_sys_t 
> *vout, vlc_tick_t *deadline)
>                          if (likely(pic_system_pts != INT64_MAX))
>                              pic_render_deadline = pic_system_pts - 
> render_delay;
>                      }
> +                    else if (sys->display_restart)
> +                        return VLC_SUCCESS; // restart the display 
> immediately
>                  }
>  
>                  if (date_refresh == VLC_TICK_INVALID || 
> pic_render_deadline < date_refresh)
> @@ -1885,6 +1897,8 @@ error:
>      return VLC_EGENERIC;
>  }
>  
> +static void ThreadDisplayRestartDisplay(vout_thread_sys_t *);
> +
>  /*****************************************************************************
>   * Thread: video output thread
>   *****************************************************************************
> @@ -1899,10 +1913,14 @@ static void *Thread(void *object)
>  
>      vlc_tick_t deadline = VLC_TICK_INVALID;
>      bool wait = false;
> +    sys->display_restart = false;
>  
>      for (;;) {
>          vout_control_cmd_t cmd;
>  
> +        if (sys->display_restart)
> +            ThreadDisplayRestartDisplay(vout);
> +
>          if (wait)
>          {
>              const vlc_tick_t max_deadline = vlc_tick_now() + 
> VLC_TICK_FROM_MS(100);
> @@ -2276,6 +2294,68 @@ static void vout_InitSource(vout_thread_sys_t 
> *vout)
>      }
>  }
>  
> +static void ThreadDisplayRestartDisplay(vout_thread_sys_t *vout)
> +{
> +    vout_thread_sys_t *sys = vout;
> +
> +    vlc_mutex_lock(&sys->window_lock);
> +
> +    vout_display_cfg_t dcfg = sys->display_cfg;
> +    int x = 0, y = 0, w = 0, h = 0;
> +    vlc_rational_t dar = (vlc_rational_t) { sys->source.dar.num, 
> sys->source.dar.den };
> +    vlc_rational_t crop = {0};
> +    switch (sys->source.crop.mode) {
> +        case VOUT_CROP_NONE:
> +            break;
> +        case VOUT_CROP_RATIO:
> +            crop = (vlc_rational_t) { sys->source.crop.ratio.num,
> +                                      sys->source.crop.ratio.den };
> +            break;
> +        case VOUT_CROP_WINDOW:
> +            x = sys->source.crop.window.x;
> +            y = sys->source.crop.window.y;
> +            w = sys->source.crop.window.width;
> +            h = sys->source.crop.window.height;
> +            break;
> +        case VOUT_CROP_BORDER:
> +            x = sys->source.crop.border.left;
> +            y = sys->source.crop.border.top;
> +            w = -(int)sys->source.crop.border.right;
> +            h = -(int)sys->source.crop.border.bottom;
> +            break;
> +    }
> +
> +    vlc_mutex_lock(&sys->filter.lock);
> +
> +    const es_format_t *filter_out = 
> filter_chain_GetFmtOut(sys->filter.chain_interactive);
> +    vlc_video_context *vctx_out = 
> filter_chain_GetVideoCtxOut(sys->filter.chain_interactive);
> +
> +#ifndef NDEBUG
> +    if (vctx_out)
> +    {
> +        // make sure the decoder device we receive matches the one we 
> have cached
> +        vlc_decoder_device *dec_device = 
> vlc_video_context_HoldDevice(vctx_out);
> +        assert(dec_device && dec_device == sys->dec_device);
> +        vlc_decoder_device_Release(dec_device);
> +    }
> +#endif
> +
> +    vlc_mutex_unlock(&sys->window_lock);
> +
> +    if (likely(sys->display != NULL))
> +        vout_ReleaseDisplayAlone(sys);
> +
> +    vout_StartDisplayAloneLocked(vout, &filter_out->video, vctx_out, 
> &dcfg,
> +                                 &dar, &crop, x, y, h, w);
> +
> +    sys->displayed.current  = NULL;
> +    sys->displayed.date     = VLC_TICK_INVALID;
> +
> +    vlc_mutex_unlock(&sys->filter.lock);
> +
> +    sys->display_restart = false;
> +}
> +
>  int vout_Request(const vout_configuration_t *cfg, vlc_video_context 
> *vctx, input_thread_t *input)
>  {
>      vout_thread_sys_t *vout = VOUT_THREAD_TO_SYS(cfg->vout);
> -- 
> 2.26.2
> 
> _______________________________________________
> 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