[vlc-devel] [PATCH 4/4] filters: add an operations structure to set the callbacks
Thomas Guillem
thomas at gllm.fr
Tue Oct 6 09:14:08 CEST 2020
This patch should be named: "VLC filters : A New Ops"
OK, sorrry, real review below...
On Mon, Oct 5, 2020, at 17:03, Steve Lhomme wrote:
> From: Alexandre Janniaux <ajanni at videolabs.io>
>
> Generate a simple operations structure for filters generating their own filter
> callback via VIDEO_FILTER_WRAPPER().
>
> The filter chain sets a mouse handler on video filters that don't have one,
> just as before, by using a local version of the ops structure of the filter and
> adding the local mouse callback.
>
> Co-authored-by: Steve Lhomme <robux4 at ycbcr.xyz>
> ---
> include/vlc_filter.h | 124 ++++++++++--------
> modules/access/screen/screen.c | 2 +-
> modules/arm_neon/chroma_yuv.c | 44 +++----
> modules/arm_neon/yuv_rgb.c | 10 +-
> modules/audio_filter/audiobargraph_a.c | 7 +-
> modules/audio_filter/center.c | 7 +-
> modules/audio_filter/channel_mixer/dolby.c | 6 +-
> .../audio_filter/channel_mixer/headphone.c | 7 +-
> modules/audio_filter/channel_mixer/mono.c | 7 +-
> modules/audio_filter/channel_mixer/remap.c | 6 +-
> modules/audio_filter/channel_mixer/simple.c | 8 +-
> .../channel_mixer/spatialaudio.cpp | 18 ++-
> modules/audio_filter/channel_mixer/trivial.c | 24 +++-
> modules/audio_filter/chorus_flanger.c | 11 +-
> modules/audio_filter/compressor.c | 7 +-
> modules/audio_filter/converter/format.c | 14 +-
> modules/audio_filter/converter/tospdif.c | 8 +-
> modules/audio_filter/equalizer.c | 7 +-
> modules/audio_filter/gain.c | 6 +-
> modules/audio_filter/karaoke.c | 7 +-
> modules/audio_filter/libebur128.c | 7 +-
> modules/audio_filter/normvol.c | 6 +-
> modules/audio_filter/param_eq.c | 20 +--
> modules/audio_filter/resampler/bandlimited.c | 6 +-
> modules/audio_filter/resampler/soxr.c | 10 +-
> modules/audio_filter/resampler/speex.c | 6 +-
> modules/audio_filter/resampler/src.c | 7 +-
> modules/audio_filter/resampler/ugly.c | 6 +-
> modules/audio_filter/scaletempo.c | 14 +-
> .../audio_filter/spatializer/spatializer.cpp | 12 +-
> modules/audio_filter/stereo_widen.c | 6 +-
> modules/hw/d3d11/d3d11_deinterlace.c | 7 +-
> modules/hw/d3d11/d3d11_filters.c | 6 +-
> modules/hw/d3d11/d3d11_surface.c | 20 +--
> modules/hw/d3d9/d3d9_filters.c | 6 +-
> modules/hw/d3d9/dxa9.c | 16 ++-
> modules/hw/d3d9/dxva2_deinterlace.c | 7 +-
> modules/hw/mmal/converter.c | 7 +-
> modules/hw/mmal/deinterlace.c | 14 +-
> modules/hw/nvdec/chroma.c | 6 +-
> modules/hw/vaapi/chroma.c | 10 +-
> modules/hw/vaapi/filters.c | 24 +++-
> modules/hw/vdpau/adjust.c | 6 +-
> modules/hw/vdpau/chroma.c | 23 +++-
> modules/hw/vdpau/deinterlace.c | 6 +-
> modules/hw/vdpau/sharpen.c | 6 +-
> modules/spu/audiobargraph_v.c | 12 +-
> modules/spu/dynamicoverlay/dynamicoverlay.c | 6 +-
> modules/spu/logo.c | 18 ++-
> modules/spu/marq.c | 6 +-
> modules/spu/mosaic.c | 6 +-
> modules/spu/rss.c | 6 +-
> modules/spu/subsdelay.c | 6 +-
> modules/text_renderer/freetype/freetype.c | 7 +-
> modules/text_renderer/nsspeechsynthesizer.m | 6 +-
> modules/text_renderer/sapi.cpp | 10 +-
> modules/text_renderer/svg.c | 6 +-
> modules/text_renderer/tdummy.c | 6 +-
> modules/video_chroma/chain.c | 15 ++-
> modules/video_chroma/cvpx.c | 28 +++-
> modules/video_chroma/grey_yuv.c | 29 ++--
> modules/video_chroma/i420_nv12.c | 12 +-
> modules/video_chroma/i420_rgb.c | 18 +--
> modules/video_chroma/i420_yuy2.c | 59 +++++----
> modules/video_chroma/i422_i420.c | 6 +-
> modules/video_chroma/i422_yuy2.c | 69 +++++-----
> modules/video_chroma/omxdl.c | 52 ++++----
> modules/video_chroma/rv32.c | 6 +-
> modules/video_chroma/swscale.c | 6 +-
> modules/video_chroma/yuvp.c | 2 +-
> modules/video_chroma/yuy2_i420.c | 6 +-
> modules/video_chroma/yuy2_i422.c | 6 +-
> modules/video_filter/adjust.c | 16 ++-
> modules/video_filter/alphamask.c | 7 +-
> modules/video_filter/anaglyph.c | 8 +-
> modules/video_filter/antiflicker.c | 7 +-
> modules/video_filter/ball.c | 6 +-
> modules/video_filter/blend.cpp | 13 +-
> modules/video_filter/blendbench.c | 12 +-
> modules/video_filter/bluescreen.c | 7 +-
> modules/video_filter/canvas.c | 7 +-
> modules/video_filter/ci_filters.m | 14 +-
> modules/video_filter/colorthres.c | 14 +-
> modules/video_filter/croppadd.c | 7 +-
> .../video_filter/deinterlace/deinterlace.c | 12 +-
> modules/video_filter/edgedetection.c | 7 +-
> modules/video_filter/erase.c | 7 +-
> modules/video_filter/extract.c | 7 +-
> modules/video_filter/fps.c | 7 +-
> modules/video_filter/freeze.c | 9 +-
> modules/video_filter/gaussianblur.c | 7 +-
> modules/video_filter/gradfun.c | 10 +-
> modules/video_filter/gradient.c | 7 +-
> modules/video_filter/grain.c | 10 +-
> modules/video_filter/hqdn3d.c | 7 +-
> modules/video_filter/invert.c | 6 +-
> modules/video_filter/magnify.c | 9 +-
> modules/video_filter/mirror.c | 6 +-
> modules/video_filter/motionblur.c | 6 +-
> modules/video_filter/motiondetect.c | 6 +-
> modules/video_filter/oldmovie.c | 6 +-
> modules/video_filter/opencv_example.cpp | 12 +-
> modules/video_filter/opencv_wrapper.c | 9 +-
> modules/video_filter/posterize.c | 6 +-
> modules/video_filter/postproc.c | 6 +-
> modules/video_filter/psychedelic.c | 6 +-
> modules/video_filter/puzzle.c | 8 +-
> modules/video_filter/ripple.c | 7 +-
> modules/video_filter/rotate.c | 14 +-
> modules/video_filter/scale.c | 7 +-
> modules/video_filter/scene.c | 8 +-
> modules/video_filter/sepia.c | 6 +-
> modules/video_filter/sharpen.c | 6 +-
> modules/video_filter/transform.c | 8 +-
> modules/video_filter/vhs.c | 6 +-
> modules/video_filter/wave.c | 6 +-
> modules/visualization/glspectrum.c | 6 +-
> modules/visualization/goom.c | 8 +-
> modules/visualization/projectm.cpp | 10 +-
> modules/visualization/visual/visual.c | 8 +-
> modules/visualization/vsxu.cpp | 10 +-
> src/audio_output/filters.c | 6 +-
> src/audio_output/meter.c | 8 +-
> src/misc/filter.c | 2 +-
> src/misc/filter_chain.c | 10 +-
> src/misc/image.c | 6 +-
> src/video_output/vout_subpictures.c | 6 +-
> 127 files changed, 1007 insertions(+), 438 deletions(-)
>
> diff --git a/include/vlc_filter.h b/include/vlc_filter.h
> index d9c274a645a..0ced8ea03d6 100644
> --- a/include/vlc_filter.h
> +++ b/include/vlc_filter.h
> @@ -79,68 +79,44 @@ typedef struct filter_owner_t
>
> struct vlc_mouse_t;
>
> -/** Structure describing a filter
> - * @warning BIG FAT WARNING : the code relies on the first 4 members of
> - * filter_t and decoder_t to be the same, so if you have anything to add,
> - * do it at the end of the structure.
> - */
> -struct filter_t
> +struct vlc_filter_operations
> {
> - struct vlc_object_t obj;
> -
> - /* Module properties */
> - module_t * p_module;
> - void *p_sys;
> -
> - /* Input format */
> - es_format_t fmt_in;
> - vlc_video_context *vctx_in; // video filter, set by owner
> -
> - /* Output format of filter */
> - es_format_t fmt_out;
> - vlc_video_context *vctx_out; // video filter, handled by the filter
> - bool b_allow_fmt_out_change;
> -
> - /* Name of the "video filter" shortcut that is requested, can be NULL */
> - const char * psz_name;
> - /* Filter configuration */
> - config_chain_t * p_cfg;
> -
> + /* Operation depending on the type of filter. */
> union
> {
> /** Filter a picture (video filter) */
> - picture_t * (*pf_video_filter)( filter_t *, picture_t * );
> + picture_t * (*filter_video)(filter_t *, picture_t *);
>
> /** Filter an audio block (audio filter) */
> - block_t * (*pf_audio_filter)( filter_t *, block_t * );
> + block_t * (*filter_audio)(filter_t *, block_t *);
>
> /** Blend a subpicture onto a picture (blend) */
> - void (*pf_video_blend)( filter_t *, picture_t *, const picture_t *,
> - int, int, int );
> + void (*blend_video)(filter_t *, picture_t *, const picture_t *,
> + int, int, int);
>
> /** Generate a subpicture (sub source) */
> - subpicture_t *(*pf_sub_source)( filter_t *, vlc_tick_t );
> + subpicture_t *(*source_sub)(filter_t *, vlc_tick_t);
>
> /** Filter a subpicture (sub filter) */
> - subpicture_t *(*pf_sub_filter)( filter_t *, subpicture_t * );
> + subpicture_t *(*filter_sub)(filter_t *, subpicture_t *);
>
> /** Render text (text render) */
> - int (*pf_render)( filter_t *, subpicture_region_t *,
> - subpicture_region_t *, const vlc_fourcc_t * );
> + int (*render)(filter_t *, subpicture_region_t *,
> + subpicture_region_t *, const vlc_fourcc_t *);
> };
>
> union
> {
> /* TODO: video filter drain */
> /** Drain (audio filter) */
> - block_t *(*pf_audio_drain) ( filter_t * );
> + block_t *(*drain_audio)(filter_t *);
> };
>
> /** Flush
> *
> * Flush (i.e. discard) any internal buffer in a video or audio filter.
> */
> - void (*pf_flush)( filter_t * );
> + void (*flush)(filter_t *);
>
> /** Change viewpoint
> *
> @@ -148,20 +124,49 @@ struct filter_t
> * used for Ambisonics rendering will change its output according to this
> * viewpoint.
> */
> - void (*pf_change_viewpoint)( filter_t *, const vlc_viewpoint_t * );
> + void (*change_viewpoint)(filter_t *, const vlc_viewpoint_t *);
>
> - union
> - {
> - /** Filter mouse state (video filter).
> - *
> - * If non-NULL, you must convert from output to input formats:
> - * - If VLC_SUCCESS is returned, the mouse state is propagated.
> - * - Otherwise, the mouse change is not propagated.
> - * If NULL, the mouse state is considered unchanged and will be
> - * propagated. */
> - int (*pf_video_mouse)( filter_t *, struct vlc_mouse_t *,
> - const struct vlc_mouse_t *p_old);
> - };
> + /** Filter mouse state (video filter).
> + *
> + * If non-NULL, you must convert from output to input formats:
> + * - If VLC_SUCCESS is returned, the mouse state is propagated.
> + * - Otherwise, the mouse change is not propagated.
> + * If NULL, the mouse state is considered unchanged and will be
> + * propagated. */
> + int (*video_mouse)(filter_t *, struct vlc_mouse_t *,
> + const struct vlc_mouse_t *p_old);
> +
> +};
> +
> +/** Structure describing a filter
> + * @warning BIG FAT WARNING : the code relies on the first 4 members of
> + * filter_t and decoder_t to be the same, so if you have anything to add,
> + * do it at the end of the structure.
> + */
> +struct filter_t
> +{
> + struct vlc_object_t obj;
> +
> + /* Module properties */
> + module_t * p_module;
> + void *p_sys;
> +
> + /* Input format */
> + es_format_t fmt_in;
> + vlc_video_context *vctx_in; // video filter, set by owner
> +
> + /* Output format of filter */
> + es_format_t fmt_out;
> + vlc_video_context *vctx_out; // video filter, handled by the filter
> + bool b_allow_fmt_out_change;
> +
> + /* Name of the "video filter" shortcut that is requested, can be NULL */
> + const char * psz_name;
> + /* Filter configuration */
> + config_chain_t * p_cfg;
> +
> + /* Implementation of filter API */
> + const struct vlc_filter_operations *ops;
>
> /** Private structure for the owner of the filter */
> filter_owner_t owner;
> @@ -170,7 +175,7 @@ struct filter_t
> /**
> * This function will return a new picture usable by p_filter as an
> output
> * buffer. You have to release it using picture_Release or by returning
> - * it to the caller as a pf_video_filter return value.
> + * it to the caller as a ops->filter_video return value.
> * Provided for convenience.
> *
> * \param p_filter filter_t object
> @@ -198,15 +203,15 @@ static inline picture_t *filter_NewPicture(
> filter_t *p_filter )
> */
> static inline void filter_Flush( filter_t *p_filter )
> {
> - if( p_filter->pf_flush != NULL )
> - p_filter->pf_flush( p_filter );
> + if( p_filter->ops && p_filter->ops->flush != NULL )
filters->ops should be mandatory no ?
> + p_filter->ops->flush( p_filter );
> }
>
> static inline void filter_ChangeViewpoint( filter_t *p_filter,
> const vlc_viewpoint_t *vp)
> {
> - if( p_filter->pf_change_viewpoint != NULL )
> - p_filter->pf_change_viewpoint( p_filter, vp );
> + if( p_filter->ops && p_filter->ops->change_viewpoint != NULL )
> + p_filter->ops->change_viewpoint( p_filter, vp );
> }
>
> static inline vlc_decoder_device * filter_HoldDecoderDevice( filter_t
> *p_filter )
> @@ -239,8 +244,8 @@ static inline vlc_decoder_device *
> filter_HoldDecoderDeviceType( filter_t *p_fil
> */
> static inline block_t *filter_DrainAudio( filter_t *p_filter )
> {
> - if( p_filter->pf_audio_drain )
> - return p_filter->pf_audio_drain( p_filter );
> + if( p_filter->ops && p_filter->ops->drain_audio )
> + return p_filter->ops->drain_audio( p_filter );
> else
> return NULL;
> }
> @@ -255,7 +260,7 @@ static inline void
> filter_SendAudioLoudness(filter_t *filter,
> /**
> * This function will return a new subpicture usable by p_filter as an
> output
> * buffer. You have to release it using subpicture_Delete or by
> returning it to
> - * the caller as a pf_sub_source return value.
> + * the caller as a ops->sub_source return value.
> * Provided for convenience.
> *
> * \param p_filter filter_t object
> @@ -353,7 +358,10 @@ VLC_API void filter_DeleteBlend( vlc_blender_t * );
> }
> \
> picture_Release( p_pic );
> \
> return p_outpic;
> \
> - }
> + }
> \
> + static const struct vlc_filter_operations name ## _ops = {
> \
> + .filter_video = name ## _Filter,
> \
> + };
>
> /**
> * Filter chain management API
> diff --git a/modules/access/screen/screen.c
> b/modules/access/screen/screen.c
> index 0c472deaa8f..fda1417eb0c 100644
> --- a/modules/access/screen/screen.c
> +++ b/modules/access/screen/screen.c
> @@ -390,7 +390,7 @@ void RenderCursor( demux_t *p_demux, int i_x, int
> i_y,
> if( p_sys->p_blend )
> {
> p_sys->dst.p->p_pixels = p_dst;
> - p_sys->p_blend->pf_video_blend( p_sys->p_blend,
> + p_sys->p_blend->ops->blend_video( p_sys->p_blend,
> &p_sys->dst,
> p_sys->p_mouse,
> #ifdef SCREEN_SUBSCREEN
> diff --git a/modules/arm_neon/chroma_yuv.c
> b/modules/arm_neon/chroma_yuv.c
> index 53fe0f86f51..6715f228a97 100644
> --- a/modules/arm_neon/chroma_yuv.c
> +++ b/modules/arm_neon/chroma_yuv.c
> @@ -231,16 +231,16 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_YUYV:
> - filter->pf_video_filter = I420_YUYV_Filter;
> + filter->ops = &I420_YUYV_ops;
> break;
> case VLC_CODEC_UYVY:
> - filter->pf_video_filter = I420_UYVY_Filter;
> + filter->ops = &I420_UYVY_ops;
> break;
> case VLC_CODEC_YVYU:
> - filter->pf_video_filter = I420_YVYU_Filter;
> + filter->ops = &I420_YVYU_ops;
> break;
> case VLC_CODEC_VYUY:
> - filter->pf_video_filter = I420_VYUY_Filter;
> + filter->ops = &I420_VYUY_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -251,16 +251,16 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_YUYV:
> - filter->pf_video_filter = I420_YVYU_Filter;
> + filter->ops = &I420_YVYU_ops;
> break;
> case VLC_CODEC_UYVY:
> - filter->pf_video_filter = I420_VYUY_Filter;
> + filter->ops = &I420_VYUY_ops;
> break;
> case VLC_CODEC_YVYU:
> - filter->pf_video_filter = I420_YUYV_Filter;
> + filter->ops = &I420_YUYV_ops;
> break;
> case VLC_CODEC_VYUY:
> - filter->pf_video_filter = I420_UYVY_Filter;
> + filter->ops = &I420_UYVY_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -271,16 +271,16 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_YUYV:
> - filter->pf_video_filter = I422_YUYV_Filter;
> + filter->ops = &I422_YUYV_ops;
> break;
> case VLC_CODEC_UYVY:
> - filter->pf_video_filter = I422_UYVY_Filter;
> + filter->ops = &I422_UYVY_ops;
> break;
> case VLC_CODEC_YVYU:
> - filter->pf_video_filter = I422_YVYU_Filter;
> + filter->ops = &I422_YVYU_ops;
> break;
> case VLC_CODEC_VYUY:
> - filter->pf_video_filter = I422_VYUY_Filter;
> + filter->ops = &I422_VYUY_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -292,10 +292,10 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter =
> Semiplanar_Planar_420_Filter;
> + filter->ops = &Semiplanar_Planar_420_ops;
> break;
> case VLC_CODEC_YV12:
> - filter->pf_video_filter =
> Semiplanar_Planar_420_Swap_Filter;
> + filter->ops = &Semiplanar_Planar_420_Swap_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -306,10 +306,10 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter =
> Semiplanar_Planar_420_Swap_Filter;
> + filter->ops = &Semiplanar_Planar_420_Swap_ops;
> break;
> case VLC_CODEC_YV12:
> - filter->pf_video_filter =
> Semiplanar_Planar_420_Filter;
> + filter->ops = &Semiplanar_Planar_420_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -320,7 +320,7 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I422:
> - filter->pf_video_filter =
> Semiplanar_Planar_422_Filter;
> + filter->ops = &Semiplanar_Planar_422_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -331,7 +331,7 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I444:
> - filter->pf_video_filter =
> Semiplanar_Planar_444_Filter;
> + filter->ops = &Semiplanar_Planar_444_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -343,7 +343,7 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I422:
> - filter->pf_video_filter = YUYV_I422_Filter;
> + filter->ops = &YUYV_I422_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -353,7 +353,7 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I422:
> - filter->pf_video_filter = UYVY_I422_Filter;
> + filter->ops = &UYVY_I422_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -363,7 +363,7 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I422:
> - filter->pf_video_filter = YVYU_I422_Filter;
> + filter->ops = &YVYU_I422_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -374,7 +374,7 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I422:
> - filter->pf_video_filter = VYUY_I422_Filter;
> + filter->ops = &VYUY_I422_ops;
> break;
> default:
> return VLC_EGENERIC;
> diff --git a/modules/arm_neon/yuv_rgb.c b/modules/arm_neon/yuv_rgb.c
> index 84b5328d768..a654a72f50d 100644
> --- a/modules/arm_neon/yuv_rgb.c
> +++ b/modules/arm_neon/yuv_rgb.c
> @@ -150,7 +150,7 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_in.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter = I420_RV16_Filter;
> + filter->ops = &I420_RV16_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -166,16 +166,16 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_in.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter = I420_RGBA_Filter;
> + filter->ops = &I420_RGBA_ops;
> break;
> case VLC_CODEC_YV12:
> - filter->pf_video_filter = YV12_RGBA_Filter;
> + filter->ops = &YV12_RGBA_ops;
> break;
> case VLC_CODEC_NV21:
> - filter->pf_video_filter = NV21_RGBA_Filter;
> + filter->ops = &NV21_RGBA_ops;
> break;
> case VLC_CODEC_NV12:
> - filter->pf_video_filter = NV12_RGBA_Filter;
> + filter->ops = &NV12_RGBA_ops;
> break;
> default:
> return VLC_EGENERIC;
> diff --git a/modules/audio_filter/audiobargraph_a.c
> b/modules/audio_filter/audiobargraph_a.c
> index e744b52f243..90a212c2901 100644
> --- a/modules/audio_filter/audiobargraph_a.c
> +++ b/modules/audio_filter/audiobargraph_a.c
> @@ -137,7 +137,12 @@ static int Open( vlc_object_t *p_this )
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> vlc_object_t *vlc = VLC_OBJECT(vlc_object_instance(p_filter));
>
> diff --git a/modules/audio_filter/center.c b/modules/audio_filter/center.c
> index fe9301cfdbf..14a41e156c3 100644
> --- a/modules/audio_filter/center.c
> +++ b/modules/audio_filter/center.c
> @@ -75,7 +75,12 @@ static int Open (vlc_object_t *in)
> filter->fmt_out.audio.i_rate = filter->fmt_in.audio.i_rate;
> aout_FormatPrepare(&filter->fmt_in.audio);
> aout_FormatPrepare(&filter->fmt_out.audio);
> - filter->pf_audio_filter = Process;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Process,
> + };
> + filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/channel_mixer/dolby.c
> b/modules/audio_filter/channel_mixer/dolby.c
> index 8d5c63c2567..de05e3eb7ff 100644
> --- a/modules/audio_filter/channel_mixer/dolby.c
> +++ b/modules/audio_filter/channel_mixer/dolby.c
> @@ -138,7 +138,11 @@ static int Create( vlc_object_t *p_this )
> ++i;
> }
>
> - p_filter->pf_audio_filter = DoWork;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/audio_filter/channel_mixer/headphone.c
> b/modules/audio_filter/channel_mixer/headphone.c
> index 0c91a158926..77aa32411ba 100644
> --- a/modules/audio_filter/channel_mixer/headphone.c
> +++ b/modules/audio_filter/channel_mixer/headphone.c
> @@ -478,7 +478,12 @@ static int OpenFilter( vlc_object_t *p_this )
> {
> p_filter->fmt_in.audio.i_physical_channels = AOUT_CHANS_5_0;
> }
> - p_filter->pf_audio_filter = Convert;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Convert,
> + };
> + p_filter->ops = &filter_ops;
>
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> aout_FormatPrepare(&p_filter->fmt_out.audio);
> diff --git a/modules/audio_filter/channel_mixer/mono.c
> b/modules/audio_filter/channel_mixer/mono.c
> index 0c383e761ec..74f8ccb736f 100644
> --- a/modules/audio_filter/channel_mixer/mono.c
> +++ b/modules/audio_filter/channel_mixer/mono.c
> @@ -384,7 +384,12 @@ static int OpenFilter( vlc_object_t *p_this )
> p_filter->fmt_out.audio.i_channels = 2;
> }
> p_filter->fmt_out.audio.i_rate = p_filter->fmt_in.audio.i_rate;
> - p_filter->pf_audio_filter = Convert;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Convert,
> + };
> + p_filter->ops = &filter_ops;
>
> msg_Dbg( p_this, "%4.4s->%4.4s, channels %d->%d, bits per sample:
> %i->%i",
> (char *)&p_filter->fmt_in.i_codec,
> diff --git a/modules/audio_filter/channel_mixer/remap.c
> b/modules/audio_filter/channel_mixer/remap.c
> index 8c49a5f1ae3..e6299f8cb8f 100644
> --- a/modules/audio_filter/channel_mixer/remap.c
> +++ b/modules/audio_filter/channel_mixer/remap.c
> @@ -366,7 +366,11 @@ static int OpenFilter( vlc_object_t *p_this )
> aout_FormatPrintChannels( audio_in ),
> aout_FormatPrintChannels( audio_out ) );
>
> - p_filter->pf_audio_filter = Remap;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Remap,
> + };
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/channel_mixer/simple.c
> b/modules/audio_filter/channel_mixer/simple.c
> index 567269a6bff..06f17e3fbfc 100644
> --- a/modules/audio_filter/channel_mixer/simple.c
> +++ b/modules/audio_filter/channel_mixer/simple.c
> @@ -345,8 +345,11 @@ static int OpenFilter( vlc_object_t *p_this )
> if( do_work == NULL )
> return VLC_EGENERIC;
>
> - p_filter->pf_audio_filter = Filter;
> - p_filter->p_sys = (void *)do_work;
> + static const struct vlc_filter_operations filter_ops =
> + { .filter_audio = Filter };
> +
> + p_filter->ops = &filter_ops;
> + p_filter->p_sys = do_work;
> return VLC_SUCCESS;
> }
>
> @@ -392,4 +395,3 @@ static block_t *Filter( filter_t *p_filter, block_t
> *p_block )
>
> return p_out;
> }
> -
> diff --git a/modules/audio_filter/channel_mixer/spatialaudio.cpp
> b/modules/audio_filter/channel_mixer/spatialaudio.cpp
> index acb9ed0b75b..803c03bbaa2 100644
> --- a/modules/audio_filter/channel_mixer/spatialaudio.cpp
> +++ b/modules/audio_filter/channel_mixer/spatialaudio.cpp
> @@ -318,6 +318,16 @@ static int allocateBuffers(filter_spatialaudio
> *p_sys)
> return VLC_SUCCESS;
> }
>
> +static const struct FilterOperationInitializer {
> + struct vlc_filter_operations ops {};
> + FilterOperationInitializer()
> + {
> + ops.filter_audio = Mix;
> + ops.flush = Flush;
> + ops.change_viewpoint = ChangeViewpoint;
> + };
> +} filter_ops;
> +
> static int OpenBinauralizer(vlc_object_t *p_this)
> {
> filter_t *p_filter = (filter_t *)p_this;
> @@ -391,9 +401,7 @@ static int OpenBinauralizer(vlc_object_t *p_this)
> aout_FormatPrepare(outfmt);
>
> p_filter->p_sys = p_sys;
> - p_filter->pf_audio_filter = Mix;
> - p_filter->pf_flush = Flush;
> - p_filter->pf_change_viewpoint = ChangeViewpoint;
> + p_filter->ops = &filter_ops.ops;
>
> return VLC_SUCCESS;
> }
> @@ -541,9 +549,7 @@ static int Open(vlc_object_t *p_this)
> }
>
> p_filter->p_sys = p_sys;
> - p_filter->pf_audio_filter = Mix;
> - p_filter->pf_flush = Flush;
> - p_filter->pf_change_viewpoint = ChangeViewpoint;
> + p_filter->ops = &filter_ops.ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/audio_filter/channel_mixer/trivial.c
> b/modules/audio_filter/channel_mixer/trivial.c
> index 6bb58e34da6..faa142e6488 100644
> --- a/modules/audio_filter/channel_mixer/trivial.c
> +++ b/modules/audio_filter/channel_mixer/trivial.c
> @@ -174,6 +174,18 @@ static int Create( vlc_object_t *p_this )
> const audio_format_t *infmt = &p_filter->fmt_in.audio;
> const audio_format_t *outfmt = &p_filter->fmt_out.audio;
>
> + static const struct vlc_filter_operations equal_filter_ops =
> + { .filter_audio = Equals };
> +
> + static const struct vlc_filter_operations extract_filter_ops =
> + { .filter_audio = Extract };
> +
> + static const struct vlc_filter_operations upmix_filter_ops =
> + { .filter_audio = Upmix };
> +
> + static const struct vlc_filter_operations downmix_filter_ops =
> + { .filter_audio = Downmix };
> +
> if( infmt->i_physical_channels == 0 )
> {
> assert( infmt->i_channels > 0 );
> @@ -181,7 +193,7 @@ static int Create( vlc_object_t *p_this )
> return VLC_EGENERIC;
> if( aout_FormatNbChannels( outfmt ) == infmt->i_channels )
> {
> - p_filter->pf_audio_filter = Equals;
> + p_filter->ops = &equal_filter_ops;
> return VLC_SUCCESS;
> }
> else
> @@ -189,7 +201,7 @@ static int Create( vlc_object_t *p_this )
> if( infmt->i_channels > AOUT_CHAN_MAX )
> msg_Info(p_filter, "%d channels will be dropped.",
> infmt->i_channels - AOUT_CHAN_MAX);
> - p_filter->pf_audio_filter = Extract;
> + p_filter->ops = &extract_filter_ops;
> return VLC_SUCCESS;
> }
> }
> @@ -211,7 +223,7 @@ static int Create( vlc_object_t *p_this )
> if ( aout_FormatNbChannels( outfmt ) == 1
> && aout_FormatNbChannels( infmt ) == 1 )
> {
> - p_filter->pf_audio_filter = Equals;
> + p_filter->ops = &equal_filter_ops;
> return VLC_SUCCESS;
> }
>
> @@ -293,7 +305,7 @@ static int Create( vlc_object_t *p_this )
> }
> if( b_equals )
> {
> - p_filter->pf_audio_filter = Equals;
> + p_filter->ops = &equal_filter_ops;
> return VLC_SUCCESS;
> }
> }
> @@ -305,9 +317,9 @@ static int Create( vlc_object_t *p_this )
> memcpy( p_sys->channel_map, channel_map, sizeof(channel_map) );
>
> if( aout_FormatNbChannels( outfmt ) > aout_FormatNbChannels( infmt ) )
> - p_filter->pf_audio_filter = Upmix;
> + p_filter->ops = &upmix_filter_ops;
> else
> - p_filter->pf_audio_filter = Downmix;
> + p_filter->ops = &downmix_filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/audio_filter/chorus_flanger.c
> b/modules/audio_filter/chorus_flanger.c
> index 8643c502f8e..6732fd412c2 100644
> --- a/modules/audio_filter/chorus_flanger.c
> +++ b/modules/audio_filter/chorus_flanger.c
> @@ -196,7 +196,12 @@ static int Open( vlc_object_t *p_this )
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> @@ -344,7 +349,7 @@ static int paramCallback( vlc_object_t *p_this,
> char const *psz_var,
> {
> p_sys->f_delayTime = oldval.f_float;
> p_sys->i_bufferLength = p_sys->i_channels * ( (int)
> - ( ( p_sys->f_delayTime +
> p_sys->f_sweepDepth ) *
> + ( ( p_sys->f_delayTime +
> p_sys->f_sweepDepth ) *
> p_filter->fmt_in.audio.i_rate/1000 ) + 1
> );
> }
> }
> @@ -357,7 +362,7 @@ static int paramCallback( vlc_object_t *p_this,
> char const *psz_var,
> {
> p_sys->f_sweepDepth = oldval.f_float;
> p_sys->i_bufferLength = p_sys->i_channels * ( (int)
> - ( ( p_sys->f_delayTime +
> p_sys->f_sweepDepth ) *
> + ( ( p_sys->f_delayTime +
> p_sys->f_sweepDepth ) *
> p_filter->fmt_in.audio.i_rate/1000 ) + 1
> );
> }
> }
> diff --git a/modules/audio_filter/compressor.c
> b/modules/audio_filter/compressor.c
> index 5aab1ceaaca..5f25865d55d 100644
> --- a/modules/audio_filter/compressor.c
> +++ b/modules/audio_filter/compressor.c
> @@ -256,7 +256,12 @@ static int Open( vlc_object_t *p_this )
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> /* At this stage, we are ready! */
> msg_Dbg( p_filter, "compressor successfully initialized" );
> diff --git a/modules/audio_filter/converter/format.c
> b/modules/audio_filter/converter/format.c
> index b7801998d98..e9098f24fe0 100644
> --- a/modules/audio_filter/converter/format.c
> +++ b/modules/audio_filter/converter/format.c
> @@ -71,10 +71,20 @@ static int Open(vlc_object_t *object)
> if (src->i_codec == dst->i_codec)
> return VLC_EGENERIC;
>
> - filter->pf_audio_filter = FindConversion(src->i_codec, dst->i_codec);
> - if (filter->pf_audio_filter == NULL)
> + cvt_t conv_func = FindConversion(src->i_codec, dst->i_codec);
> + if (conv_func == NULL)
> return VLC_EGENERIC;
>
> + struct vlc_filter_operations *filter_ops = vlc_obj_malloc(object,
> sizeof *filter_ops);
> + if (filter_ops == NULL)
> + return VLC_ENOMEM;
> +
> + (*filter_ops) = (const struct vlc_filter_operations) {
> + .filter_audio = conv_func,
> + };
> +
> + filter->ops = filter_ops;
> +
> msg_Dbg(filter, "%4.4s->%4.4s, bits per sample: %i->%i",
> (char *)&src->i_codec, (char *)&dst->i_codec,
> src->audio.i_bitspersample, dst->audio.i_bitspersample);
> diff --git a/modules/audio_filter/converter/tospdif.c
> b/modules/audio_filter/converter/tospdif.c
> index c9d7e08adcf..e513e7aa288 100644
> --- a/modules/audio_filter/converter/tospdif.c
> +++ b/modules/audio_filter/converter/tospdif.c
> @@ -616,8 +616,12 @@ static int Open( vlc_object_t *p_this )
> if( unlikely( p_sys == NULL ) )
> return VLC_ENOMEM;
>
> - p_filter->pf_audio_filter = DoWork;
> - p_filter->pf_flush = Flush;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + .flush = Flush,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/audio_filter/equalizer.c b/modules/audio_filter/equalizer.c
> index 92ccaf85b2d..b99beb7ccd3 100644
> --- a/modules/audio_filter/equalizer.c
> +++ b/modules/audio_filter/equalizer.c
> @@ -164,7 +164,11 @@ static int Open( vlc_object_t *p_this )
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> @@ -571,4 +575,3 @@ static int TwoPassCallback( vlc_object_t *p_this,
> char const *psz_cmd,
> vlc_mutex_unlock( &p_sys->lock );
> return VLC_SUCCESS;
> }
> -
> diff --git a/modules/audio_filter/gain.c b/modules/audio_filter/gain.c
> index 655d9443049..049677396f0 100644
> --- a/modules/audio_filter/gain.c
> +++ b/modules/audio_filter/gain.c
> @@ -98,7 +98,11 @@ static int Open( vlc_object_t *p_this )
> msg_Dbg( p_filter, "gain multiplier sets to %.2fx", p_sys->f_gain
> );
>
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = Process;
> +
> + static const struct vlc_filter_operations filter_ops =
> + { .filter_audio = Process };
> + p_filter->ops = &filter_ops;
> +
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/karaoke.c b/modules/audio_filter/karaoke.c
> index 62967e5cec0..2ec3d6e37c2 100644
> --- a/modules/audio_filter/karaoke.c
> +++ b/modules/audio_filter/karaoke.c
> @@ -54,7 +54,12 @@ static int Open (vlc_object_t *obj)
> filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&filter->fmt_in.audio);
> filter->fmt_out.audio = filter->fmt_in.audio;
> - filter->pf_audio_filter = Process;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Process,
> + };
> + filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/libebur128.c
> b/modules/audio_filter/libebur128.c
> index 2a1623741f0..368016eb7b6 100644
> --- a/modules/audio_filter/libebur128.c
> +++ b/modules/audio_filter/libebur128.c
> @@ -230,6 +230,10 @@ Flush(filter_t *filter)
> }
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_audio = Process, .flush = Flush,
> +};
> +
> static int Open(vlc_object_t *this)
> {
> filter_t *filter = (filter_t *) this;
> @@ -279,8 +283,7 @@ static int Open(vlc_object_t *this)
>
> filter->p_sys = sys;
> filter->fmt_out.audio = filter->fmt_in.audio;
> - filter->pf_audio_filter = Process;
> - filter->pf_flush = Flush;
> + filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/normvol.c b/modules/audio_filter/normvol.c
> index a9aa2b9cfb3..0fc01194d11 100644
> --- a/modules/audio_filter/normvol.c
> +++ b/modules/audio_filter/normvol.c
> @@ -119,7 +119,11 @@ static int Open( vlc_object_t *p_this )
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/audio_filter/param_eq.c b/modules/audio_filter/param_eq.c
> index f498ffe08f0..57efac83d56 100644
> --- a/modules/audio_filter/param_eq.c
> +++ b/modules/audio_filter/param_eq.c
> @@ -114,17 +114,22 @@ static int Open( vlc_object_t *p_this )
>
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> p_sys->f_lowf = var_InheritFloat( p_this, "param-eq-lowf");
> p_sys->f_lowgain = var_InheritFloat( p_this, "param-eq-lowgain");
> p_sys->f_highf = var_InheritFloat( p_this, "param-eq-highf");
> p_sys->f_highgain = var_InheritFloat( p_this, "param-eq-highgain");
> -
> +
> p_sys->f_f1 = var_InheritFloat( p_this, "param-eq-f1");
> p_sys->f_Q1 = var_InheritFloat( p_this, "param-eq-q1");
> p_sys->f_gain1 = var_InheritFloat( p_this, "param-eq-gain1");
> -
> +
> p_sys->f_f2 = var_InheritFloat( p_this, "param-eq-f2");
> p_sys->f_Q2 = var_InheritFloat( p_this, "param-eq-q2");
> p_sys->f_gain2 = var_InheritFloat( p_this, "param-eq-gain2");
> @@ -132,7 +137,7 @@ static int Open( vlc_object_t *p_this )
> p_sys->f_f3 = var_InheritFloat( p_this, "param-eq-f3");
> p_sys->f_Q3 = var_InheritFloat( p_this, "param-eq-q3");
> p_sys->f_gain3 = var_InheritFloat( p_this, "param-eq-gain3");
> -
> +
>
> i_samplerate = p_filter->fmt_in.audio.i_rate;
> CalcPeakEQCoeffs(p_sys->f_f1, p_sys->f_Q1, p_sys->f_gain1,
> @@ -200,18 +205,18 @@ static void CalcPeakEQCoeffs( float f0, float Q,
> float gainDB, float Fs,
> if (f0 > Fs/2*0.95f) f0 = Fs/2*0.95f;
> if (gainDB < -40) gainDB = -40;
> if (gainDB > 40) gainDB = 40;
> -
> +
> A = powf(10, gainDB/40);
> w0 = 2*((float)M_PI)*f0/Fs;
> alpha = sinf(w0)/(2*Q);
> -
> +
> b0 = 1 + alpha*A;
> b1 = -2*cosf(w0);
> b2 = 1 - alpha*A;
> a0 = 1 + alpha/A;
> a1 = -2*cosf(w0);
> a2 = 1 - alpha/A;
> -
> +
> // Store values to coeffs and normalize by 1/a0
> coeffs[0] = b0/a0;
> coeffs[1] = b1/a0;
> @@ -320,4 +325,3 @@ void ProcessEQ( const float *src, float *dest,
> float *state,
> }
> }
> }
> -
> diff --git a/modules/audio_filter/resampler/bandlimited.c
> b/modules/audio_filter/resampler/bandlimited.c
> index 2d544315af3..1256f71afd6 100644
> --- a/modules/audio_filter/resampler/bandlimited.c
> +++ b/modules/audio_filter/resampler/bandlimited.c
> @@ -279,6 +279,10 @@ static block_t *Resample( filter_t * p_filter,
> block_t * p_in_buf )
> return p_out_buf;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_audio = Resample,
> +};
> +
> /*****************************************************************************
> * OpenFilter:
> *****************************************************************************/
> @@ -306,7 +310,7 @@ static int OpenFilter( vlc_object_t *p_this )
>
> p_sys->i_old_wing = 0;
> p_sys->b_first = true;
> - p_filter->pf_audio_filter = Resample;
> + p_filter->ops = &filter_ops;
>
> msg_Dbg( p_this, "%4.4s/%iKHz/%i->%4.4s/%iKHz/%i",
> (char *)&p_filter->fmt_in.i_codec,
> diff --git a/modules/audio_filter/resampler/soxr.c
> b/modules/audio_filter/resampler/soxr.c
> index 1490d30c63e..b073e3e3a34 100644
> --- a/modules/audio_filter/resampler/soxr.c
> +++ b/modules/audio_filter/resampler/soxr.c
> @@ -188,10 +188,14 @@ Open( vlc_object_t *p_obj, bool b_change_ratio )
> (const char *)&p_filter->fmt_out.audio.i_format,
> p_filter->fmt_out.audio.i_rate );
>
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Resample,
> + .drain_audio = Drain,
> + .flush = Flush,
> + };
> + p_filter->ops = &filter_ops;
> p_filter->p_sys = p_sys;
> - p_filter->pf_audio_filter = Resample;
> - p_filter->pf_flush = Flush;
> - p_filter->pf_audio_drain = Drain;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/resampler/speex.c
> b/modules/audio_filter/resampler/speex.c
> index eeefc4f4c43..6c339489c2a 100644
> --- a/modules/audio_filter/resampler/speex.c
> +++ b/modules/audio_filter/resampler/speex.c
> @@ -92,8 +92,12 @@ static int OpenResampler (vlc_object_t *obj)
> return VLC_ENOMEM;
> }
>
> + static const struct vlc_filter_operations filter_ops =
> + { .filter_audio = Resample };
> +
> filter->p_sys = st;
> - filter->pf_audio_filter = Resample;
> + filter->ops = &filter_ops;
> +
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/resampler/src.c
> b/modules/audio_filter/resampler/src.c
> index 1254314b137..5e069e76bc6 100644
> --- a/modules/audio_filter/resampler/src.c
> +++ b/modules/audio_filter/resampler/src.c
> @@ -103,8 +103,13 @@ static int OpenResampler (vlc_object_t *obj)
> return VLC_EGENERIC;
> }
>
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Resample,
> + };
> + filter->ops = &filter_ops;
> filter->p_sys = s;
> - filter->pf_audio_filter = Resample;
> +
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/resampler/ugly.c
> b/modules/audio_filter/resampler/ugly.c
> index 63bba803c77..da13a598dd0 100644
> --- a/modules/audio_filter/resampler/ugly.c
> +++ b/modules/audio_filter/resampler/ugly.c
> @@ -77,7 +77,11 @@ static int CreateResampler( vlc_object_t *p_this )
> || !AOUT_FMT_LINEAR( &p_filter->fmt_in.audio ) )
> return VLC_EGENERIC;
>
> - p_filter->pf_audio_filter = DoWork;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/audio_filter/scaletempo.c
> b/modules/audio_filter/scaletempo.c
> index c67e01a50fc..18f8a30d106 100644
> --- a/modules/audio_filter/scaletempo.c
> +++ b/modules/audio_filter/scaletempo.c
> @@ -444,7 +444,11 @@ static int Open( vlc_object_t *p_this )
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoWork,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> @@ -510,7 +514,11 @@ static int OpenPitch( vlc_object_t *p_this )
> if( !p_sys->resampler )
> return VLC_EGENERIC;
>
> - p_filter->pf_audio_filter = DoPitchWork;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = DoPitchWork,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> @@ -609,7 +617,7 @@ static block_t *DoPitchWork( filter_t * p_filter,
> block_t * p_in_buf )
> p_filter->fmt_in.audio.i_rate = rate_shift;
>
> /* Change rate, thus changing pitch */
> - p_in_buf = p->resampler->pf_audio_filter( p->resampler, p_in_buf );
> + p_in_buf = p->resampler->ops->filter_audio( p->resampler, p_in_buf );
>
> /* Change tempo while preserving shifted pitch */
> return DoWork( p_filter, p_in_buf );
> diff --git a/modules/audio_filter/spatializer/spatializer.cpp
> b/modules/audio_filter/spatializer/spatializer.cpp
> index 4f9c19b1330..a1f78d30af9 100644
> --- a/modules/audio_filter/spatializer/spatializer.cpp
> +++ b/modules/audio_filter/spatializer/spatializer.cpp
> @@ -171,7 +171,16 @@ static int Open( vlc_object_t *p_this )
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> aout_FormatPrepare(&p_filter->fmt_in.audio);
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> +
> + static const struct FilterOperationInitializer {
> + struct vlc_filter_operations ops {};
> + FilterOperationInitializer()
> + {
> + ops.filter_audio = DoWork;
> + };
> + } filter_ops;
> +
> + p_filter->ops = &filter_ops.ops;
> return VLC_SUCCESS;
> }
>
> @@ -286,4 +295,3 @@ static int DampCallback( vlc_object_t *p_this, char
> const *,
> msg_Dbg( p_this, "'damp' value is now %3.1f", newval.f_float );
> return VLC_SUCCESS;
> }
> -
> diff --git a/modules/audio_filter/stereo_widen.c
> b/modules/audio_filter/stereo_widen.c
> index 1ec29bfffd0..ba19de6d464 100644
> --- a/modules/audio_filter/stereo_widen.c
> +++ b/modules/audio_filter/stereo_widen.c
> @@ -153,7 +153,11 @@ static int Open( vlc_object_t *obj )
> return VLC_ENOMEM;
> }
>
> - p_filter->pf_audio_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_audio = Filter,
> + };
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/hw/d3d11/d3d11_deinterlace.c
> b/modules/hw/d3d11/d3d11_deinterlace.c
> index b2c8d99447a..3eb8e9bf081 100644
> --- a/modules/hw/d3d11/d3d11_deinterlace.c
> +++ b/modules/hw/d3d11/d3d11_deinterlace.c
> @@ -232,6 +232,10 @@ picture_t *AllocPicture( filter_t *p_filter )
> return pic;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Deinterlace, .flush = Flush,
> +};
> +
> int D3D11OpenDeinterlace(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -350,8 +354,7 @@ int D3D11OpenDeinterlace(vlc_object_t *obj)
>
> filter->fmt_out.video = out_fmt;
> filter->vctx_out = vlc_video_context_Hold(filter->vctx_in);
> - filter->pf_video_filter = Deinterlace;
> - filter->pf_flush = Flush;
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
>
> return VLC_SUCCESS;
> diff --git a/modules/hw/d3d11/d3d11_filters.c
> b/modules/hw/d3d11/d3d11_filters.c
> index 868ce7ac31f..36e3351543e 100644
> --- a/modules/hw/d3d11/d3d11_filters.c
> +++ b/modules/hw/d3d11/d3d11_filters.c
> @@ -335,6 +335,10 @@ static int AdjustCallback( vlc_object_t *p_this,
> char const *psz_var,
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Filter,
> +};
> +
> static int D3D11OpenAdjust(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -507,7 +511,7 @@ static int D3D11OpenAdjust(vlc_object_t *obj)
> }
> }
>
> - filter->pf_video_filter = Filter;
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
> filter->vctx_out = vlc_video_context_Hold(filter->vctx_in);
> d3d11_device_unlock(sys->d3d_dev);
> diff --git a/modules/hw/d3d11/d3d11_surface.c
> b/modules/hw/d3d11/d3d11_surface.c
> index d6bc9ba0267..f3fe4ddbd44 100644
> --- a/modules/hw/d3d11/d3d11_surface.c
> +++ b/modules/hw/d3d11/d3d11_surface.c
> @@ -566,7 +566,7 @@ static void NV12_D3D11(filter_t *p_filter,
> picture_t *src, picture_t *dst)
> sys->staging_pic->context = NULL; // some CPU filters won't
> like the mix of CPU/GPU
>
> picture_Hold( src );
> - sys->filter->pf_video_filter(sys->filter, src);
> + sys->filter->ops->filter_video(sys->filter, src);
>
> sys->staging_pic->context = staging_pic_ctx;
> ID3D11DeviceContext_Unmap(sys->d3d_dev->d3dcontext,
> p_staging_sys->resource[KNOWN_DXGI_INDEX], 0);
> @@ -660,6 +660,10 @@ static picture_t *NV12_D3D11_Filter( filter_t
> *p_filter, picture_t *p_pic )
> return p_outpic;
> }
>
> +static const struct vlc_filter_operations NV12_D3D11_ops = {
> + .filter_video = NV12_D3D11_Filter,
> +};
> +
> int D3D11OpenConverter( vlc_object_t *obj )
> {
> filter_t *p_filter = (filter_t *)obj;
> @@ -679,34 +683,34 @@ int D3D11OpenConverter( vlc_object_t *obj )
> case VLC_CODEC_YV12:
> if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_D3D11_OPAQUE )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = D3D11_YUY2_Filter;
> + p_filter->ops = &D3D11_YUY2_ops;
> break;
> case VLC_CODEC_I420_10L:
> if( p_filter->fmt_in.video.i_chroma !=
> VLC_CODEC_D3D11_OPAQUE_10B )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = D3D11_YUY2_Filter;
> + p_filter->ops = &D3D11_YUY2_ops;
> pixel_bytes = 2;
> break;
> case VLC_CODEC_NV12:
> if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_D3D11_OPAQUE )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = D3D11_NV12_Filter;
> + p_filter->ops = &D3D11_NV12_ops;
> break;
> case VLC_CODEC_P010:
> if( p_filter->fmt_in.video.i_chroma !=
> VLC_CODEC_D3D11_OPAQUE_10B )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = D3D11_NV12_Filter;
> + p_filter->ops = &D3D11_NV12_ops;
> pixel_bytes = 2;
> break;
> case VLC_CODEC_RGBA:
> if( p_filter->fmt_in.video.i_chroma !=
> VLC_CODEC_D3D11_OPAQUE_RGBA )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = D3D11_RGBA_Filter;
> + p_filter->ops = &D3D11_RGBA_ops;
> break;
> case VLC_CODEC_BGRA:
> if( p_filter->fmt_in.video.i_chroma !=
> VLC_CODEC_D3D11_OPAQUE_BGRA )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = D3D11_RGBA_Filter;
> + p_filter->ops = &D3D11_RGBA_ops;
> break;
> default:
> return VLC_EGENERIC;
> @@ -753,7 +757,7 @@ int D3D11OpenCPUConverter( vlc_object_t *obj )
> case VLC_CODEC_YV12:
> case VLC_CODEC_NV12:
> case VLC_CODEC_P010:
> - p_filter->pf_video_filter = NV12_D3D11_Filter;
> + p_filter->ops = &NV12_D3D11_ops;
> break;
> default:
> return VLC_EGENERIC;
> diff --git a/modules/hw/d3d9/d3d9_filters.c
> b/modules/hw/d3d9/d3d9_filters.c
> index 80106bce5b2..07eaa133a99 100644
> --- a/modules/hw/d3d9/d3d9_filters.c
> +++ b/modules/hw/d3d9/d3d9_filters.c
> @@ -259,6 +259,10 @@ static int AdjustCallback( vlc_object_t *p_this,
> char const *psz_var,
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Filter,
> +};
> +
> static int D3D9OpenAdjust(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -450,7 +454,7 @@ static int D3D9OpenAdjust(vlc_object_t *obj)
>
> sys->hdecoder_dll = hdecoder_dll;
>
> - filter->pf_video_filter = Filter;
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
> filter->vctx_out = vlc_video_context_Hold(filter->vctx_in);
>
> diff --git a/modules/hw/d3d9/dxa9.c b/modules/hw/d3d9/dxa9.c
> index 563818dc708..afb484895d1 100644
> --- a/modules/hw/d3d9/dxa9.c
> +++ b/modules/hw/d3d9/dxa9.c
> @@ -258,7 +258,7 @@ static void YV12_D3D9(filter_t *p_filter, picture_t
> *src, picture_t *dst)
>
> picture_Hold( src );
>
> - sys->filter->pf_video_filter(sys->filter, src);
> + sys->filter->ops->filter_video(sys->filter, src);
>
> sys->staging->context = staging_pic_ctx;
>
> @@ -396,23 +396,23 @@ int D3D9OpenConverter( vlc_object_t *obj )
> case VLC_CODEC_YV12:
> if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = DXA9_YV12_Filter;
> + p_filter->ops = &DXA9_YV12_ops;
> break;
> case VLC_CODEC_I420_10L:
> if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = DXA9_YV12_Filter;
> + p_filter->ops = &DXA9_YV12_ops;
> pixel_bytes = 2;
> break;
> case VLC_CODEC_NV12:
> if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = DXA9_NV12_Filter;
> + p_filter->ops = &DXA9_NV12_ops;
> break;
> case VLC_CODEC_P010:
> if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B )
> return VLC_EGENERIC;
> - p_filter->pf_video_filter = DXA9_NV12_Filter;
> + p_filter->ops = &DXA9_NV12_ops;
> pixel_bytes = 2;
> break;
> default:
> @@ -433,6 +433,10 @@ int D3D9OpenConverter( vlc_object_t *obj )
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations YV12_D3D9_ops = {
> + .filter_video = YV12_D3D9_Filter,
> +};
> +
> int D3D9OpenCPUConverter( vlc_object_t *obj )
> {
> filter_t *p_filter = (filter_t *)obj;
> @@ -452,7 +456,7 @@ int D3D9OpenCPUConverter( vlc_object_t *obj )
> case VLC_CODEC_YV12:
> case VLC_CODEC_I420_10L:
> case VLC_CODEC_P010:
> - p_filter->pf_video_filter = YV12_D3D9_Filter;
> + p_filter->ops = &YV12_D3D9_ops;
> break;
> default:
> return VLC_EGENERIC;
> diff --git a/modules/hw/d3d9/dxva2_deinterlace.c
> b/modules/hw/d3d9/dxva2_deinterlace.c
> index 7c0c4ec6920..0d5f5825500 100644
> --- a/modules/hw/d3d9/dxva2_deinterlace.c
> +++ b/modules/hw/d3d9/dxva2_deinterlace.c
> @@ -321,6 +321,10 @@ picture_t *AllocPicture( filter_t *p_filter )
> return pic;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Deinterlace, .flush = Flush,
> +};
> +
> int D3D9OpenDeinterlace(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -501,8 +505,7 @@ int D3D9OpenDeinterlace(vlc_object_t *obj)
>
> filter->fmt_out.video = out_fmt;
> filter->vctx_out = vlc_video_context_Hold(filter->vctx_in);
> - filter->pf_video_filter = Deinterlace;
> - filter->pf_flush = Flush;
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
>
> return VLC_SUCCESS;
> diff --git a/modules/hw/mmal/converter.c b/modules/hw/mmal/converter.c
> index f62f21e0876..eecf36eac00 100644
> --- a/modules/hw/mmal/converter.c
> +++ b/modules/hw/mmal/converter.c
> @@ -787,6 +787,10 @@ static MMAL_FOURCC_T filter_enc_in(const
> video_format_t * const fmt)
> }
>
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = conv_filter, .flush = conv_flush,
> +};
> +
> int OpenConverter(vlc_object_t * obj)
> {
> filter_t * const p_filter = (filter_t *)obj;
> @@ -975,8 +979,7 @@ retry:
> }
> }
>
> - p_filter->pf_video_filter = conv_filter;
> - p_filter->pf_flush = conv_flush;
> + p_filter->ops = &filter_ops;
> // video_drain NIF in filter structure
>
> return VLC_SUCCESS;
> diff --git a/modules/hw/mmal/deinterlace.c b/modules/hw/mmal/deinterlace.c
> index 2709a1f1730..97c11a20c81 100644
> --- a/modules/hw/mmal/deinterlace.c
> +++ b/modules/hw/mmal/deinterlace.c
> @@ -417,6 +417,14 @@ static bool is_fmt_valid_in(const vlc_fourcc_t fmt)
> return fmt == VLC_CODEC_MMAL_OPAQUE;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = deinterlace, .flush = di_flush,
> +};
> +
> +static const struct vlc_filter_operations filter_pass_ops = {
> + .filter_video = pass_deinterlace, .flush = pass_flush,
> +};
> +
> static int OpenMmalDeinterlace(vlc_object_t *p_this)
> {
> filter_t *filter = (filter_t*)p_this;
> @@ -499,8 +507,7 @@ static int OpenMmalDeinterlace(vlc_object_t *p_this)
>
> if (sys->use_passthrough)
> {
> - filter->pf_video_filter = pass_deinterlace;
> - filter->pf_flush = pass_flush;
> + filter->ops = &filter_pass_ops;
> return VLC_SUCCESS;
> }
>
> @@ -600,8 +607,7 @@ static int OpenMmalDeinterlace(vlc_object_t *p_this)
> goto fail;
> }
>
> - filter->pf_video_filter = deinterlace;
> - filter->pf_flush = di_flush;
> + filter->ops = &filter_ops;
> return 0;
>
> fail:
> diff --git a/modules/hw/nvdec/chroma.c b/modules/hw/nvdec/chroma.c
> index 88353f5cbed..2e09fb18cef 100644
> --- a/modules/hw/nvdec/chroma.c
> +++ b/modules/hw/nvdec/chroma.c
> @@ -117,6 +117,10 @@ done:
> return dst;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = FilterCUDAToCPU,
> +};
> +
> static int OpenCUDAToCPU( vlc_object_t *p_this )
> {
> filter_t *p_filter = (filter_t *)p_this;
> @@ -137,7 +141,7 @@ static int OpenCUDAToCPU( vlc_object_t *p_this )
> ) )
> return VLC_EGENERIC;
>
> - p_filter->pf_video_filter = FilterCUDAToCPU;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/hw/vaapi/chroma.c b/modules/hw/vaapi/chroma.c
> index 38b904ed203..7ea95254d40 100644
> --- a/modules/hw/vaapi/chroma.c
> +++ b/modules/hw/vaapi/chroma.c
> @@ -316,6 +316,14 @@ static int CheckFmt(const video_format_t *in,
> const video_format_t *out,
> return VLC_EGENERIC;
> }
>
> +static const struct vlc_filter_operations filter_upload_ops = {
> + .filter_video = UploadSurface,
> +};
> +
> +static const struct vlc_filter_operations filter_download_ops = {
> + .filter_video = DownloadSurface,
> +};
> +
> int
> vlc_vaapi_OpenChroma(vlc_object_t *obj)
> {
> @@ -333,7 +341,7 @@ vlc_vaapi_OpenChroma(vlc_object_t *obj)
> &pixel_bytes))
> return VLC_EGENERIC;
>
> - filter->pf_video_filter = is_upload ? UploadSurface : DownloadSurface;
> + filter->ops = is_upload ? &filter_upload_ops : &filter_download_ops;
>
> if (!(filter_sys = calloc(1, sizeof(filter_sys_t))))
> {
> diff --git a/modules/hw/vaapi/filters.c b/modules/hw/vaapi/filters.c
> index debe2b507b1..ac96b16c81c 100644
> --- a/modules/hw/vaapi/filters.c
> +++ b/modules/hw/vaapi/filters.c
> @@ -567,6 +567,10 @@ OpenAdjust_InitFilterParams(filter_t * filter,
> void * p_data,
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations Adjust_ops = {
> + .filter_video = Adjust,
> +};
> +
> static int
> OpenAdjust(vlc_object_t * obj)
> {
> @@ -587,7 +591,7 @@ OpenAdjust(vlc_object_t * obj)
> for (unsigned int i = 0; i < NUM_ADJUST_MODES; ++i)
> var_AddCallback(obj, adjust_params_names[i], FilterCallback, p_data);
>
> - filter->pf_video_filter = Adjust;
> + filter->ops = &Adjust_ops;
>
> return VLC_SUCCESS;
>
> @@ -684,6 +688,10 @@ OpenBasicFilter_InitFilterParams(filter_t *
> filter, void * p_data,
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations BasicFilter_ops = {
> + .filter_video = BasicFilter,
> +};
> +
> static int
> OpenBasicFilter(vlc_object_t * obj, VAProcFilterType filter_type,
> const char *psz_sigma_name, struct range const
> *p_vlc_range)
> @@ -708,7 +716,7 @@ OpenBasicFilter(vlc_object_t * obj,
> VAProcFilterType filter_type,
>
> var_AddCallback(obj, p_data->sigma.psz_name, FilterCallback, p_data);
>
> - filter->pf_video_filter = BasicFilter;
> + filter->ops = &BasicFilter_ops;
>
> return VLC_SUCCESS;
>
> @@ -1065,6 +1073,13 @@ OpenDeinterlace_InitHistory(void * p_data,
> VAProcPipelineCaps const * pipeline_c
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations DeinterlaceX2_ops = {
> + .filter_video = DeinterlaceX2, .flush = Deinterlace_Flush,
> +};
> +static const struct vlc_filter_operations Deinterlace_ops = {
> + .filter_video = Deinterlace, .flush = Deinterlace_Flush,
> +};
> +
> static int
> OpenDeinterlace(vlc_object_t * obj)
> {
> @@ -1079,10 +1094,9 @@ OpenDeinterlace(vlc_object_t * obj)
> goto error;
>
> if (p_data->b_double_rate)
> - filter->pf_video_filter = DeinterlaceX2;
> + filter->ops = &DeinterlaceX2_ops;
> else
> - filter->pf_video_filter = Deinterlace;
> - filter->pf_flush = Deinterlace_Flush;
> + filter->ops = &Deinterlace_ops;
>
> for (unsigned int i = 0; i < METADATA_SIZE; ++i)
> {
> diff --git a/modules/hw/vdpau/adjust.c b/modules/hw/vdpau/adjust.c
> index 27c8b4bfa7d..3a4d5a5387a 100644
> --- a/modules/hw/vdpau/adjust.c
> +++ b/modules/hw/vdpau/adjust.c
> @@ -139,6 +139,10 @@ static const char *const options[] = {
> "brightness", "contrast", "saturation", "hue", NULL
> };
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Adjust,
> +};
> +
> static int Open(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -157,7 +161,7 @@ static int Open(vlc_object_t *obj)
> if (unlikely(sys == NULL))
> return VLC_ENOMEM;
>
> - filter->pf_video_filter = Adjust;
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
>
> config_ChainParse(filter, "", options, filter->p_cfg);
> diff --git a/modules/hw/vdpau/chroma.c b/modules/hw/vdpau/chroma.c
> index fa4b1e8b62c..06c1a633d89 100644
> --- a/modules/hw/vdpau/chroma.c
> +++ b/modules/hw/vdpau/chroma.c
> @@ -743,6 +743,14 @@ const struct vlc_video_context_operations
> vdpau_vctx_ops = {
> NULL,
> };
>
> +static const struct vlc_filter_operations filter_output_opaque_ops = {
> + .filter_video = VideoRender, .flush = Flush,
> +};
> +
> +static const struct vlc_filter_operations filter_output_ycbcr_ops = {
> + .filter_video = YCbCrRender, .flush = Flush,
> +};
> +
> static int OutputOpen(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -766,7 +774,7 @@ static int OutputOpen(vlc_object_t *obj)
>
> filter->p_sys = sys;
>
> - picture_t *(*video_filter)(filter_t *, picture_t *) = VideoRender;
> + const struct vlc_filter_operations *ops = &filter_output_opaque_ops;
>
> if (filter->fmt_in.video.i_chroma == VLC_CODEC_VDPAU_VIDEO_444)
> {
> @@ -789,7 +797,7 @@ static int OutputOpen(vlc_object_t *obj)
> else
> if (vlc_fourcc_to_vdp_ycc(filter->fmt_in.video.i_chroma,
> &sys->chroma, &sys->format))
> - video_filter = YCbCrRender;
> + ops = &filter_output_ycbcr_ops;
> else
> {
> vlc_decoder_device_Release(dec_device);
> @@ -817,7 +825,7 @@ static int OutputOpen(vlc_object_t *obj)
> }
>
> /* Create the video-to-output mixer */
> - sys->mixer = MixerCreate(filter, video_filter == YCbCrRender);
> + sys->mixer = MixerCreate(filter, ops == &filter_output_ycbcr_ops);
> if (sys->mixer == VDP_INVALID_HANDLE)
> {
> picture_pool_Release(sys->pool);
> @@ -834,8 +842,7 @@ static int OutputOpen(vlc_object_t *obj)
> sys->procamp.saturation = 1.f;
> sys->procamp.hue = 0.f;
>
> - filter->pf_video_filter = video_filter;
> - filter->pf_flush = Flush;
> + filter->ops = ops;
> return VLC_SUCCESS;
> }
>
> @@ -888,6 +895,10 @@ static bool ChromaMatches(VdpChromaType vdp_type,
> vlc_fourcc_t vlc_chroma)
> }
> }
>
> +static const struct vlc_filter_operations filter_ycbcr_ops = {
> + .filter_video = VideoExport_Filter,
> +};
> +
> static int YCbCrOpen(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -913,7 +924,7 @@ static int YCbCrOpen(vlc_object_t *obj)
> return VLC_ENOMEM;
> sys->format = format;
>
> - filter->pf_video_filter = VideoExport_Filter;
> + filter->ops = &filter_ycbcr_ops;
> filter->p_sys = sys;
> return VLC_SUCCESS;
> }
> diff --git a/modules/hw/vdpau/deinterlace.c
> b/modules/hw/vdpau/deinterlace.c
> index bd66a61d1b0..2a5a996f384 100644
> --- a/modules/hw/vdpau/deinterlace.c
> +++ b/modules/hw/vdpau/deinterlace.c
> @@ -96,6 +96,10 @@ static picture_t *Deinterlace(filter_t *filter,
> picture_t *src)
> return src;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Deinterlace,
> +};
> +
> static int Open(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -119,7 +123,7 @@ static int Open(vlc_object_t *obj)
>
> sys->last_pts = VLC_TICK_INVALID;
>
> - filter->pf_video_filter = Deinterlace;
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
> filter->fmt_out.video.i_frame_rate *= 2;
> filter->vctx_out = vlc_video_context_Hold(filter->vctx_in);
> diff --git a/modules/hw/vdpau/sharpen.c b/modules/hw/vdpau/sharpen.c
> index 4aee7e3c406..718eedddb1f 100644
> --- a/modules/hw/vdpau/sharpen.c
> +++ b/modules/hw/vdpau/sharpen.c
> @@ -79,6 +79,10 @@ static picture_t *Sharpen(filter_t *filter, picture_t *pic)
>
> static const char *const options[] = { "sigma", NULL };
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Sharpen,
> +};
> +
> static int Open(vlc_object_t *obj)
> {
> filter_t *filter = (filter_t *)obj;
> @@ -125,7 +129,7 @@ static int Open(vlc_object_t *obj)
> if (unlikely(sys == NULL))
> return VLC_ENOMEM;
>
> - filter->pf_video_filter = Sharpen;
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
>
> config_ChainParse(filter, "sharpen-", options, filter->p_cfg);
> diff --git a/modules/spu/audiobargraph_v.c b/modules/spu/audiobargraph_v.c
> index de3f9627a6f..9fdc78c7e4d 100644
> --- a/modules/spu/audiobargraph_v.c
> +++ b/modules/spu/audiobargraph_v.c
> @@ -487,6 +487,14 @@ out:
> return p_dst;
> }
>
> +static const struct vlc_filter_operations filter_sub_ops = {
> + .source_sub = FilterSub,
> +};
> +
> +static const struct vlc_filter_operations filter_video_ops = {
> + .filter_video = FilterVideo,
> +};
> +
> /**
> * Common open function
> */
> @@ -558,9 +566,9 @@ static int OpenCommon(vlc_object_t *p_this, bool b_sub)
> BarGraphCallback, p_sys);
>
> if (b_sub)
> - p_filter->pf_sub_source = FilterSub;
> + p_filter->ops = &filter_sub_ops;
> else
> - p_filter->pf_video_filter = FilterVideo;
> + p_filter->ops = &filter_video_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/spu/dynamicoverlay/dynamicoverlay.c
> b/modules/spu/dynamicoverlay/dynamicoverlay.c
> index b038a2d66ac..37cdf7936da 100644
> --- a/modules/spu/dynamicoverlay/dynamicoverlay.c
> +++ b/modules/spu/dynamicoverlay/dynamicoverlay.c
> @@ -81,6 +81,10 @@ static const char *const ppsz_filter_options[] = {
> "input", "output", NULL
> };
>
> +static const struct vlc_filter_operations filter_ops = {
> + .source_sub = Filter,
> +};
> +
> /*****************************************************************************
> * Create: allocates adjust video thread output method
> *****************************************************************************
> @@ -110,7 +114,7 @@ static int Create( vlc_object_t *p_this )
> p_sys->b_atomic = false;
> vlc_mutex_init( &p_sys->lock );
>
> - p_filter->pf_sub_source = Filter;
> + p_filter->ops = &filter_ops;
>
> config_ChainParse( p_filter, "overlay-", ppsz_filter_options,
> p_filter->p_cfg );
> diff --git a/modules/spu/logo.c b/modules/spu/logo.c
> index c8d1b02445b..9a713cb2407 100644
> --- a/modules/spu/logo.c
> +++ b/modules/spu/logo.c
> @@ -215,6 +215,15 @@ static int OpenVideo( vlc_object_t *p_this )
> return OpenCommon( p_this, false );
> }
>
> +static const struct vlc_filter_operations filter_sub_ops = {
> + .source_sub = FilterSub,
> +};
> +
> +static const struct vlc_filter_operations filter_video_ops = {
> + .filter_video = FilterVideo,
> + .video_mouse = Mouse,
> +};
> +
> /**
> * Common open function
> */
> @@ -293,14 +302,9 @@ static int OpenCommon( vlc_object_t *p_this, bool b_sub )
>
> /* Misc init */
> if( b_sub )
> - {
> - p_filter->pf_sub_source = FilterSub;
> - }
> + p_filter->ops = &filter_sub_ops;
> else
> - {
> - p_filter->pf_video_filter = FilterVideo;
> - p_filter->pf_video_mouse = Mouse;
> - }
> + p_filter->ops = &filter_video_ops;
>
> free( psz_filename );
> return VLC_SUCCESS;
> diff --git a/modules/spu/marq.c b/modules/spu/marq.c
> index c370c5322dc..31657aa0478 100644
> --- a/modules/spu/marq.c
> +++ b/modules/spu/marq.c
> @@ -178,6 +178,10 @@ static const char *const ppsz_filter_options[] = {
> NULL
> };
>
> +static const struct vlc_filter_operations filter_ops = {
> + .source_sub = Filter,
> +};
> +
> /*****************************************************************************
> * CreateFilter: allocates marquee video filter
> *****************************************************************************/
> @@ -228,7 +232,7 @@ static int CreateFilter( vlc_object_t *p_this )
> CREATE_VAR( p_style->i_font_size, Integer, "marq-size" );
>
> /* Misc init */
> - p_filter->pf_sub_source = Filter;
> + p_filter->ops = &filter_ops;
> p_sys->last_time = 0;
>
> return VLC_SUCCESS;
> diff --git a/modules/spu/mosaic.c b/modules/spu/mosaic.c
> index deecc74e73c..c8544950014 100644
> --- a/modules/spu/mosaic.c
> +++ b/modules/spu/mosaic.c
> @@ -271,6 +271,10 @@ static void mosaic_ParseSetOffsets( vlc_object_t *p_this,
> #define mosaic_ParseSetOffsets( a, b, c ) \
> mosaic_ParseSetOffsets( VLC_OBJECT( a ), b, c )
>
> +static const struct vlc_filter_operations filter_ops = {
> + .source_sub = Filter,
> +};
> +
> /*****************************************************************************
> * CreateFiler: allocate mosaic video filter
> *****************************************************************************/
> @@ -288,7 +292,7 @@ static int CreateFilter( vlc_object_t *p_this )
> if( p_sys == NULL )
> return VLC_ENOMEM;
>
> - p_filter->pf_sub_source = Filter;
> + p_filter->ops = &filter_ops;
>
> vlc_mutex_init( &p_sys->lock );
> vlc_mutex_lock( &p_sys->lock );
> diff --git a/modules/spu/rss.c b/modules/spu/rss.c
> index 95f55e34a4b..08c5ea59577 100644
> --- a/modules/spu/rss.c
> +++ b/modules/spu/rss.c
> @@ -240,6 +240,10 @@ static void InitCurrentContext(filter_sys_t *p_sys)
> p_sys->i_cur_char = -1;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .source_sub = Filter,
> +};
> +
> /*****************************************************************************
> * CreateFilter: allocates RSS video filter
> *****************************************************************************/
> @@ -311,7 +315,7 @@ static int CreateFilter( vlc_object_t *p_this )
>
> /* Misc init */
> vlc_mutex_init( &p_sys->lock );
> - p_filter->pf_sub_source = Filter;
> + p_filter->ops = &filter_ops;
> p_sys->last_date = (vlc_tick_t)0;
> p_sys->b_fetched = false;
>
> diff --git a/modules/spu/subsdelay.c b/modules/spu/subsdelay.c
> index 70b2e9a332f..b17a4325655 100644
> --- a/modules/spu/subsdelay.c
> +++ b/modules/spu/subsdelay.c
> @@ -293,6 +293,10 @@ vlc_module_begin()
>
> static const char * const ppsz_filter_options[] = { "mode", "factor",
> "overlap", NULL };
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_sub = SubsdelayFilter,
> +};
> +
>
> /*****************************************************************************
> * SubsdelayCreate: Create subsdelay filter
>
> *****************************************************************************/
> @@ -336,7 +340,7 @@ static int SubsdelayCreate( vlc_object_t *p_this )
> var_AddCallback( p_filter, CFG_MIN_START_STOP_INTERVAL,
> SubsdelayCallback, p_sys );
>
> p_filter->p_sys = p_sys;
> - p_filter->pf_sub_filter = SubsdelayFilter;
> + p_filter->ops = &filter_ops;
>
> config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
> p_filter->p_cfg );
>
> diff --git a/modules/text_renderer/freetype/freetype.c
> b/modules/text_renderer/freetype/freetype.c
> index 5b5fc2d08f2..fe78056212d 100644
> --- a/modules/text_renderer/freetype/freetype.c
> +++ b/modules/text_renderer/freetype/freetype.c
> @@ -1159,6 +1159,11 @@ static int Render( filter_t *p_filter,
> subpicture_region_t *p_region_out,
> return rv;
> }
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .render = Render,
> +};
> +
> /*****************************************************************************
> * Create: allocates osd-text video thread output method
> *****************************************************************************
> @@ -1236,7 +1241,7 @@ static int Create( vlc_object_t *p_this )
> if( LoadFontsFromAttachments( p_filter ) == VLC_ENOMEM )
> goto error;
>
> - p_filter->pf_render = Render;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
>
> diff --git a/modules/text_renderer/nsspeechsynthesizer.m
> b/modules/text_renderer/nsspeechsynthesizer.m
> index 1b71c779ec6..5e6774f09af 100644
> --- a/modules/text_renderer/nsspeechsynthesizer.m
> +++ b/modules/text_renderer/nsspeechsynthesizer.m
> @@ -58,6 +58,10 @@ typedef struct filter_sys_t
> NSString *lastString;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops = {
> + .render = RenderText,
> +};
> +
> static int Create (vlc_object_t *p_this)
> {
> filter_t *p_filter = (filter_t *)p_this;
> @@ -70,7 +74,7 @@ static int Create (vlc_object_t *p_this)
> p_sys->currentLocale = p_sys->lastString = @"";
> p_sys->speechSynthesizer = [[NSSpeechSynthesizer alloc] init];
>
> - p_filter->pf_render = RenderText;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/text_renderer/sapi.cpp b/modules/text_renderer/sapi.cpp
> index 874f5c83143..ad5109ef05c 100644
> --- a/modules/text_renderer/sapi.cpp
> +++ b/modules/text_renderer/sapi.cpp
> @@ -93,6 +93,14 @@ static void LeaveMTA(void)
> CoUninitialize();
> }
>
> +static const struct FilterOperationInitializer {
> + struct vlc_filter_operations ops {};
> + FilterOperationInitializer()
> + {
> + ops.render = RenderText;
> + };
> +} filter_ops;
> +
> static int Create (vlc_object_t *p_this)
> {
> filter_t *p_filter = (filter_t *)p_this;
> @@ -157,7 +165,7 @@ static int Create (vlc_object_t *p_this)
>
> LeaveMTA();
>
> - p_filter->pf_render = RenderText;
> + p_filter->ops = &filter_ops.ops;
>
> return VLC_SUCCESS;
>
> diff --git a/modules/text_renderer/svg.c b/modules/text_renderer/svg.c
> index f97c5fa3bf6..5e710d15eec 100644
> --- a/modules/text_renderer/svg.c
> +++ b/modules/text_renderer/svg.c
> @@ -169,6 +169,10 @@ static char *svg_GetDocument( filter_t *p_filter,
> int i_width, int i_height, con
> return psz_result;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .render = RenderText,
> +};
> +
> /*****************************************************************************
> * Create: allocates svg video thread output method
> *****************************************************************************
> @@ -184,7 +188,7 @@ static int Create( vlc_object_t *p_this )
> return VLC_ENOMEM;
> p_filter->p_sys = p_sys;
>
> - p_filter->pf_render = RenderText;
> + p_filter->ops = &filter_ops;
> svg_LoadTemplate( p_filter );
>
> #if (GLIB_MAJOR_VERSION < 2 || GLIB_MINOR_VERSION < 36)
> diff --git a/modules/text_renderer/tdummy.c
> b/modules/text_renderer/tdummy.c
> index 3451c1068c9..4fd996674c1 100644
> --- a/modules/text_renderer/tdummy.c
> +++ b/modules/text_renderer/tdummy.c
> @@ -47,9 +47,13 @@ static int RenderText( filter_t *p_filter,
> subpicture_region_t *p_region_out,
> return VLC_EGENERIC;
> }
>
> +static const struct vlc_filter_operations filter_ops = {
> + .render = RenderText,
> +};
> +
> static int OpenRenderer( vlc_object_t *p_this )
> {
> filter_t *p_filter = (filter_t *)p_this;
> - p_filter->pf_render = RenderText;
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_chroma/chain.c b/modules/video_chroma/chain.c
> index 7ec2798cc3c..c25711c7d32 100644
> --- a/modules/video_chroma/chain.c
> +++ b/modules/video_chroma/chain.c
> @@ -114,6 +114,7 @@ typedef struct
> {
> filter_chain_t *p_chain;
> filter_t *p_video_filter;
> + struct vlc_filter_operations custom_ops;
> } filter_sys_t;
>
> /* Restart filter callback */
> @@ -152,6 +153,10 @@ static const struct filter_video_callbacks
> filter_video_chain_cbs =
> BufferChainNew, HoldChainDecoderDevice,
> };
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Chain,
> +};
> +
>
> /*****************************************************************************
> * Activate: allocate a chroma function
>
> *****************************************************************************
> @@ -213,7 +218,7 @@ static int Activate( filter_t *p_filter, int
> (*pf_build)(filter_t *) )
> }
> assert(p_filter->vctx_out == filter_chain_GetVideoCtxOut(
> p_sys->p_chain ));
> /* */
> - p_filter->pf_video_filter = Chain;
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> @@ -409,8 +414,12 @@ static int BuildFilterChain( filter_t *p_filter )
> filter_AddProxyCallbacks( p_filter,
> p_sys->p_video_filter,
> RestartFilterCallback );
> - if (p_sys->p_video_filter->pf_video_mouse != NULL)
> - p_filter->pf_video_mouse = ChainMouse;
> + if (p_sys->p_video_filter->ops->video_mouse != NULL)
> + {
> + p_sys->custom_ops = *p_sys->p_video_filter->ops;
> + p_sys->p_video_filter->ops = &p_sys->custom_ops;
> + p_sys->custom_ops.video_mouse = ChainMouse;
> + }
> es_format_Clean( &fmt_mid );
> i_ret = VLC_SUCCESS;
> p_filter->vctx_out = filter_chain_GetVideoCtxOut(
> p_sys->p_chain );
> diff --git a/modules/video_chroma/cvpx.c b/modules/video_chroma/cvpx.c
> index f3ece816328..062b1ef0f9a 100644
> --- a/modules/video_chroma/cvpx.c
> +++ b/modules/video_chroma/cvpx.c
> @@ -248,6 +248,13 @@ static void Close(vlc_object_t *obj)
> free(p_sys);
> }
>
> +static const struct vlc_filter_operations CVPX_TO_SW_ops = {
> + .filter_video = CVPX_TO_SW_Filter,
> +};
> +static const struct vlc_filter_operations SW_TO_CVPX_ops = {
> + .filter_video = SW_TO_CVPX_Filter,
> +};
> +
> static int Open(vlc_object_t *obj)
> {
> filter_t *p_filter = (filter_t *)obj;
> @@ -261,9 +268,9 @@ static int Open(vlc_object_t *obj)
> case VLC_CODEC_CVPX_##x: \
> sw_fmt = p_filter->fmt_out.video; \
> if (p_filter->fmt_out.video.i_chroma == VLC_CODEC_##x) \
> - p_filter->pf_video_filter = CVPX_TO_SW_Filter; \
> + p_filter->ops = &CVPX_TO_SW_ops; \
> else if (i420_fcc != 0 && p_filter->fmt_out.video.i_chroma ==
> i420_fcc) { \
> - p_filter->pf_video_filter = CVPX_TO_SW_Filter; \
> + p_filter->ops = &CVPX_TO_SW_ops; \
> sw_fmt.i_chroma = VLC_CODEC_##x; \
> } else return VLC_EGENERIC; \
>
> @@ -271,10 +278,10 @@ static int Open(vlc_object_t *obj)
> case VLC_CODEC_CVPX_##x: \
> sw_fmt = p_filter->fmt_in.video; \
> if (p_filter->fmt_in.video.i_chroma == VLC_CODEC_##x) { \
> - p_filter->pf_video_filter = SW_TO_CVPX_Filter; \
> + p_filter->ops = &SW_TO_CVPX_ops; \
> } \
> else if (i420_fcc != 0 && p_filter->fmt_in.video.i_chroma ==
> i420_fcc) { \
> - p_filter->pf_video_filter = SW_TO_CVPX_Filter; \
> + p_filter->ops = &SW_TO_CVPX_ops; \
> sw_fmt.i_chroma = VLC_CODEC_##x; \
> } else return VLC_EGENERIC; \
> b_need_pool = true;
> @@ -432,6 +439,10 @@ static vlc_fourcc_t const supported_chromas[] = {
> VLC_CODEC_CVPX_BGRA,
> VLC_CODEC_CVPX_P010,
> VLC_CODEC_CVPX_UYVY
> };
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Filter,
> +};
> +
> static int
> Open_CVPX_to_CVPX(vlc_object_t *obj)
> {
> @@ -480,7 +491,7 @@ Open_CVPX_to_CVPX(vlc_object_t *obj)
> }
>
> filter->p_sys = p_sys;
> - filter->pf_video_filter = Filter;
> + filter->ops = &filter_ops;
> filter->vctx_out = vlc_video_context_Hold(filter->vctx_in);
> filter->fmt_out.i_codec = filter->fmt_out.video.i_chroma;
> return VLC_SUCCESS;
> @@ -553,6 +564,10 @@ static const vlc_fourcc_t supported_sw_chromas[] = {
> VLC_CODEC_UYVY, VLC_CODEC_P010,
> };
>
> +static const struct vlc_filter_operations chain_CVPX_ops = {
> + .filter_video = chain_CVPX_Filter, .flush = chain_CVPX_Flush,
> +};
> +
> static int
> Open_chain_CVPX(vlc_object_t *obj)
> {
> @@ -656,8 +671,7 @@ Open_chain_CVPX(vlc_object_t *obj)
>
> filter->vctx_out = vctx_out;
> filter->p_sys = chain;
> - filter->pf_flush = chain_CVPX_Flush;
> - filter->pf_video_filter = chain_CVPX_Filter;
> + filter->ops = &chain_CVPX_ops;
>
> /* Display the current conversion chain in the logs. */
> msg_Dbg(filter, "CVPX conversion chain:");
> diff --git a/modules/video_chroma/grey_yuv.c b/modules/video_chroma/grey_yuv.c
> index ea09775c9cb..308bd5c24b0 100644
> --- a/modules/video_chroma/grey_yuv.c
> +++ b/modules/video_chroma/grey_yuv.c
> @@ -56,6 +56,20 @@ vlc_module_end ()
> VIDEO_FILTER_WRAPPER( GREY_I420 )
> VIDEO_FILTER_WRAPPER( GREY_YUY2 )
>
> +static const struct vlc_filter_operations *
> +GetFilterOperations( filter_t *filter )
> +{
> + switch( filter->fmt_out.video.i_chroma )
> + {
> + case VLC_CODEC_I420:
> + return &GREY_I420_ops;
> + case VLC_CODEC_YUYV:
> + return &GREY_YUY2_ops;
> + default:
> + return NULL;
> + }
> +}
> +
> /*****************************************************************************
> * Activate: allocate a chroma function
> *****************************************************************************
> @@ -78,18 +92,9 @@ static int Activate( vlc_object_t *p_this )
>
> if ( p_filter->fmt_in.video.i_chroma != VLC_CODEC_GREY )
> return VLC_EGENERIC;
> -
> - switch( p_filter->fmt_out.video.i_chroma )
> - {
> - case VLC_CODEC_I420:
> - p_filter->pf_video_filter = GREY_I420_Filter;
> - break;
> - case VLC_CODEC_YUYV:
> - p_filter->pf_video_filter = GREY_YUY2_Filter;
> - break;
> - default:
> - return VLC_EGENERIC;
> - }
> + p_filter->ops = GetFilterOperations(p_filter);
> + if ( p_filter->ops == NULL )
> + return VLC_EGENERIC;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_chroma/i420_nv12.c b/modules/video_chroma/i420_nv12.c
> index 53e1364adfc..fe27022517d 100644
> --- a/modules/video_chroma/i420_nv12.c
> +++ b/modules/video_chroma/i420_nv12.c
> @@ -168,23 +168,23 @@ static int Create( vlc_object_t *p_this )
> case VLC_CODEC_J420:
> if( outfcc != VLC_CODEC_NV12 )
> return -1;
> - p_filter->pf_video_filter = I420_NV12_Filter;
> + p_filter->ops = &I420_NV12_ops;
> break;
>
> case VLC_CODEC_YV12:
> if( outfcc != VLC_CODEC_NV12 )
> return -1;
> - p_filter->pf_video_filter = YV12_NV12_Filter;
> + p_filter->ops = &YV12_NV12_ops;
> break;
> case VLC_CODEC_NV12:
> switch( outfcc )
> {
> case VLC_CODEC_I420:
> case VLC_CODEC_J420:
> - p_filter->pf_video_filter = NV12_I420_Filter;
> + p_filter->ops = &NV12_I420_ops;
> break;
> case VLC_CODEC_YV12:
> - p_filter->pf_video_filter = NV12_YV12_Filter;
> + p_filter->ops = &NV12_YV12_ops;
> break;
> default:
> return -1;
> @@ -195,14 +195,14 @@ static int Create( vlc_object_t *p_this )
> if( outfcc != VLC_CODEC_P010 )
> return -1;
> pixel_bytes = 2;
> - p_filter->pf_video_filter = I42010B_P010_Filter;
> + p_filter->ops = &I42010B_P010_ops;
> break;
>
> case VLC_CODEC_P010:
> if( outfcc != VLC_CODEC_I420_10L )
> return -1;
> pixel_bytes = 2;
> - p_filter->pf_video_filter = P010_I42010B_Filter;
> + p_filter->ops = &P010_I42010B_ops;
> break;
>
> default:
> diff --git a/modules/video_chroma/i420_rgb.c b/modules/video_chroma/i420_rgb.c
> index fbb8f90e42b..20bb2eadbe9 100644
> --- a/modules/video_chroma/i420_rgb.c
> +++ b/modules/video_chroma/i420_rgb.c
> @@ -131,7 +131,7 @@ static int Activate( vlc_object_t *p_this )
> {
> /* R5G5B6 pixel format */
> msg_Dbg(p_this, "RGB pixel format is R5G5B5");
> - p_filter->pf_video_filter = I420_R5G5B5_Filter;
> + p_filter->ops = &I420_R5G5B5_ops;
> }
> else if( ( p_filter->fmt_out.video.i_rmask == 0xf800
> && p_filter->fmt_out.video.i_gmask == 0x07e0
> @@ -139,7 +139,7 @@ static int Activate( vlc_object_t *p_this )
> {
> /* R5G6B5 pixel format */
> msg_Dbg(p_this, "RGB pixel format is R5G6B5");
> - p_filter->pf_video_filter = I420_R5G6B5_Filter;
> + p_filter->ops = &I420_R5G6B5_ops;
> }
> else
> return VLC_EGENERIC;
> @@ -152,7 +152,7 @@ static int Activate( vlc_object_t *p_this )
> {
> /* A8R8G8B8 pixel format */
> msg_Dbg(p_this, "RGB pixel format is A8R8G8B8");
> - p_filter->pf_video_filter = I420_A8R8G8B8_Filter;
> + p_filter->ops = &I420_A8R8G8B8_ops;
> }
> else if( p_filter->fmt_out.video.i_rmask == 0xff000000
> && p_filter->fmt_out.video.i_gmask == 0x00ff0000
> @@ -160,7 +160,7 @@ static int Activate( vlc_object_t *p_this )
> {
> /* R8G8B8A8 pixel format */
> msg_Dbg(p_this, "RGB pixel format is R8G8B8A8");
> - p_filter->pf_video_filter = I420_R8G8B8A8_Filter;
> + p_filter->ops = &I420_R8G8B8A8_ops;
> }
> else if( p_filter->fmt_out.video.i_rmask == 0x0000ff00
> && p_filter->fmt_out.video.i_gmask == 0x00ff0000
> @@ -168,7 +168,7 @@ static int Activate( vlc_object_t *p_this )
> {
> /* B8G8R8A8 pixel format */
> msg_Dbg(p_this, "RGB pixel format is B8G8R8A8");
> - p_filter->pf_video_filter = I420_B8G8R8A8_Filter;
> + p_filter->ops = &I420_B8G8R8A8_ops;
> }
> else if( p_filter->fmt_out.video.i_rmask == 0x000000ff
> && p_filter->fmt_out.video.i_gmask == 0x0000ff00
> @@ -176,21 +176,21 @@ static int Activate( vlc_object_t *p_this )
> {
> /* A8B8G8R8 pixel format */
> msg_Dbg(p_this, "RGB pixel format is A8B8G8R8");
> - p_filter->pf_video_filter = I420_A8B8G8R8_Filter;
> + p_filter->ops = &I420_A8B8G8R8_ops;
> }
> else
> return VLC_EGENERIC;
> break;
> #else
> case VLC_CODEC_RGB8:
> - p_filter->pf_video_filter = I420_RGB8_Filter;
> + p_filter->ops = &I420_RGB8_ops;
> break;
> case VLC_CODEC_RGB15:
> case VLC_CODEC_RGB16:
> - p_filter->pf_video_filter = I420_RGB16_Filter;
> + p_filter->ops = &I420_RGB16_ops;
> break;
> case VLC_CODEC_RGB32:
> - p_filter->pf_video_filter = I420_RGB32_Filter;
> + p_filter->ops = &I420_RGB32_ops;
> break;
> #endif
> default:
> diff --git a/modules/video_chroma/i420_yuy2.c b/modules/video_chroma/i420_yuy2.c
> index b18fea3c31f..fb7a787f957 100644
> --- a/modules/video_chroma/i420_yuy2.c
> +++ b/modules/video_chroma/i420_yuy2.c
> @@ -107,6 +107,34 @@ VIDEO_FILTER_WRAPPER( I420_IUYV )
> VIDEO_FILTER_WRAPPER( I420_Y211 )
> #endif
>
> +static const struct vlc_filter_operations *
> +GetFilterOperations( filter_t *p_filter )
> +{
> + switch( p_filter->fmt_out.video.i_chroma )
> + {
> + case VLC_CODEC_YUYV:
> + return &I420_YUY2_ops;
> +
> + case VLC_CODEC_YVYU:
> + return &I420_YVYU_ops;
> +
> + case VLC_CODEC_UYVY:
> + return &I420_UYVY_ops;
> +
> +#if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
> + case VLC_FOURCC('I','U','Y','V'):
> + return &I420_IUYV_ops;
> +#endif
> +
> +#if defined (MODULE_NAME_IS_i420_yuy2)
> + case VLC_CODEC_Y211:
> + return &I420_Y211_ops;
> +#endif
> + default:
> + return NULL;
> + }
> +}
> +
> /*****************************************************************************
> * Activate: allocate a chroma function
> *****************************************************************************
> @@ -134,33 +162,10 @@ static int Activate( vlc_object_t *p_this )
> if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_I420)
> return VLC_EGENERIC;
>
> - switch( p_filter->fmt_out.video.i_chroma )
> - {
> - case VLC_CODEC_YUYV:
> - p_filter->pf_video_filter = I420_YUY2_Filter;
> - break;
> -
> - case VLC_CODEC_YVYU:
> - p_filter->pf_video_filter = I420_YVYU_Filter;
> - break;
> -
> - case VLC_CODEC_UYVY:
> - p_filter->pf_video_filter = I420_UYVY_Filter;
> - break;
> -#if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
> - case VLC_FOURCC('I','U','Y','V'):
> - p_filter->pf_video_filter = I420_IUYV_Filter;
> - break;
> -#endif
> -
> -#if defined (MODULE_NAME_IS_i420_yuy2)
> - case VLC_CODEC_Y211:
> - p_filter->pf_video_filter = I420_Y211_Filter;
> - break;
> -#endif
> - default:
> - return VLC_EGENERIC;
> - }
> + /* Find the adequate filter function depending on the output format. */
> + p_filter->ops = GetFilterOperations( p_filter );
> + if( p_filter->ops == NULL )
> + return VLC_EGENERIC;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_chroma/i422_i420.c b/modules/video_chroma/i422_i420.c
> index 5ac6918f853..72315a8d943 100644
> --- a/modules/video_chroma/i422_i420.c
> +++ b/modules/video_chroma/i422_i420.c
> @@ -87,15 +87,15 @@ static int Activate( vlc_object_t *p_this )
> {
> case VLC_CODEC_I420:
> case VLC_CODEC_J420:
> - p_filter->pf_video_filter = I422_I420_Filter;
> + p_filter->ops = &I422_I420_ops;
> break;
>
> case VLC_CODEC_YV12:
> - p_filter->pf_video_filter = I422_YV12_Filter;
> + p_filter->ops = &I422_YV12_ops;
> break;
>
> case VLC_CODEC_YUV420A:
> - p_filter->pf_video_filter = I422_YUVA_Filter;
> + p_filter->ops = &I422_YUVA_ops;
> break;
>
> default:
> diff --git a/modules/video_chroma/i422_yuy2.c b/modules/video_chroma/i422_yuy2.c
> index 416dbfff02c..eb29dc965da 100644
> --- a/modules/video_chroma/i422_yuy2.c
> +++ b/modules/video_chroma/i422_yuy2.c
> @@ -89,6 +89,35 @@ VIDEO_FILTER_WRAPPER( I422_IUYV )
> VIDEO_FILTER_WRAPPER( I422_Y211 )
> #endif
>
> +
> +static const struct vlc_filter_operations*
> +GetFilterOperations(filter_t *filter)
> +{
> + switch( filter->fmt_out.video.i_chroma )
> + {
> + case VLC_CODEC_YUYV:
> + return &I422_YUY2_ops;
> +
> + case VLC_CODEC_YVYU:
> + return &I422_YVYU_ops;
> +
> + case VLC_CODEC_UYVY:
> + return &I422_UYVY_ops;
> +
> + case VLC_FOURCC('I','U','Y','V'):
> + return &I422_IUYV_ops;
> +
> +#if defined (MODULE_NAME_IS_i422_yuy2)
> + case VLC_CODEC_Y211:
> + return &I422_Y211_ops;
> +#endif
> +
> + default:
> + return NULL;
> + }
> +
> +}
> +
> /*****************************************************************************
> * Activate: allocate a chroma function
> *****************************************************************************
> @@ -111,42 +140,16 @@ static int Activate( vlc_object_t *p_this )
> return VLC_EGENERIC;
> }
>
> - switch( p_filter->fmt_in.video.i_chroma )
> - {
> - case VLC_CODEC_I422:
> - switch( p_filter->fmt_out.video.i_chroma )
> - {
> - case VLC_CODEC_YUYV:
> - p_filter->pf_video_filter = I422_YUY2_Filter;
> - break;
> -
> - case VLC_CODEC_YVYU:
> - p_filter->pf_video_filter = I422_YVYU_Filter;
> - break;
> -
> - case VLC_CODEC_UYVY:
> - p_filter->pf_video_filter = I422_UYVY_Filter;
> - break;
> + /* This is a i422 -> * converter. */
> + if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_I422 )
> + return VLC_EGENERIC;
>
> - case VLC_FOURCC('I','U','Y','V'):
> - p_filter->pf_video_filter = I422_IUYV_Filter;
> - break;
>
> -#if defined (MODULE_NAME_IS_i422_yuy2)
> - case VLC_CODEC_Y211:
> - p_filter->pf_video_filter = I422_Y211_Filter;
> - break;
> -#endif
> -
> - default:
> - return -1;
> - }
> - break;
> + p_filter->ops = GetFilterOperations( p_filter );
> + if( p_filter->ops == NULL)
> + return VLC_EGENERIC;
>
> - default:
> - return -1;
> - }
> - return 0;
> + return VLC_SUCCESS;
> }
>
> /* Following functions are local */
> diff --git a/modules/video_chroma/omxdl.c b/modules/video_chroma/omxdl.c
> index 292fe950eab..e643f0735d5 100644
> --- a/modules/video_chroma/omxdl.c
> +++ b/modules/video_chroma/omxdl.c
> @@ -265,7 +265,7 @@ static int Open (vlc_object_t *obj)
> case VLC_CODEC_RGB16:
> if (FixRV16 (&filter->fmt_out.video))
> return VLC_EGENERIC;
> - filter->pf_video_filter = I420_RV16_Filter;
> + filter->ops = &I420_RV16_ops;
> return VLC_SUCCESS;
> }
> break;
> @@ -276,7 +276,7 @@ static int Open (vlc_object_t *obj)
> case VLC_CODEC_RGB16:
> if (FixRV16 (&filter->fmt_out.video))
> return VLC_EGENERIC;
> - filter->pf_video_filter = YV12_RV16_Filter;
> + filter->ops = &YV12_RV16_ops;
> return VLC_SUCCESS;
> }
> break;
> @@ -285,10 +285,10 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter = I422_I420_Filter;
> + filter->ops = &I422_I420_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_YV12:
> - filter->pf_video_filter = I422_YV12_Filter;
> + filter->ops = &I422_YV12_ops;
> return VLC_SUCCESS;
> }
> break;
> @@ -299,7 +299,7 @@ static int Open (vlc_object_t *obj)
> case VLC_CODEC_RGB16:
> if (FixRV16 (&filter->fmt_out.video))
> return VLC_EGENERIC;
> - filter->pf_video_filter = I444_RV16_Filter;
> + filter->ops = &I444_RV16_ops;
> return VLC_SUCCESS;
> }
> return VLC_EGENERIC;
> @@ -310,12 +310,12 @@ static int Open (vlc_object_t *obj)
> case VLC_CODEC_RGB24:
> if (FixRV24 (&filter->fmt_out.video))
> return VLC_EGENERIC;
> - filter->pf_video_filter = YUYV_RV24_Filter;
> + filter->ops = &YUYV_RV24_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB16:
> if (FixRV16 (&filter->fmt_out.video))
> return VLC_EGENERIC;
> - filter->pf_video_filter = YUYV_RV16_Filter;
> + filter->ops = &YUYV_RV16_ops;
> return VLC_SUCCESS;
> }
> return VLC_EGENERIC;
> @@ -324,10 +324,10 @@ static int Open (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter = UYVY_I420_Filter;
> + filter->ops = &UYVY_I420_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_YV12:
> - filter->pf_video_filter = UYVY_YV12_Filter;
> + filter->ops = &UYVY_YV12_ops;
> return VLC_SUCCESS;
> }
> return VLC_EGENERIC;
> @@ -484,33 +484,33 @@ static int OpenScaler (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter = I420_I420_Scale_Filter;
> + filter->ops = &I420_I420_Scale_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_YV12:
> - filter->pf_video_filter = I420_YV12_Scale_Filter;
> + filter->ops = &I420_YV12_Scale_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB16:
> if (FixRV16 (&filter->fmt_out.video))
> return VLC_EGENERIC;
> - filter->pf_video_filter = I420_RGB_Scale_Filter;
> + filter->ops = &I420_RGB_Scale_ops;
> *conv = OMX_IP_BGR565;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB15:
> if (FixRV15 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = I420_RGB_Scale_Filter;
> + filter->ops = &I420_RGB_Scale_ops;
> *conv = OMX_IP_BGR555;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB12:
> if (FixRV12 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = I420_RGB_Scale_Filter;
> + filter->ops = &I420_RGB_Scale_ops;
> *conv = OMX_IP_BGR444;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB24:
> if (FixRV24 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = I420_RGB_Scale_Filter;
> + filter->ops = &I420_RGB_Scale_ops;
> *conv = OMX_IP_BGR888;
> return VLC_SUCCESS;
> }
> @@ -520,33 +520,33 @@ static int OpenScaler (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I420:
> - filter->pf_video_filter = YV12_I420_Scale_Filter;
> + filter->ops = &YV12_I420_Scale_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_YV12:
> - filter->pf_video_filter = YV12_YV12_Scale_Filter;
> + filter->ops = &YV12_YV12_Scale_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB16:
> if (FixRV16 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = YV12_RGB_Scale_Filter;
> + filter->ops = &YV12_RGB_Scale_ops;
> *conv = OMX_IP_BGR565;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB15:
> if (FixRV15 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = YV12_RGB_Scale_Filter;
> + filter->ops = &YV12_RGB_Scale_ops;
> *conv = OMX_IP_BGR555;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB12:
> if (FixRV12 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = YV12_RGB_Scale_Filter;
> + filter->ops = &YV12_RGB_Scale_ops;
> *conv = OMX_IP_BGR444;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB24:
> if (FixRV24 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = YV12_RGB_Scale_Filter;
> + filter->ops = &YV12_RGB_Scale_ops;
> *conv = OMX_IP_BGR888;
> return VLC_SUCCESS;
> }
> @@ -556,30 +556,30 @@ static int OpenScaler (vlc_object_t *obj)
> switch (filter->fmt_out.video.i_chroma)
> {
> case VLC_CODEC_I422:
> - filter->pf_video_filter = I422_I422_Scale_Filter;
> + filter->ops = &I422_I422_Scale_ops;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB16:
> if (FixRV16 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = I422_RGB_Scale_Filter;
> + filter->ops = &I422_RGB_Scale_ops;
> *conv = OMX_IP_BGR565;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB15:
> if (FixRV15 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = I422_RGB_Scale_Filter;
> + filter->ops = &I422_RGB_Scale_ops;
> *conv = OMX_IP_BGR555;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB12:
> if (FixRV12 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = I422_RGB_Scale_Filter;
> + filter->ops = &I422_RGB_Scale_ops;
> *conv = OMX_IP_BGR444;
> return VLC_SUCCESS;
> case VLC_CODEC_RGB24:
> if (FixRV24 (&filter->fmt_out.video))
> break;
> - filter->pf_video_filter = I422_RGB_Scale_Filter;
> + filter->ops = &I422_RGB_Scale_ops;
> *conv = OMX_IP_BGR888;
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_chroma/rv32.c b/modules/video_chroma/rv32.c
> index 9546872722b..835b658531d 100644
> --- a/modules/video_chroma/rv32.c
> +++ b/modules/video_chroma/rv32.c
> @@ -47,6 +47,10 @@ vlc_module_begin ()
> set_callback( OpenFilter )
> vlc_module_end ()
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Filter,
> +};
> +
>
> /*****************************************************************************
> * OpenFilter: probe the filter and return score
>
> *****************************************************************************/
> @@ -67,7 +71,7 @@ static int OpenFilter( vlc_object_t *p_this )
> || p_filter->fmt_in.video.orientation !=
> p_filter->fmt_out.video.orientation)
> return -1;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_chroma/swscale.c b/modules/video_chroma/swscale.c
> index 3c7bdf78ea3..8d5106ffd61 100644
> --- a/modules/video_chroma/swscale.c
> +++ b/modules/video_chroma/swscale.c
> @@ -139,6 +139,10 @@ static int GetSwsCpuMask(void);
> /* XXX is it always 3 even for BIG_ENDIAN (blend.c seems to think so) ? */
> #define OFFSET_A (3)
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> * OpenScaler: probe the filter and return score
> *****************************************************************************/
> @@ -192,7 +196,7 @@ static int OpenScaler( vlc_object_t *p_this )
> }
>
> /* */
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> msg_Dbg( p_filter, "%ix%i (%ix%i) chroma: %4.4s -> %ix%i (%ix%i)
> chroma: %4.4s with scaling using %s",
> p_filter->fmt_in.video.i_visible_width,
> p_filter->fmt_in.video.i_visible_height,
> diff --git a/modules/video_chroma/yuvp.c b/modules/video_chroma/yuvp.c
> index b6149ce1654..8fe086637bd 100644
> --- a/modules/video_chroma/yuvp.c
> +++ b/modules/video_chroma/yuvp.c
> @@ -78,7 +78,7 @@ static int Open( vlc_object_t *p_this )
> return VLC_EGENERIC;
> }
>
> - p_filter->pf_video_filter = Convert_Filter;
> + p_filter->ops = &Convert_ops;
>
> msg_Dbg( p_filter, "YUVP to %4.4s converter",
> (const char*)&p_filter->fmt_out.video.i_chroma );
> diff --git a/modules/video_chroma/yuy2_i420.c b/modules/video_chroma/yuy2_i420.c
> index cfcb2c3717b..fa0c3cfd570 100644
> --- a/modules/video_chroma/yuy2_i420.c
> +++ b/modules/video_chroma/yuy2_i420.c
> @@ -84,15 +84,15 @@ static int Activate( vlc_object_t *p_this )
> switch( p_filter->fmt_in.video.i_chroma )
> {
> case VLC_CODEC_YUYV:
> - p_filter->pf_video_filter = YUY2_I420_Filter;
> + p_filter->ops = &YUY2_I420_ops;
> break;
>
> case VLC_CODEC_YVYU:
> - p_filter->pf_video_filter = YVYU_I420_Filter;
> + p_filter->ops = &YVYU_I420_ops;
> break;
>
> case VLC_CODEC_UYVY:
> - p_filter->pf_video_filter = UYVY_I420_Filter;
> + p_filter->ops = &UYVY_I420_ops;
> break;
>
> default:
> diff --git a/modules/video_chroma/yuy2_i422.c b/modules/video_chroma/yuy2_i422.c
> index f8aa0b9b040..b35c62f84dc 100644
> --- a/modules/video_chroma/yuy2_i422.c
> +++ b/modules/video_chroma/yuy2_i422.c
> @@ -84,15 +84,15 @@ static int Activate( vlc_object_t *p_this )
> switch( p_filter->fmt_in.video.i_chroma )
> {
> case VLC_CODEC_YUYV:
> - p_filter->pf_video_filter = YUY2_I422_Filter;
> + p_filter->ops = &YUY2_I422_ops;
> break;
>
> case VLC_CODEC_YVYU:
> - p_filter->pf_video_filter = YVYU_I422_Filter;
> + p_filter->ops = &YVYU_I422_ops;
> break;
>
> case VLC_CODEC_UYVY:
> - p_filter->pf_video_filter = UYVY_I422_Filter;
> + p_filter->ops = &UYVY_I422_ops;
> break;
>
> default:
> diff --git a/modules/video_filter/adjust.c
> b/modules/video_filter/adjust.c
> index 063af77f22a..85cf2bbb165 100644
> --- a/modules/video_filter/adjust.c
> +++ b/modules/video_filter/adjust.c
> @@ -141,6 +141,16 @@ static int BoolCallback( vlc_object_t *obj, char
> const *varname,
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations planar_filter_ops =
> +{
> + .filter_video = FilterPlanar,
> +};
> +
> +static const struct vlc_filter_operations packed_filter_ops =
> +{
> + .filter_video = FilterPacked,
> +};
> +
> /*****************************************************************************
> * Create: allocates adjust video filter
> *****************************************************************************/
> @@ -166,7 +176,7 @@ static int Create( vlc_object_t *p_this )
> {
> CASE_PLANAR_YUV
> /* Planar YUV */
> - p_filter->pf_video_filter = FilterPlanar;
> + p_filter->ops = &planar_filter_ops;
> p_sys->pf_process_sat_hue_clip = planar_sat_hue_clip_C;
> p_sys->pf_process_sat_hue = planar_sat_hue_C;
> break;
> @@ -174,14 +184,14 @@ static int Create( vlc_object_t *p_this )
> CASE_PLANAR_YUV10
> CASE_PLANAR_YUV9
> /* Planar YUV 9-bit or 10-bit */
> - p_filter->pf_video_filter = FilterPlanar;
> + p_filter->ops = &planar_filter_ops;
> p_sys->pf_process_sat_hue_clip = planar_sat_hue_clip_C_16;
> p_sys->pf_process_sat_hue = planar_sat_hue_C_16;
> break;
>
> CASE_PACKED_YUV_422
> /* Packed YUV 4:2:2 */
> - p_filter->pf_video_filter = FilterPacked;
> + p_filter->ops = &packed_filter_ops;
> p_sys->pf_process_sat_hue_clip = packed_sat_hue_clip_C;
> p_sys->pf_process_sat_hue = packed_sat_hue_C;
> break;
> diff --git a/modules/video_filter/alphamask.c b/modules/video_filter/alphamask.c
> index 001f37185c7..9b894f9f760 100644
> --- a/modules/video_filter/alphamask.c
> +++ b/modules/video_filter/alphamask.c
> @@ -82,6 +82,11 @@ typedef struct
> vlc_mutex_t mask_lock;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> static int Create( vlc_object_t *p_this )
> {
> filter_t *p_filter = (filter_t *)p_this;
> @@ -122,7 +127,7 @@ static int Create( vlc_object_t *p_this )
> vlc_mutex_init( &p_sys->mask_lock );
> var_AddCallback( p_filter, CFG_PREFIX "mask", MaskCallback,
> p_filter );
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/anaglyph.c b/modules/video_filter/anaglyph.c
> index b17bf7a5256..0f1b16689f4 100644
> --- a/modules/video_filter/anaglyph.c
> +++ b/modules/video_filter/anaglyph.c
> @@ -86,6 +86,11 @@ typedef struct
> int left, right;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = &Filter,
> +};
> +
>
> static int Create(vlc_object_t *p_this)
> {
> @@ -156,7 +161,7 @@ static int Create(vlc_object_t *p_this)
> break;
> }
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> @@ -301,4 +306,3 @@ static void combine_side_by_side_yuv420(picture_t
> *p_inpic, picture_t *p_outpic,
> vout += p_outpic->p[V_PLANE].i_pitch - uv_visible_pitch;
> }
> }
> -
> diff --git a/modules/video_filter/antiflicker.c
> b/modules/video_filter/antiflicker.c
> index 568a84ae615..4f360ee0027 100644
> --- a/modules/video_filter/antiflicker.c
> +++ b/modules/video_filter/antiflicker.c
> @@ -94,6 +94,11 @@ typedef struct
> uint8_t *p_old_data;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> * Create: allocates Distort video thread output method
> *****************************************************************************
> @@ -121,7 +126,7 @@ static int Create( vlc_object_t *p_this )
> return VLC_ENOMEM;
> p_filter->p_sys = p_sys;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> /* Initialize the arguments */
> atomic_init( &p_sys->i_window_size,
> diff --git a/modules/video_filter/ball.c b/modules/video_filter/ball.c
> index 563ff8bedc0..15086833117 100644
> --- a/modules/video_filter/ball.c
> +++ b/modules/video_filter/ball.c
> @@ -215,6 +215,10 @@ struct filter_sys_t
> } colorList[4];
> };
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
>
> /*****************************************************************************
> * Create: allocates Distort video thread output method
> @@ -261,7 +265,7 @@ static int Create( vlc_object_t *p_this )
> if( p_sys->p_image == NULL )
> return VLC_EGENERIC;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
> p_filter->p_cfg );
> diff --git a/modules/video_filter/blend.cpp b/modules/video_filter/blend.cpp
> index b33aa084f38..faf49cf482f 100644
> --- a/modules/video_filter/blend.cpp
> +++ b/modules/video_filter/blend.cpp
> @@ -649,7 +649,7 @@ struct filter_sys_t {
> /**
> * It blends 2 picture together.
> */
> -static void Blend(filter_t *filter,
> +static void DoBlend(filter_t *filter,
> picture_t *dst, const picture_t *src,
> int x_offset, int y_offset, int alpha)
> {
> @@ -680,6 +680,14 @@ static void Blend(filter_t *filter,
> width, height, alpha);
> }
>
> +static const struct FilterOperationInitializer {
> + struct vlc_filter_operations ops {};
> + FilterOperationInitializer()
> + {
> + ops.blend_video = DoBlend;
> + };
> +} filter_ops;
> +
> static int Open(vlc_object_t *object)
> {
> filter_t *filter = (filter_t *)object;
> @@ -699,7 +707,7 @@ static int Open(vlc_object_t *object)
> return VLC_EGENERIC;
> }
>
> - filter->pf_video_blend = Blend;
> + filter->ops = &filter_ops.ops;
> filter->p_sys = sys;
> return VLC_SUCCESS;
> }
> @@ -710,4 +718,3 @@ static void Close(vlc_object_t *object)
> filter_sys_t *p_sys = reinterpret_cast<filter_sys_t *>(
> filter->p_sys );
> delete p_sys;
> }
> -
> diff --git a/modules/video_filter/blendbench.c
> b/modules/video_filter/blendbench.c
> index f2886385311..0a6c17ad22b 100644
> --- a/modules/video_filter/blendbench.c
> +++ b/modules/video_filter/blendbench.c
> @@ -144,6 +144,11 @@ static int blendbench_LoadImage( vlc_object_t
> *p_this, picture_t **pp_pic,
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> * Create: allocates video thread output method
> *****************************************************************************/
> @@ -162,7 +167,7 @@ static int Create( vlc_object_t *p_this )
> p_sys = p_filter->p_sys;
> p_sys->b_done = false;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> /* needed to get options passed in transcode using the
> * adjust{name=value} syntax */
> @@ -252,9 +257,8 @@ static picture_t *Filter( filter_t *p_filter,
> picture_t *p_pic )
> vlc_tick_t time = vlc_tick_now();
> for( int i_iter = 0; i_iter < p_sys->i_loops; ++i_iter )
> {
> - p_blend->pf_video_blend( p_blend,
> - p_sys->p_base_image,
> p_sys->p_blend_image,
> - 0, 0, p_sys->i_alpha );
> + filter_Blend( p_blend, p_sys->p_base_image,
> p_sys->p_blend_image,
> + 0, 0, p_sys->i_alpha );
> }
> time = vlc_tick_now() - time;
>
> diff --git a/modules/video_filter/bluescreen.c
> b/modules/video_filter/bluescreen.c
> index 3fe83a1a5df..d624ddf2df9 100644
> --- a/modules/video_filter/bluescreen.c
> +++ b/modules/video_filter/bluescreen.c
> @@ -106,6 +106,11 @@ typedef struct
> uint8_t *p_at;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> static int Create( vlc_object_t *p_this )
> {
> filter_t *p_filter = (filter_t *)p_this;
> @@ -143,7 +148,7 @@ static int Create( vlc_object_t *p_this )
> p_sys->p_at = NULL;
> #undef GET_VAR
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/canvas.c b/modules/video_filter/canvas.c
> index 80010eecc17..580948f719c 100644
> --- a/modules/video_filter/canvas.c
> +++ b/modules/video_filter/canvas.c
> @@ -144,6 +144,11 @@ static const struct filter_video_callbacks canvas_cbs =
> video_chain_new, NULL,
> };
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> *
> *****************************************************************************/
> @@ -373,7 +378,7 @@ static int Activate( vlc_object_t *p_this )
> i_canvas_width, i_canvas_height );
> }
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/ci_filters.m
> b/modules/video_filter/ci_filters.m
> index 154fc44012c..4bc46be3460 100644
> --- a/modules/video_filter/ci_filters.m
> +++ b/modules/video_filter/ci_filters.m
> @@ -376,7 +376,8 @@ Filter(filter_t *filter, picture_t *src)
>
> if (ctx->src_converter)
> {
> - src = ctx->dst_converter->pf_video_filter(ctx->src_converter, src);
> + // TODO
> + src = ctx->dst_converter->ops->filter_video(ctx->src_converter, src);
> if (!src)
> return NULL;
> }
> @@ -416,7 +417,7 @@ Filter(filter_t *filter, picture_t *src)
>
> if (ctx->dst_converter)
> {
> - dst = ctx->dst_converter->pf_video_filter(ctx->dst_converter,
> dst);
> + dst =
> ctx->dst_converter->ops->filter_video(ctx->dst_converter, dst);
> if (!dst)
> return NULL;
> }
> @@ -568,6 +569,12 @@ CVPX_to_CVPX_converter_Create(filter_t *filter,
> bool to_rgba)
> return converter;
> }
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> + .video_mouse = Mouse,
> +};
> +
> static int
> Open(vlc_object_t *obj, char const *psz_filter)
> {
> @@ -677,8 +684,7 @@ Open(vlc_object_t *obj, char const *psz_filter)
> p_sys->psz_filter = psz_filter;
> p_sys->ctx = ctx;
>
> - filter->pf_video_filter = Filter;
> - filter->pf_video_mouse = Mouse;
> + filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
>
> diff --git a/modules/video_filter/colorthres.c
> b/modules/video_filter/colorthres.c
> index 3011b94f99d..5f7e483b117 100644
> --- a/modules/video_filter/colorthres.c
> +++ b/modules/video_filter/colorthres.c
> @@ -102,6 +102,16 @@ typedef struct
> atomic_int i_color;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations planar_filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> +static const struct vlc_filter_operations packed_filter_ops =
> +{
> + .filter_video = FilterPacked,
> +};
> +
> /*****************************************************************************
> * Create: allocates adjust video thread output method
> *****************************************************************************
> @@ -115,11 +125,11 @@ static int Create( vlc_object_t *p_this )
> switch( p_filter->fmt_in.video.i_chroma )
> {
> CASE_PLANAR_YUV
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &planar_filter_ops;
> break;
>
> CASE_PACKED_YUV_422
> - p_filter->pf_video_filter = FilterPacked;
> + p_filter->ops = &packed_filter_ops;
> break;
>
> default:
> diff --git a/modules/video_filter/croppadd.c b/modules/video_filter/croppadd.c
> index 1d2f27fbe45..4471e859a7b 100644
> --- a/modules/video_filter/croppadd.c
> +++ b/modules/video_filter/croppadd.c
> @@ -122,6 +122,11 @@ typedef struct
> int i_paddright;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> * OpenFilter: probe the filter and return score
> *****************************************************************************/
> @@ -185,7 +190,7 @@ static int OpenFilter( vlc_object_t *p_this )
> - p_sys->i_cropleft - p_sys->i_cropright
> + p_sys->i_paddleft + p_sys->i_paddright;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> msg_Dbg( p_filter, "Crop: Top: %d, Bottom: %d, Left: %d, Right:
> %d",
> p_sys->i_croptop, p_sys->i_cropbottom, p_sys->i_cropleft,
> diff --git a/modules/video_filter/deinterlace/deinterlace.c
> b/modules/video_filter/deinterlace/deinterlace.c
> index 1676a07f8ca..714066c21c3 100644
> --- a/modules/video_filter/deinterlace/deinterlace.c
> +++ b/modules/video_filter/deinterlace/deinterlace.c
> @@ -53,7 +53,7 @@
> /**
> * Top-level filtering method.
> *
> - * Open() sets this up as the processing method (pf_video_filter)
> + * Open() sets this up as the processing method (filter_video)
> * in the filter structure.
> *
> * Note that there is no guarantee that the returned picture directly
> @@ -480,6 +480,12 @@ int Mouse( filter_t *p_filter,
> }
>
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_video = Deinterlace,
> + .flush = Flush,
> + .video_mouse = Mouse,
> +};
> +
> /*****************************************************************************
> * Open
> *****************************************************************************/
> @@ -643,9 +649,7 @@ notsupp:
> }
> p_filter->fmt_out.video = fmt;
> p_filter->fmt_out.i_codec = fmt.i_chroma;
> - p_filter->pf_video_filter = Deinterlace;
> - p_filter->pf_flush = Flush;
> - p_filter->pf_video_mouse = Mouse;
> + p_filter->ops = &filter_ops;
>
> msg_Dbg( p_filter, "deinterlacing" );
>
> diff --git a/modules/video_filter/edgedetection.c
> b/modules/video_filter/edgedetection.c
> index 935189122f1..d425473704f 100644
> --- a/modules/video_filter/edgedetection.c
> +++ b/modules/video_filter/edgedetection.c
> @@ -82,6 +82,11 @@ static const struct filter_video_callbacks
> filter_video_edge_cbs =
> new_frame, NULL,
> };
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
>
> /*****************************************************************************
> * Opens the filter.
> * Allocates and initializes data needed by the filter. The image
> needs to
> @@ -123,7 +128,7 @@ static int Open( vlc_object_t *p_this )
> return VLC_EGENERIC;
> }
> /* Set callback function */
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
> p_filter->p_sys = sys;
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/erase.c b/modules/video_filter/erase.c
> index 7e6683b14e4..0ec8df77d50 100644
> --- a/modules/video_filter/erase.c
> +++ b/modules/video_filter/erase.c
> @@ -122,6 +122,11 @@ static void LoadMask( filter_t *p_filter, const
> char *psz_filename )
> image_HandlerDelete( p_image );
> }
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> * Create
> *****************************************************************************/
> @@ -153,7 +158,7 @@ static int Create( vlc_object_t *p_this )
> return VLC_ENOMEM;
> p_sys = p_filter->p_sys;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
> p_filter->p_cfg );
> diff --git a/modules/video_filter/extract.c b/modules/video_filter/extract.c
> index 0e849642a95..ca5708792c3 100644
> --- a/modules/video_filter/extract.c
> +++ b/modules/video_filter/extract.c
> @@ -89,6 +89,11 @@ typedef struct
> uint32_t i_color;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> * Create
> *****************************************************************************/
> @@ -142,7 +147,7 @@ static int Create( vlc_object_t *p_this )
> var_AddCallback( p_filter, FILTER_PREFIX "component",
> ExtractCallback, p_sys );
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/fps.c b/modules/video_filter/fps.c
> index 4e6a59dfd66..a4ea6fd671a 100644
> --- a/modules/video_filter/fps.c
> +++ b/modules/video_filter/fps.c
> @@ -131,6 +131,11 @@ static picture_t *Filter( filter_t *p_filter,
> picture_t *p_picture)
> return last_pic;
> }
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> static int Open( vlc_object_t *p_this)
> {
> filter_t *p_filter = (filter_t*)p_this;
> @@ -180,7 +185,7 @@ static int Open( vlc_object_t *p_this)
>
> p_sys->p_previous_pic = NULL;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> /* We don't change neither the format nor the picture */
> if ( p_filter->vctx_in )
> diff --git a/modules/video_filter/freeze.c b/modules/video_filter/freeze.c
> index be5fde8e9d9..719a762619f 100644
> --- a/modules/video_filter/freeze.c
> +++ b/modules/video_filter/freeze.c
> @@ -88,6 +88,12 @@ vlc_module_end()
> * Local prototypes
> *****************************************************************************/
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> + .video_mouse = freeze_mouse,
> +};
> +
> /**
> * Open the filter
> */
> @@ -121,8 +127,7 @@ static int Open( vlc_object_t *p_this )
>
> /* init data */
>
> - p_filter->pf_video_filter = Filter;
> - p_filter->pf_video_mouse = freeze_mouse;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/gaussianblur.c
> b/modules/video_filter/gaussianblur.c
> index 3a97dbcd34e..ea0aa41167e 100644
> --- a/modules/video_filter/gaussianblur.c
> +++ b/modules/video_filter/gaussianblur.c
> @@ -123,6 +123,11 @@ static void gaussianblur_InitDistribution(
> filter_sys_t *p_sys )
> p_sys->pt_distribution = pt_distribution;
> }
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> static int Create( vlc_object_t *p_this )
> {
> filter_t *p_filter = (filter_t *)p_this;
> @@ -155,7 +160,7 @@ static int Create( vlc_object_t *p_this )
> config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
> p_filter->p_cfg );
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> p_sys->f_sigma =
> var_CreateGetFloat( p_filter, FILTER_PREFIX "sigma" );
> diff --git a/modules/video_filter/gradfun.c b/modules/video_filter/gradfun.c
> index 093d207523e..01f0042486a 100644
> --- a/modules/video_filter/gradfun.c
> +++ b/modules/video_filter/gradfun.c
> @@ -110,6 +110,11 @@ typedef struct
> struct vf_priv_s cfg;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> static int Open(vlc_object_t *object)
> {
> filter_t *filter = (filter_t *)object;
> @@ -156,8 +161,8 @@ static int Open(vlc_object_t *object)
> #endif
> cfg->filter_line = filter_line_c;
>
> - filter->p_sys = sys;
> - filter->pf_video_filter = Filter;
> + filter->p_sys = sys;
> + filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> @@ -236,4 +241,3 @@ static int Callback(vlc_object_t *object, char const *cmd,
>
> return VLC_SUCCESS;
> }
> -
> diff --git a/modules/video_filter/gradient.c b/modules/video_filter/gradient.c
> index 22675305f5e..b7c599d2266 100644
> --- a/modules/video_filter/gradient.c
> +++ b/modules/video_filter/gradient.c
> @@ -124,6 +124,11 @@ typedef struct
> int *p_pre_hough;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> /*****************************************************************************
> * Create: allocates Distort video thread output method
> *****************************************************************************
> @@ -151,7 +156,7 @@ static int Create( vlc_object_t *p_this )
> return VLC_ENOMEM;
> p_filter->p_sys = p_sys;
>
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &filter_ops;
>
> p_sys->p_pre_hough = NULL;
>
> diff --git a/modules/video_filter/grain.c b/modules/video_filter/grain.c
> index 174de0a822a..b63f836c6eb 100644
> --- a/modules/video_filter/grain.c
> +++ b/modules/video_filter/grain.c
> @@ -378,6 +378,11 @@ static int Callback(vlc_object_t *object, char const *cmd,
> return VLC_SUCCESS;
> }
>
> +static const struct vlc_filter_operations filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> static int Open(vlc_object_t *object)
> {
> filter_t *filter = (filter_t *)object;
> @@ -419,8 +424,8 @@ static int Open(vlc_object_t *object)
> sys->cfg.variance = var_CreateGetFloatCommand(filter, CFG_PREFIX
> "variance");
> var_AddCallback(filter, CFG_PREFIX "variance", Callback, NULL);
>
> - filter->p_sys = sys;
> - filter->pf_video_filter = Filter;
> + filter->p_sys = sys;
> + filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> @@ -432,4 +437,3 @@ static void Close(vlc_object_t *object)
> var_DelCallback(filter, CFG_PREFIX "variance", Callback, NULL);
> free(sys);
> }
> -
> diff --git a/modules/video_filter/hqdn3d.c
> b/modules/video_filter/hqdn3d.c
> index beb57974d8e..0dcbca718e9 100644
> --- a/modules/video_filter/hqdn3d.c
> +++ b/modules/video_filter/hqdn3d.c
> @@ -154,8 +154,13 @@ static int Open(vlc_object_t *this)
> sys->luma_temp = var_CreateGetFloatCommand(filter, FILTER_PREFIX
> "luma-temp");
> sys->chroma_temp = var_CreateGetFloatCommand(filter, FILTER_PREFIX
> "chroma-temp");
>
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> +
> filter->p_sys = sys;
> - filter->pf_video_filter = Filter;
> + filter->ops = &filter_ops;
>
> var_AddCallback( filter, FILTER_PREFIX "luma-spat",
> DenoiseCallback, sys );
> var_AddCallback( filter, FILTER_PREFIX "chroma-spat",
> DenoiseCallback, sys );
> diff --git a/modules/video_filter/invert.c
> b/modules/video_filter/invert.c
> index 67f96977c78..632635ce588 100644
> --- a/modules/video_filter/invert.c
> +++ b/modules/video_filter/invert.c
> @@ -76,7 +76,11 @@ static int Create( vlc_object_t *p_this )
> || p_chroma->pixel_size * 8 != p_chroma->pixel_bits )
> return VLC_EGENERIC;
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/video_filter/magnify.c
> b/modules/video_filter/magnify.c
> index e5582bbc0ff..b5d2fe042c0 100644
> --- a/modules/video_filter/magnify.c
> +++ b/modules/video_filter/magnify.c
> @@ -129,8 +129,12 @@ static int Create( vlc_object_t *p_this )
> p_sys->i_hide_timeout = VLC_TICK_FROM_MS( var_InheritInteger(
> p_filter, "mouse-hide-timeout" ) );
>
> /* */
> - p_filter->pf_video_filter = Filter;
> - p_filter->pf_video_mouse = Mouse;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + .video_mouse = Mouse,
> + };
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> @@ -419,4 +423,3 @@ static int Mouse( filter_t *p_filter, vlc_mouse_t
> *p_new, const vlc_mouse_t *p_o
> p_new->i_y = p_sys->i_y + p_new->i_y * ZOOM_FACTOR / p_sys->i_zoom;
> return VLC_SUCCESS;
> }
> -
> diff --git a/modules/video_filter/mirror.c
> b/modules/video_filter/mirror.c
> index ab8f9dcdd04..57a1dea39c4 100644
> --- a/modules/video_filter/mirror.c
> +++ b/modules/video_filter/mirror.c
> @@ -155,7 +155,11 @@ static int Create( vlc_object_t *p_this )
> var_AddCallback( p_filter, CFG_PREFIX "split", FilterCallback,
> p_sys );
> var_AddCallback( p_filter, CFG_PREFIX "direction", FilterCallback,
> p_sys );
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/motionblur.c
> b/modules/video_filter/motionblur.c
> index 4bd504598c8..b536c0a4520 100644
> --- a/modules/video_filter/motionblur.c
> +++ b/modules/video_filter/motionblur.c
> @@ -113,7 +113,11 @@ static int Create( vlc_object_t *p_this )
> }
> p_sys->b_first = true;
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
> p_filter->p_cfg );
> diff --git a/modules/video_filter/motiondetect.c
> b/modules/video_filter/motiondetect.c
> index 9906132a616..4787f5580ca 100644
> --- a/modules/video_filter/motiondetect.c
> +++ b/modules/video_filter/motiondetect.c
> @@ -106,7 +106,11 @@ static int Create( vlc_object_t *p_this )
> (char*)&(p_fmt->i_chroma) );
> return VLC_EGENERIC;
> }
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> /* Allocate structure */
> p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) );
> diff --git a/modules/video_filter/oldmovie.c b/modules/video_filter/oldmovie.c
> index f7c6a710fc0..c2d4fc7cb54 100644
> --- a/modules/video_filter/oldmovie.c
> +++ b/modules/video_filter/oldmovie.c
> @@ -216,7 +216,11 @@ static int Open( vlc_object_t *p_this ) {
> return VLC_ENOMEM;
>
> /* init data */
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
> p_sys->i_start_time = p_sys->i_cur_time = p_sys->i_last_time =
> vlc_tick_now();
>
> return VLC_SUCCESS;
> diff --git a/modules/video_filter/opencv_example.cpp
> b/modules/video_filter/opencv_example.cpp
> index 1334cd4c366..ed4e8cba266 100644
> --- a/modules/video_filter/opencv_example.cpp
> +++ b/modules/video_filter/opencv_example.cpp
> @@ -108,7 +108,14 @@ static int OpenFilter( vlc_object_t *p_this )
> p_sys->event_info.p_region = NULL;
> p_sys->i_id = 0;
>
> - p_filter->pf_video_filter = Filter;
> + static const struct FilterOperationInitializer {
> + struct vlc_filter_operations ops {};
> + FilterOperationInitializer()
> + {
> + ops.filter_video = Filter;
> + };
> + } filter_ops;
> + p_filter->ops = &filter_ops.ops;
>
> //create the VIDEO_FILTER_EVENT_VARIABLE
> vlc_value_t val;
> @@ -157,7 +164,7 @@ static picture_t *Filter( filter_t *p_filter,
> picture_t *p_pic )
> CvPoint pt1, pt2;
> int scale = 1;
> filter_sys_t *p_sys = static_cast<filter_sys_t *>(p_filter->p_sys);
> -
> +
> if ((!p_pic) )
> {
> msg_Err( p_filter, "no image array" );
> @@ -217,4 +224,3 @@ static picture_t *Filter( filter_t *p_filter,
> picture_t *p_pic )
>
> return p_pic;
> }
> -
> diff --git a/modules/video_filter/opencv_wrapper.c
> b/modules/video_filter/opencv_wrapper.c
> index 2ce695913f9..d103cc7edc8 100644
> --- a/modules/video_filter/opencv_wrapper.c
> +++ b/modules/video_filter/opencv_wrapper.c
> @@ -249,8 +249,12 @@ static int Create( vlc_object_t *p_this )
> msg_Dbg( p_filter, "opencv_wrapper successfully started" );
> #endif
>
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
> p_filter->p_sys = p_sys;
> - p_filter->pf_video_filter = Filter;
>
> return VLC_SUCCESS;
> }
> @@ -414,7 +418,7 @@ static picture_t* Filter( filter_t* p_filter,
> picture_t* p_pic )
> VlcPictureToIplImage( p_filter, p_pic );
> // Pass the image (as a pointer to the first IplImage*) to the
> // internal OpenCV filter for processing.
> - p_sys->p_opencv->pf_video_filter( p_sys->p_opencv,
> (picture_t*)&(p_sys->p_cv_image[0]) );
> + p_sys->p_opencv->ops->filter_video( p_sys->p_opencv,
> (picture_t*)&(p_sys->p_cv_image[0]) );
>
> if(p_sys->i_wrapper_output == PROCESSED) {
> // Processed video
> @@ -459,4 +463,3 @@ static picture_t* Filter( filter_t* p_filter,
> picture_t* p_pic )
> return NULL;
> }
> }
> -
> diff --git a/modules/video_filter/posterize.c
> b/modules/video_filter/posterize.c
> index 91762a8591c..99d69cac17f 100644
> --- a/modules/video_filter/posterize.c
> +++ b/modules/video_filter/posterize.c
> @@ -134,7 +134,11 @@ static int Create( vlc_object_t *p_this )
>
> var_AddCallback( p_filter, CFG_PREFIX "level", FilterCallback, p_sys );
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/postproc.c b/modules/video_filter/postproc.c
> index bf0192de2b0..24fa4bc9ba7 100644
> --- a/modules/video_filter/postproc.c
> +++ b/modules/video_filter/postproc.c
> @@ -252,7 +252,11 @@ static int OpenPostproc( vlc_object_t *p_this )
> var_AddCallback( p_filter, FILTER_PREFIX "q", PPQCallback, NULL );
> var_AddCallback( p_filter, FILTER_PREFIX "name", PPNameCallback, NULL );
>
> - p_filter->pf_video_filter = PostprocPict;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = PostprocPict,
> + };
> + p_filter->ops = &filter_ops;
>
> msg_Warn( p_filter, "Quantification table was not set by video
> decoder. "
> "Postprocessing won't look good." );
> diff --git a/modules/video_filter/psychedelic.c
> b/modules/video_filter/psychedelic.c
> index 94c57641227..5295ffce441 100644
> --- a/modules/video_filter/psychedelic.c
> +++ b/modules/video_filter/psychedelic.c
> @@ -96,7 +96,11 @@ static int Create( vlc_object_t *p_this )
> return VLC_ENOMEM;
> p_filter->p_sys = p_sys;
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> p_sys->x = 10;
> p_sys->y = 10;
> diff --git a/modules/video_filter/puzzle.c
> b/modules/video_filter/puzzle.c
> index bef39368bc4..80b5775c742 100644
> --- a/modules/video_filter/puzzle.c
> +++ b/modules/video_filter/puzzle.c
> @@ -202,8 +202,12 @@ static int Open( vlc_object_t *p_this )
> var_AddCallback( p_filter, CFG_PREFIX "rotation",
> puzzle_Callback, p_sys );
> var_AddCallback( p_filter, CFG_PREFIX "mode", puzzle_Callback,
> p_sys );
>
> - p_filter->pf_video_filter = Filter;
> - p_filter->pf_video_mouse = puzzle_mouse;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + .video_mouse = puzzle_mouse,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/ripple.c b/modules/video_filter/ripple.c
> index a190c350039..c6748995bbd 100644
> --- a/modules/video_filter/ripple.c
> +++ b/modules/video_filter/ripple.c
> @@ -90,7 +90,12 @@ static int Create( vlc_object_t *p_this )
> if( p_sys == NULL )
> return VLC_ENOMEM;
> p_filter->p_sys = p_sys;
> - p_filter->pf_video_filter = Filter;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> p_sys->f_angle = 0.0;
> p_sys->last_date = 0;
> diff --git a/modules/video_filter/rotate.c
> b/modules/video_filter/rotate.c
> index 005ba96ec9b..48b9d92cb3a 100644
> --- a/modules/video_filter/rotate.c
> +++ b/modules/video_filter/rotate.c
> @@ -118,6 +118,16 @@ static void fetch_trigo( filter_sys_t *sys, int
> *i_sin, int *i_cos )
> *i_cos = sincos.cos;
> }
>
> +static const struct vlc_filter_operations planar_filter_ops =
> +{
> + .filter_video = Filter,
> +};
> +
> +static const struct vlc_filter_operations packed_filter_ops =
> +{
> + .filter_video = FilterPacked,
> +};
> +
> /*****************************************************************************
> * Create: allocates Distort video filter
> *****************************************************************************/
> @@ -135,11 +145,11 @@ static int Create( vlc_object_t *p_this )
> switch( p_filter->fmt_in.video.i_chroma )
> {
> CASE_PLANAR_YUV
> - p_filter->pf_video_filter = Filter;
> + p_filter->ops = &planar_filter_ops;
> break;
>
> CASE_PACKED_YUV_422
> - p_filter->pf_video_filter = FilterPacked;
> + p_filter->ops = &packed_filter_ops;
> break;
>
> default:
> diff --git a/modules/video_filter/scale.c b/modules/video_filter/scale.c
> index ef5189e2e13..648be69e4ab 100644
> --- a/modules/video_filter/scale.c
> +++ b/modules/video_filter/scale.c
> @@ -74,7 +74,12 @@ static int OpenFilter( vlc_object_t *p_this )
>
> #warning Converter cannot (really) change output format.
> video_format_ScaleCropAr( &p_filter->fmt_out.video,
> &p_filter->fmt_in.video );
> - p_filter->pf_video_filter = Filter;
> +
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> msg_Dbg( p_filter, "%ix%i -> %ix%i", p_filter->fmt_in.video.i_width,
> p_filter->fmt_in.video.i_height, p_filter->fmt_out.video.i_width,
> diff --git a/modules/video_filter/scene.c b/modules/video_filter/scene.c
> index 48ca076dfd8..f655cb4e7a6 100644
> --- a/modules/video_filter/scene.c
> +++ b/modules/video_filter/scene.c
> @@ -148,7 +148,7 @@ typedef struct
> } filter_sys_t;
>
> /*****************************************************************************
> - * Create: initialize and set pf_video_filter()
> + * Create: initialize and set ops
> *****************************************************************************/
> static int Create( vlc_object_t *p_this )
> {
> @@ -197,7 +197,11 @@ static int Create( vlc_object_t *p_this )
> if( p_sys->psz_path == NULL )
> p_sys->psz_path = config_GetUserDir( VLC_PICTURES_DIR );
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/sepia.c b/modules/video_filter/sepia.c
> index 9ca567c614e..aa653ffdc83 100644
> --- a/modules/video_filter/sepia.c
> +++ b/modules/video_filter/sepia.c
> @@ -143,7 +143,11 @@ static int Create( vlc_object_t *p_this )
> var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "intensity" ) );
> var_AddCallback( p_filter, CFG_PREFIX "intensity", FilterCallback, NULL );
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/video_filter/sharpen.c b/modules/video_filter/sharpen.c
> index 76972de44af..a53ca5c5001 100644
> --- a/modules/video_filter/sharpen.c
> +++ b/modules/video_filter/sharpen.c
> @@ -118,7 +118,11 @@ static int Create( vlc_object_t *p_this )
> return VLC_ENOMEM;
> p_filter->p_sys = p_sys;
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
> p_filter->p_cfg );
> diff --git a/modules/video_filter/transform.c b/modules/video_filter/transform.c
> index a9e8dcb1479..ab48f748b41 100644
> --- a/modules/video_filter/transform.c
> +++ b/modules/video_filter/transform.c
> @@ -432,9 +432,13 @@ static int Open(vlc_object_t *object)
> goto error;
> }
>
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + .video_mouse = Mouse,
> + };
> + filter->ops = &filter_ops;
> filter->p_sys = sys;
> - filter->pf_video_filter = Filter;
> - filter->pf_video_mouse = Mouse;
> return VLC_SUCCESS;
> error:
> free(sys);
> diff --git a/modules/video_filter/vhs.c b/modules/video_filter/vhs.c
> index 6d5c13db8e8..e27c9b376aa 100644
> --- a/modules/video_filter/vhs.c
> +++ b/modules/video_filter/vhs.c
> @@ -143,7 +143,11 @@ static int Open( vlc_object_t *p_this )
> return VLC_ENOMEM;
>
> /* init data */
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
> p_sys->i_start_time = p_sys->i_cur_time = p_sys->i_last_time =
> vlc_tick_now();
>
> return VLC_SUCCESS;
> diff --git a/modules/video_filter/wave.c b/modules/video_filter/wave.c
> index eae6c961b74..e732251cacc 100644
> --- a/modules/video_filter/wave.c
> +++ b/modules/video_filter/wave.c
> @@ -90,7 +90,11 @@ static int Create( vlc_object_t *p_this )
> if( !p_sys )
> return VLC_ENOMEM;
>
> - p_filter->pf_video_filter = Filter;
> + static const struct vlc_filter_operations filter_ops =
> + {
> + .filter_video = Filter,
> + };
> + p_filter->ops = &filter_ops;
>
> p_sys->f_angle = 0.0;
> p_sys->last_date = 0;
> diff --git a/modules/visualization/glspectrum.c
> b/modules/visualization/glspectrum.c
> index 5ca0e75dedb..3e8b878197b 100644
> --- a/modules/visualization/glspectrum.c
> +++ b/modules/visualization/glspectrum.c
> @@ -111,6 +111,10 @@ static void *Thread(void *);
> const GLfloat lightZeroColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
> const GLfloat lightZeroPosition[] = {0.0f, 3.0f, 10.0f, 0.0f};
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_audio = DoWork,
> +};
> +
> /**
> * Open the module.
> * @param p_this: the filter object
> @@ -160,7 +164,7 @@ static int Open(vlc_object_t * p_this)
>
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> + p_filter->ops = &filter_ops;
>
> return VLC_SUCCESS;
> }
> diff --git a/modules/visualization/goom.c b/modules/visualization/goom.c
> index fa8f2cc197a..eeeeae90cf7 100644
> --- a/modules/visualization/goom.c
> +++ b/modules/visualization/goom.c
> @@ -104,6 +104,11 @@ static void Flush( filter_t * );
>
> static void *Thread( void * );
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_audio = DoWork,
> + .flush = Flush,
> +};
> +
> /*****************************************************************************
> * Open: open a scope effect plugin
> *****************************************************************************/
> @@ -154,8 +159,7 @@ static int Open( vlc_object_t *p_this )
>
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> - p_filter->pf_flush = Flush;
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
> }
>
> diff --git a/modules/visualization/projectm.cpp
> b/modules/visualization/projectm.cpp
> index f4b636fb232..b0e2d0edbb0 100644
> --- a/modules/visualization/projectm.cpp
> +++ b/modules/visualization/projectm.cpp
> @@ -157,6 +157,14 @@ struct filter_sys_t
> static block_t *DoWork( filter_t *, block_t * );
> static void *Thread( void * );
>
> +static const struct FilterOperationInitializer {
> + struct vlc_filter_operations ops {};
> + FilterOperationInitializer()
> + {
> + ops.filter_audio = DoWork;
> + };
> +} filter_ops;
> +
> /**
> * Open the module
> * @param p_this: the filter object
> @@ -200,7 +208,7 @@ static int Open( vlc_object_t * p_this )
>
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> + p_filter->ops = &filter_ops.ops;
> return VLC_SUCCESS;
>
> error:
> diff --git a/modules/visualization/visual/visual.c
> b/modules/visualization/visual/visual.c
> index db693dfbcd9..21c34ad9452 100644
> --- a/modules/visualization/visual/visual.c
> +++ b/modules/visualization/visual/visual.c
> @@ -188,6 +188,11 @@ typedef struct
> vlc_thread_t thread;
> } filter_sys_t;
>
> +static const struct vlc_filter_operations filter_ops = {
> + .filter_audio = DoWork,
> + .flush = Flush,
> +};
> +
> /*****************************************************************************
> * Open: open the visualizer
> *****************************************************************************/
> @@ -323,8 +328,7 @@ static int Open( vlc_object_t *p_this )
>
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> - p_filter->pf_flush = Flush;
> + p_filter->ops = &filter_ops;
> return VLC_SUCCESS;
>
> error:
> diff --git a/modules/visualization/vsxu.cpp b/modules/visualization/vsxu.cpp
> index dbbb061ecf2..9abea745da8 100644
> --- a/modules/visualization/vsxu.cpp
> +++ b/modules/visualization/vsxu.cpp
> @@ -97,6 +97,14 @@ struct filter_sys_t
> static block_t *DoWork( filter_t *, block_t * );
> static void *Thread( void * );
>
> +static const struct FilterOperationInitializer {
> + struct vlc_filter_operations ops {};
> + FilterOperationInitializer()
> + {
> + ops.filter_audio = DoWork;
> + };
> +} filter_ops;
> +
> /**
> * Open the module
> * @param p_this: the filter object
> @@ -141,7 +149,7 @@ static int Open( vlc_object_t * p_this )
>
> p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
> p_filter->fmt_out.audio = p_filter->fmt_in.audio;
> - p_filter->pf_audio_filter = DoWork;
> + p_filter->ops = &filter_ops.ops;
>
> return VLC_SUCCESS;
>
> diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c
> index 11a77e95b1f..d2d2b3225a6 100644
> --- a/src/audio_output/filters.c
> +++ b/src/audio_output/filters.c
> @@ -84,7 +84,9 @@ filter_t *aout_filter_Create(vlc_object_t *obj, const
> filter_owner_t *restrict o
> filter = NULL;
> }
> else
> - assert (filter->pf_audio_filter != NULL);
> + {
> + assert (filter->ops != NULL && filter->ops->filter_audio !=
> NULL);
> + }
> return filter;
> }
>
> @@ -286,7 +288,7 @@ static block_t *aout_FiltersPipelinePlay(filter_t
> *const *filters,
>
> /* Please note that p_block->i_nb_samples & i_buffer
> * shall be set by the filter plug-in. */
> - block = filter->pf_audio_filter (filter, block);
> + block = filter->ops->filter_audio (filter, block);
> }
> return block;
> }
> diff --git a/src/audio_output/meter.c b/src/audio_output/meter.c
> index 3cfc1158abe..8fd570d0b10 100644
> --- a/src/audio_output/meter.c
> +++ b/src/audio_output/meter.c
> @@ -109,7 +109,7 @@ vlc_audio_meter_AddPlugin(struct vlc_audio_meter
> *meter, const char *chain,
> if (plugin->filter == NULL)
> goto error;
>
> - assert(plugin->filter->pf_audio_drain == NULL); /* Not supported */
> + assert(plugin->filter->ops->drain_audio == NULL); /* Not supported */
> }
>
> vlc_mutex_lock(&meter->lock);
> @@ -198,7 +198,7 @@ vlc_audio_meter_Process(struct vlc_audio_meter
> *meter, block_t *block, vlc_tick_
> {
> plugin->last_date = date + block->i_length;
>
> - block_t *same_block = filter->pf_audio_filter(filter, block);
> + block_t *same_block = filter->ops->filter_audio(filter, block);
> assert(same_block == block); (void) same_block;
> }
> }
> @@ -215,8 +215,8 @@ vlc_audio_meter_Flush(struct vlc_audio_meter *meter)
> vlc_list_foreach(plugin, &meter->plugins, node)
> {
> filter_t *filter = plugin->filter;
> - if (filter != NULL && filter->pf_flush != NULL)
> - filter->pf_flush(filter);
> + if (filter != NULL && filter->ops->flush != NULL)
> + filter->ops->flush(filter);
> }
>
> vlc_mutex_unlock(&meter->lock);
> diff --git a/src/misc/filter.c b/src/misc/filter.c
> index e8c1cae82eb..ed23e1d7fe6 100644
> --- a/src/misc/filter.c
> +++ b/src/misc/filter.c
> @@ -164,7 +164,7 @@ int filter_Blend( vlc_blender_t *p_blend,
> if( !p_blend->p_module )
> return VLC_EGENERIC;
>
> - p_blend->pf_video_blend( p_blend, p_dst, p_src, i_dst_x, i_dst_y,
> i_alpha );
> + p_blend->ops->blend_video( p_blend, p_dst, p_src, i_dst_x,
> i_dst_y, i_alpha );
> return VLC_SUCCESS;
> }
>
> diff --git a/src/misc/filter_chain.c b/src/misc/filter_chain.c
> index 645a27507fd..bce6980d9bb 100644
> --- a/src/misc/filter_chain.c
> +++ b/src/misc/filter_chain.c
> @@ -429,7 +429,7 @@ static picture_t *FilterChainVideoFilter(
> chained_filter_t *f, picture_t *p_pic
> for( ; f != NULL; f = f->next )
> {
> filter_t *p_filter = &f->filter;
> - p_pic = p_filter->pf_video_filter( p_filter, p_pic );
> + p_pic = p_filter->ops->filter_video( p_filter, p_pic );
> if( !p_pic )
> break;
> if( f->pending )
> @@ -483,7 +483,7 @@ void filter_chain_SubSource( filter_chain_t
> *p_chain, spu_t *spu,
> for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
> {
> filter_t *p_filter = &f->filter;
> - subpicture_t *p_subpic = p_filter->pf_sub_source( p_filter,
> display_date );
> + subpicture_t *p_subpic = p_filter->ops->source_sub( p_filter,
> display_date );
> if( p_subpic )
> spu_PutSubpicture( spu, p_subpic );
> }
> @@ -495,7 +495,7 @@ subpicture_t *filter_chain_SubFilter(
> filter_chain_t *p_chain, subpicture_t *p_s
> {
> filter_t *p_filter = &f->filter;
>
> - p_subpic = p_filter->pf_sub_filter( p_filter, p_subpic );
> + p_subpic = p_filter->ops->filter_sub( p_filter, p_subpic );
>
> if( !p_subpic )
> break;
> @@ -512,13 +512,13 @@ int filter_chain_MouseFilter( filter_chain_t
> *p_chain, vlc_mouse_t *p_dst, const
> filter_t *p_filter = &f->filter;
> vlc_mouse_t *p_mouse = f->mouse;
>
> - if( p_filter->pf_video_mouse && p_mouse )
> + if( p_filter->ops->video_mouse && p_mouse )
> {
> vlc_mouse_t old = *p_mouse;
> vlc_mouse_t filtered = current;
>
> *p_mouse = current;
> - if( p_filter->pf_video_mouse( p_filter, &filtered, &old ) )
> + if( p_filter->ops->video_mouse( p_filter, &filtered, &old)
> )
> return VLC_EGENERIC;
> current = filtered;
> }
> diff --git a/src/misc/image.c b/src/misc/image.c
> index faa05d9b018..e8f508c66b3 100644
> --- a/src/misc/image.c
> +++ b/src/misc/image.c
> @@ -270,7 +270,7 @@ static picture_t *ImageRead( image_handler_t
> *p_image, block_t *p_block,
> video_format_Copy( &p_image->p_converter->fmt_out.video,
> p_fmt_out);
> }
>
> - p_pic = p_image->p_converter->pf_video_filter(
> p_image->p_converter, p_pic );
> + p_pic = p_image->p_converter->ops->filter_video(
> p_image->p_converter, p_pic );
> }
> else
> {
> @@ -434,7 +434,7 @@ static block_t *ImageWrite( image_handler_t
> *p_image, picture_t *p_pic,
> picture_Hold( p_pic );
>
> p_tmp_pic =
> - p_image->p_converter->pf_video_filter(
> p_image->p_converter, p_pic );
> + p_image->p_converter->ops->filter_video(
> p_image->p_converter, p_pic );
>
> if( likely(p_tmp_pic != NULL) )
> {
> @@ -569,7 +569,7 @@ static picture_t *ImageConvert( image_handler_t
> *p_image, picture_t *p_pic,
>
> picture_Hold( p_pic );
>
> - return p_image->p_converter->pf_video_filter(
> p_image->p_converter, p_pic );
> + return p_image->p_converter->ops->filter_video(
> p_image->p_converter, p_pic );
> }
>
> /**
> diff --git a/src/video_output/vout_subpictures.c
> b/src/video_output/vout_subpictures.c
> index 8766e7b5820..fefcf21b8eb 100644
> --- a/src/video_output/vout_subpictures.c
> +++ b/src/video_output/vout_subpictures.c
> @@ -343,7 +343,7 @@ static int SpuRenderText(spu_t *spu,
> text->fmt_out.video.i_height =
> text->fmt_out.video.i_visible_height = i_original_height;
>
> - int i_ret = text->pf_render(text, region, region, chroma_list);
> + int i_ret = text->ops->render(text, region, region, chroma_list);
>
> vlc_mutex_unlock(&sys->textlock);
> return i_ret;
> @@ -996,7 +996,7 @@ static void SpuRenderRegion(spu_t *spu,
> scale_yuvp->fmt_out.video = region->fmt;
> scale_yuvp->fmt_out.video.i_chroma = chroma_list[0];
>
> - picture = scale_yuvp->pf_video_filter(scale_yuvp, picture);
> + picture = scale_yuvp->ops->filter_video(scale_yuvp, picture);
> if (!picture) {
> /* Well we will try conversion+scaling */
> msg_Warn(spu, "%4.4s to %4.4s conversion failed",
> @@ -1027,7 +1027,7 @@ static void SpuRenderRegion(spu_t *spu,
> scale->fmt_out.video.i_visible_height =
> spu_scale_h(region->fmt.i_visible_height, scale_size);
>
> - picture = scale->pf_video_filter(scale, picture);
> + picture = scale->ops->filter_video(scale, picture);
> if (!picture)
> msg_Err(spu, "scaling failed");
> }
> --
> 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