[vlc-devel] [PATCH 1/5] vout: update the format after filters
Alexandre Janniaux
ajanni at videolabs.io
Tue Oct 20 14:36:08 CEST 2020
Hi,
Note that this is somehow a replacement for the reset_pictures()
control, able to receive video context too.
Regards,
--
Alexandre Janniaux
Videolabs
On Tue, Oct 20, 2020 at 02:32:42PM +0200, 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/include/vlc_vout_display.h b/include/vlc_vout_display.h
> index df9e81eb6d..3b7b504d0b 100644
> --- a/include/vlc_vout_display.h
> +++ b/include/vlc_vout_display.h
> @@ -320,6 +320,17 @@ struct vlc_display_operations
> * \param vp viewpoint to use on the next render
> */
> int (*set_viewpoint)(vout_display_t *, const vlc_viewpoint_t *vp);
> +
> + /**
> + * Notifies a change in the input format.
> + *
> + * \param fmt the requested input format, could be modified by the display
> + * module to report the actual format
> + * \param ctx the video context
> + * \return VLC_SUCCESS on success, another value on error
> + */
> + int (*update_format)(vout_display_t *, video_format_t *fmt,
> + vlc_video_context *ctx);
> };
>
> struct vout_display_t {
> diff --git a/modules/hw/mmal/vout.c b/modules/hw/mmal/vout.c
> index 93dadd4ded..efba230ca6 100644
> --- a/modules/hw/mmal/vout.c
> +++ b/modules/hw/mmal/vout.c
> @@ -1094,7 +1094,7 @@ static int find_display_num(const char * name)
> }
>
> static const struct vlc_display_operations ops = {
> - CloseMmalVout, vd_prepare, vd_display, vd_control, vd_reset_pictures, NULL,
> + CloseMmalVout, vd_prepare, vd_display, vd_control, vd_reset_pictures, NULL, NULL,
> };
>
> static int OpenMmalVout(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/hw/vdpau/display.c b/modules/hw/vdpau/display.c
> index 70eaa4b8db..e548cf90a0 100644
> --- a/modules/hw/vdpau/display.c
> +++ b/modules/hw/vdpau/display.c
> @@ -286,7 +286,7 @@ static int Control(vout_display_t *vd, int query)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Queue, Wait, Control, ResetPictures, NULL,
> + Close, Queue, Wait, Control, ResetPictures, NULL, NULL,
> };
>
> static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/android/display.c b/modules/video_output/android/display.c
> index 10ac60bb0a..1f542aa6f9 100644
> --- a/modules/video_output/android/display.c
> +++ b/modules/video_output/android/display.c
> @@ -477,7 +477,7 @@ static void SetRGBMask(video_format_t *p_fmt)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, NULL,
> + Close, Prepare, Display, Control, NULL, NULL, NULL,
> };
>
> static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/caca.c b/modules/video_output/caca.c
> index d4a66c5e37..d01c259e41 100644
> --- a/modules/video_output/caca.c
> +++ b/modules/video_output/caca.c
> @@ -371,7 +371,7 @@ static void Close(vout_display_t *vd)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, PictureDisplay, Control, NULL, NULL,
> + Close, Prepare, PictureDisplay, Control, NULL, NULL, NULL,
> };
>
> /**
> diff --git a/modules/video_output/caopengllayer.m b/modules/video_output/caopengllayer.m
> index 587817d153..551def799a 100644
> --- a/modules/video_output/caopengllayer.m
> +++ b/modules/video_output/caopengllayer.m
> @@ -119,7 +119,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *vp)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint,
> + Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint, NULL,
> };
>
> /*****************************************************************************
> diff --git a/modules/video_output/decklink.cpp b/modules/video_output/decklink.cpp
> index 4f25dc6d01..d44709ace4 100644
> --- a/modules/video_output/decklink.cpp
> +++ b/modules/video_output/decklink.cpp
> @@ -769,7 +769,7 @@ static int ControlVideo(vout_display_t *vd, int query)
> }
>
> static const struct vlc_display_operations ops = {
> - CloseVideo, PrepareVideo, NULL, ControlVideo, NULL, NULL,
> + CloseVideo, PrepareVideo, NULL, ControlVideo, NULL, NULL, NULL,
> };
>
> static int OpenVideo(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/fb.c b/modules/video_output/fb.c
> index 4ea44c154c..c92b9ccd09 100644
> --- a/modules/video_output/fb.c
> +++ b/modules/video_output/fb.c
> @@ -162,7 +162,7 @@ static void ClearScreen(vout_display_sys_t *sys)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, NULL, Display, Control, NULL, NULL,
> + Close, NULL, Display, Control, NULL, NULL, NULL,
> };
>
> /**
> diff --git a/modules/video_output/flaschen.c b/modules/video_output/flaschen.c
> index ec515c9b8b..46bab8fa17 100644
> --- a/modules/video_output/flaschen.c
> +++ b/modules/video_output/flaschen.c
> @@ -82,7 +82,7 @@ static void Display(vout_display_t *, picture_t *);
> static int Control(vout_display_t *, int);
>
> static const struct vlc_display_operations ops = {
> - Close, NULL, Display, Control, NULL, NULL,
> + Close, NULL, Display, Control, NULL, NULL, NULL,
> };
>
> /*****************************************************************************
> diff --git a/modules/video_output/ios.m b/modules/video_output/ios.m
> index 07c8355d45..682d0800c8 100644
> --- a/modules/video_output/ios.m
> +++ b/modules/video_output/ios.m
> @@ -152,7 +152,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *vp)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint,
> + Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint, NULL,
> };
>
> static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/kms.c b/modules/video_output/kms.c
> index 9965f3a8ef..ec7b1c32ef 100644
> --- a/modules/video_output/kms.c
> +++ b/modules/video_output/kms.c
> @@ -663,7 +663,7 @@ static void Close(vout_display_t *vd)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, NULL,
> + Close, Prepare, Display, Control, NULL, NULL, NULL,
> };
>
> /**
> diff --git a/modules/video_output/kva.c b/modules/video_output/kva.c
> index badef7a452..edb79bd4eb 100644
> --- a/modules/video_output/kva.c
> +++ b/modules/video_output/kva.c
> @@ -156,7 +156,7 @@ static void Prepare(vout_display_t *vd, picture_t *pic, subpicture_t *subpic, vl
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, NULL,
> + Close, Prepare, Display, Control, NULL, NULL, NULL,
> };
>
> static void PMThread( void *arg )
> diff --git a/modules/video_output/macosx.m b/modules/video_output/macosx.m
> index 9ce48deaaf..6f32009b3f 100644
> --- a/modules/video_output/macosx.m
> +++ b/modules/video_output/macosx.m
> @@ -138,7 +138,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *vp)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint,
> + Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint, NULL,
> };
>
> static int Open (vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/opengl/display.c b/modules/video_output/opengl/display.c
> index b4d79cf0ca..82e0dc5156 100644
> --- a/modules/video_output/opengl/display.c
> +++ b/modules/video_output/opengl/display.c
> @@ -94,7 +94,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *vp)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint,
> + Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint, NULL,
> };
>
> /**
> diff --git a/modules/video_output/splitter.c b/modules/video_output/splitter.c
> index 6ca82e34c1..8bffeb3591 100644
> --- a/modules/video_output/splitter.c
> +++ b/modules/video_output/splitter.c
> @@ -220,7 +220,7 @@ static vout_window_t *video_splitter_CreateWindow(vlc_object_t *obj,
> }
>
> static const struct vlc_display_operations ops = {
> - vlc_vidsplit_Close, vlc_vidsplit_Prepare, vlc_vidsplit_Display, vlc_vidsplit_Control, NULL, NULL,
> + vlc_vidsplit_Close, vlc_vidsplit_Prepare, vlc_vidsplit_Display, vlc_vidsplit_Control, NULL, NULL, NULL,
> };
>
> static int vlc_vidsplit_Open(vout_display_t *vd,
> diff --git a/modules/video_output/vdummy.c b/modules/video_output/vdummy.c
> index 91309cca24..90d984be2c 100644
> --- a/modules/video_output/vdummy.c
> +++ b/modules/video_output/vdummy.c
> @@ -85,7 +85,7 @@ static void Open(vout_display_t *vd, video_format_t *fmt)
> }
>
> static const struct vlc_display_operations ops_dummy = {
> - NULL, NULL, NULL, Control, NULL, NULL,
> + NULL, NULL, NULL, Control, NULL, NULL, NULL,
> };
>
> static int OpenDummy(vout_display_t *vd, const vout_display_cfg_t *cfg,
> @@ -98,7 +98,7 @@ static int OpenDummy(vout_display_t *vd, const vout_display_cfg_t *cfg,
> }
>
> static const struct vlc_display_operations ops_stats = {
> - NULL, NULL, DisplayStat, Control, NULL, NULL,
> + NULL, NULL, DisplayStat, Control, NULL, NULL, NULL,
> };
>
> static int OpenStats(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/vmem.c b/modules/video_output/vmem.c
> index ce077db7a3..559ec1ebdd 100644
> --- a/modules/video_output/vmem.c
> +++ b/modules/video_output/vmem.c
> @@ -106,7 +106,7 @@ static void Display(vout_display_t *, picture_t *);
> static int Control(vout_display_t *, int);
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, NULL,
> + Close, Prepare, Display, Control, NULL, NULL, NULL,
> };
>
> /*****************************************************************************
> diff --git a/modules/video_output/vulkan/display.c b/modules/video_output/vulkan/display.c
> index cba7ca8903..b57591eb0c 100644
> --- a/modules/video_output/vulkan/display.c
> +++ b/modules/video_output/vulkan/display.c
> @@ -78,7 +78,7 @@ static void Close(vout_display_t *);
> static void UpdateParams(vout_display_t *);
>
> static const struct vlc_display_operations ops = {
> - Close, PictureRender, PictureDisplay, Control, NULL, NULL,
> + Close, PictureRender, PictureDisplay, Control, NULL, NULL, NULL,
> };
>
> // Allocates a Vulkan surface and instance for video output.
> diff --git a/modules/video_output/wayland/shm.c b/modules/video_output/wayland/shm.c
> index 4480fa6d3a..a336658d8d 100644
> --- a/modules/video_output/wayland/shm.c
> +++ b/modules/video_output/wayland/shm.c
> @@ -263,7 +263,7 @@ static void Close(vout_display_t *vd)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, ResetPictures, NULL,
> + Close, Prepare, Display, Control, ResetPictures, NULL, NULL,
> };
>
> static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
> index c4a020fb06..95551f43ea 100644
> --- a/modules/video_output/win32/direct3d11.c
> +++ b/modules/video_output/win32/direct3d11.c
> @@ -305,7 +305,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *viewpoint)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, SetViewpoint,
> + Close, Prepare, Display, Control, NULL, SetViewpoint, NULL,
> };
>
> static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
> diff --git a/modules/video_output/win32/direct3d9.c b/modules/video_output/win32/direct3d9.c
> index 55235f63d6..b1a3bdc8e9 100644
> --- a/modules/video_output/win32/direct3d9.c
> +++ b/modules/video_output/win32/direct3d9.c
> @@ -1761,7 +1761,7 @@ static void LocalSwapchainSwap( void *opaque )
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, NULL,
> + Close, Prepare, Display, Control, NULL, NULL, NULL,
> };
>
> /**
> diff --git a/modules/video_output/win32/glwin32.c b/modules/video_output/win32/glwin32.c
> index 627a33ccc4..07df857732 100644
> --- a/modules/video_output/win32/glwin32.c
> +++ b/modules/video_output/win32/glwin32.c
> @@ -109,7 +109,7 @@ static vout_window_t *EmbedVideoWindow_Create(vout_display_t *vd)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, SetViewpoint,
> + Close, Prepare, Display, Control, NULL, SetViewpoint, NULL,
> };
>
> /**
> diff --git a/modules/video_output/win32/wingdi.c b/modules/video_output/win32/wingdi.c
> index e25eed09e3..56a9f68aff 100644
> --- a/modules/video_output/win32/wingdi.c
> +++ b/modules/video_output/win32/wingdi.c
> @@ -104,7 +104,7 @@ static int Control(vout_display_t *vd, int query)
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, NULL,
> + Close, Prepare, Display, Control, NULL, NULL, NULL,
> };
>
> /* */
> diff --git a/modules/video_output/xcb/render.c b/modules/video_output/xcb/render.c
> index 1cf833f2c6..6aa1f83fc3 100644
> --- a/modules/video_output/xcb/render.c
> +++ b/modules/video_output/xcb/render.c
> @@ -541,7 +541,7 @@ FindVisual(const xcb_setup_t *setup, const xcb_screen_t *scr,
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, NULL, NULL,
> + Close, Prepare, Display, Control, NULL, NULL, NULL,
> };
>
> /**
> diff --git a/modules/video_output/xcb/x11.c b/modules/video_output/xcb/x11.c
> index f48471f0c5..0472f2c3d0 100644
> --- a/modules/video_output/xcb/x11.c
> +++ b/modules/video_output/xcb/x11.c
> @@ -251,7 +251,7 @@ static xcb_visualid_t ScreenToFormat(const xcb_setup_t *setup,
> }
>
> static const struct vlc_display_operations ops = {
> - Close, Prepare, Display, Control, ResetPictures, NULL,
> + Close, Prepare, Display, Control, ResetPictures, NULL, NULL,
> };
>
> /**
> diff --git a/modules/video_output/yuv.c b/modules/video_output/yuv.c
> index e7460a1d2f..9b39fbf99d 100644
> --- a/modules/video_output/yuv.c
> +++ b/modules/video_output/yuv.c
> @@ -87,7 +87,7 @@ struct vout_display_sys_t {
> };
>
> static const struct vlc_display_operations ops = {
> - Close, NULL, Display, Control, NULL, NULL,
> + Close, NULL, Display, Control, NULL, NULL, NULL,
> };
>
> /* */
> diff --git a/src/video_output/display.c b/src/video_output/display.c
> index 1d304e2b32..2d9d212924 100644
> --- a/src/video_output/display.c
> +++ b/src/video_output/display.c
> @@ -587,6 +587,16 @@ void vout_UpdateDisplaySourceProperties(vout_display_t *vd, const video_format_t
> vout_display_Reset(vd);
> }
>
> +int
> +VoutUpdateFormat(vout_display_t *vd, video_format_t *fmt,
> + vlc_video_context *ctx)
> +{
> + if (!vd->ops->update_format)
> + return VLC_EGENERIC;
> + return vd->ops->update_format(vd, fmt, ctx);
> +}
> +
> +
> void vout_display_SetSize(vout_display_t *vd, unsigned width, unsigned height)
> {
> vout_display_priv_t *osys = container_of(vd, vout_display_priv_t, display);
> diff --git a/src/video_output/display.h b/src/video_output/display.h
> index de1c631dc8..fe17e033a9 100644
> --- a/src/video_output/display.h
> +++ b/src/video_output/display.h
> @@ -24,3 +24,5 @@
>
> void vout_UpdateDisplaySourceProperties(vout_display_t *vd, const video_format_t *, const vlc_rational_t *forced_dar);
> void VoutFixFormatAR(video_format_t *);
> +int VoutUpdateFormat(vout_display_t *vd, video_format_t *fmt,
> + vlc_video_context *ctx);
> 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));
> +
> + 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;
> + 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))
> + {
> + 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