[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