[vlc-devel] [PATCH 1/5] vout: update the format after filters

Steve Lhomme robux4 at ycbcr.xyz
Tue Oct 20 15:59:27 CEST 2020


HI,

On 2020-10-20 14:32, Romain Vimont wrote:
> The vout is created first, based on the input format. Then filters
> (filter_t) could be added, possibly producing pictures in a different
> format.
> 
>        input ---> filters --->    MISMATCH    [I420] vout
>              I420         RGBA
> 
> To avoid a mismatch between the output of the last filter and the
> expected format of the vout input, a converter was added when necessary
> to compensate:
> 
>        input ---> filters ---> converter ---> [I420] vout
>              I420         RGBA           I420
> 
> But this was often a waste, and it caused problems for opaque formats.
> 
> Instead, request the vout to adapt itself to the actual format produced
> by the last filter. If it can, we can avoid an additional converter.
> 
>        input ---> filters --->    MISMATCH    [I420] vout
>              I420         RGBA
> 
>        input ---> filters ------------------> [RGBA] vout
>              I420         RGBA
> 
> If the vout does not support the new format (or does not accept to
> update its format), a converter is still added as before.
> 
> Co-authored-by: Alexandre Janniaux <ajanni at videolabs.io>
> ---
>   include/vlc_vout_display.h              | 11 +++++
>   modules/hw/mmal/vout.c                  |  2 +-
>   modules/hw/vdpau/display.c              |  2 +-
>   modules/video_output/android/display.c  |  2 +-
>   modules/video_output/caca.c             |  2 +-
>   modules/video_output/caopengllayer.m    |  2 +-
>   modules/video_output/decklink.cpp       |  2 +-
>   modules/video_output/fb.c               |  2 +-
>   modules/video_output/flaschen.c         |  2 +-
>   modules/video_output/ios.m              |  2 +-
>   modules/video_output/kms.c              |  2 +-
>   modules/video_output/kva.c              |  2 +-
>   modules/video_output/macosx.m           |  2 +-
>   modules/video_output/opengl/display.c   |  2 +-
>   modules/video_output/splitter.c         |  2 +-
>   modules/video_output/vdummy.c           |  4 +-
>   modules/video_output/vmem.c             |  2 +-
>   modules/video_output/vulkan/display.c   |  2 +-
>   modules/video_output/wayland/shm.c      |  2 +-
>   modules/video_output/win32/direct3d11.c |  2 +-
>   modules/video_output/win32/direct3d9.c  |  2 +-
>   modules/video_output/win32/glwin32.c    |  2 +-
>   modules/video_output/win32/wingdi.c     |  2 +-
>   modules/video_output/xcb/render.c       |  2 +-
>   modules/video_output/xcb/x11.c          |  2 +-
>   modules/video_output/yuv.c              |  2 +-
>   src/video_output/display.c              | 10 +++++
>   src/video_output/display.h              |  2 +
>   src/video_output/video_output.c         | 57 ++++++++++++++++++++++---
>   29 files changed, 99 insertions(+), 33 deletions(-)
> 
...
> diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
> index 57ee54e6e8..15c1f0e3ee 100644
> --- a/src/video_output/video_output.c
> +++ b/src/video_output/video_output.c
> @@ -950,6 +950,34 @@ typedef struct {
>       config_chain_t *cfg;
>   } vout_filter_t;
>   
> +static int
> +ThreadRequestVoutFormatChange(vout_thread_sys_t *sys, const video_format_t *fmt,
> +                              vlc_video_context *vctx, video_format_t *target)
> +{
> +    vout_display_t *vd = sys->display;
> +
> +    video_format_t vout_fmt;
> +    int ret = video_format_Copy(&vout_fmt, fmt);
> +    if (ret != VLC_SUCCESS)
> +        return ret;
> +
> +    vlc_mutex_lock(&sys->display_lock);
> +    ret = VoutUpdateFormat(vd, &vout_fmt, vctx);
> +    vlc_mutex_unlock(&sys->display_lock);
> +
> +    if (ret != VLC_SUCCESS)
> +    {
> +        video_format_Clean(&vout_fmt);
> +        return ret;
> +    }
> +
> +    /* Move vout_fmt to *target */
> +    video_format_Clean(target);
> +    memcpy(target, &vout_fmt, sizeof(*target));

You should use video_format_Copy()

> +
> +    return ret;
> +}
> +
>   static void ThreadChangeFilters(vout_thread_sys_t *vout)
>   {
>       vout_thread_sys_t *sys = vout;
> @@ -1043,13 +1071,28 @@ static void ThreadChangeFilters(vout_thread_sys_t *vout)
>       }
>   
>       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);
> +        msg_Dbg(&vout->obj, "Changing vout format to %4.4s",
> +                            (const char *) &p_fmt_current->video.i_chroma);
> +
> +        int ret = ThreadRequestVoutFormatChange(vout, &p_fmt_current->video,
> +                                                vctx_current,
> +                                                &fmt_target.video);
> +        if (ret == VLC_SUCCESS)
> +            fmt_target.i_codec = fmt_target.video.i_chroma;

This could be done in ThreadRequestVoutFormatChange()

> +        else
> +            msg_Dbg(&vout->obj, "Changing vout format to %4.4s failed",
> +                                (const char *) &p_fmt_current->video.i_chroma);
> +
> +        if (!es_format_IsSimilar(p_fmt_current, &fmt_target))

This test is probably not needed, you can put the code in the else 
above. If you really want to double check, just add an assert().

> +        {
> +            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);
> +            }
>           }
>       }
>   
> -- 
> 2.28.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