[vlc-devel] [PATCH] video_filter: use a video filter wrapper to generate boilerplate code

Steve Lhomme robux4 at ycbcr.xyz
Fri Oct 9 14:54:31 CEST 2020


---
 modules/video_filter/adjust.c       | 26 +++++--------------------
 modules/video_filter/anaglyph.c     | 29 +++++-----------------------
 modules/video_filter/antiflicker.c  | 24 +++++------------------
 modules/video_filter/ball.c         | 26 ++++---------------------
 modules/video_filter/colorthres.c   | 24 ++++-------------------
 modules/video_filter/croppadd.c     | 26 ++++---------------------
 modules/video_filter/erase.c        | 25 ++++--------------------
 modules/video_filter/extract.c      | 30 +++++------------------------
 modules/video_filter/gaussianblur.c | 24 ++++-------------------
 modules/video_filter/gradfun.c      | 22 ++++-----------------
 modules/video_filter/gradient.c     | 25 ++++--------------------
 modules/video_filter/grain.c        | 21 ++++----------------
 modules/video_filter/invert.c       | 26 +++++--------------------
 modules/video_filter/mirror.c       | 24 ++++-------------------
 modules/video_filter/motionblur.c   | 24 ++++-------------------
 modules/video_filter/posterize.c    | 25 ++++--------------------
 modules/video_filter/postproc.c     | 22 ++++-----------------
 modules/video_filter/psychedelic.c  | 25 ++++--------------------
 modules/video_filter/ripple.c       | 23 ++++------------------
 modules/video_filter/rotate.c       | 24 ++++-------------------
 modules/video_filter/scale.c        | 27 ++++----------------------
 modules/video_filter/sepia.c        | 25 ++++--------------------
 modules/video_filter/sharpen.c      | 22 ++++-----------------
 modules/video_filter/wave.c         | 24 +++++------------------
 24 files changed, 102 insertions(+), 491 deletions(-)

diff --git a/modules/video_filter/adjust.c b/modules/video_filter/adjust.c
index 85cf2bbb165..9ce531b1fa3 100644
--- a/modules/video_filter/adjust.c
+++ b/modules/video_filter/adjust.c
@@ -47,7 +47,7 @@
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *FilterPlanar( filter_t *, picture_t * );
+static void FilterPlanar( filter_t *, picture_t *, picture_t * );
 static picture_t *FilterPacked( filter_t *, picture_t * );
 
 /*****************************************************************************
@@ -141,10 +141,7 @@ 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,
-};
+VIDEO_FILTER_WRAPPER( FilterPlanar )
 
 static const struct vlc_filter_operations packed_filter_ops =
 {
@@ -176,7 +173,7 @@ static int Create( vlc_object_t *p_this )
     {
         CASE_PLANAR_YUV
             /* Planar YUV */
-            p_filter->ops = &planar_filter_ops;
+            p_filter->ops = &FilterPlanar_ops;
             p_sys->pf_process_sat_hue_clip = planar_sat_hue_clip_C;
             p_sys->pf_process_sat_hue = planar_sat_hue_C;
             break;
@@ -184,7 +181,7 @@ static int Create( vlc_object_t *p_this )
         CASE_PLANAR_YUV10
         CASE_PLANAR_YUV9
             /* Planar YUV 9-bit or 10-bit */
-            p_filter->ops = &planar_filter_ops;
+            p_filter->ops = &FilterPlanar_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;
@@ -253,25 +250,14 @@ static void Destroy( vlc_object_t *p_this )
 /*****************************************************************************
  * Run the filter on a Planar YUV picture
  *****************************************************************************/
-static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
+static void FilterPlanar( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
     /* The full range will only be used for 10-bit */
     int pi_luma[1024];
     int pi_gamma[1024];
 
-    picture_t *p_outpic;
-
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     bool b_16bit;
     float f_range;
     switch( p_filter->fmt_in.video.i_chroma )
@@ -443,8 +429,6 @@ static picture_t *FilterPlanar( filter_t *p_filter, picture_t *p_pic )
         p_sys->pf_process_sat_hue( p_pic, p_outpic, i_sin, i_cos, i_sat,
                                         i_x, i_y );
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/anaglyph.c b/modules/video_filter/anaglyph.c
index fcb9993ac8f..58a6de25e1c 100644
--- a/modules/video_filter/anaglyph.c
+++ b/modules/video_filter/anaglyph.c
@@ -31,7 +31,7 @@
 #include "filter_picture.h"
 
 static int Create(vlc_object_t *);
-static picture_t *Filter(filter_t *, picture_t *);
+static void Filter(filter_t *, picture_t *, picture_t *);
 static void combine_side_by_side_yuv420(picture_t *, picture_t *, int, int);
 
 #define SCHEME_TEXT N_("Color scheme")
@@ -85,11 +85,7 @@ typedef struct
     int left, right;
 } filter_sys_t;
 
-static const struct vlc_filter_operations filter_ops =
-{
-    .filter_video = &Filter,
-};
-
+VIDEO_FILTER_WRAPPER(Filter)
 
 static int Create(vlc_object_t *p_this)
 {
@@ -160,24 +156,14 @@ static int Create(vlc_object_t *p_this)
             break;
     }
 
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
     return VLC_SUCCESS;
 }
 
-static picture_t *Filter(filter_t *p_filter, picture_t *p_pic)
+static void Filter(filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic)
 {
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    if (!p_pic)
-        return NULL;
-
-    picture_t *p_outpic = filter_NewPicture(p_filter);
-    if (!p_outpic)
-    {
-        picture_Release(p_pic);
-        return NULL;
-    }
-
     switch (p_pic->format.i_chroma)
     {
         case VLC_CODEC_I420:
@@ -188,13 +174,8 @@ static picture_t *Filter(filter_t *p_filter, picture_t *p_pic)
             break;
 
         default:
-            msg_Warn(p_filter, "Unsupported input chroma (%4.4s)",
-                     (char*)&(p_pic->format.i_chroma));
-            picture_Release(p_pic);
-            return NULL;
+            vlc_assert_unreachable();
     }
-
-    return CopyInfoAndRelease(p_outpic, p_pic);
 }
 
 
diff --git a/modules/video_filter/antiflicker.c b/modules/video_filter/antiflicker.c
index 4f360ee0027..f469e1d22a2 100644
--- a/modules/video_filter/antiflicker.c
+++ b/modules/video_filter/antiflicker.c
@@ -40,13 +40,14 @@
  * Local prototypes
  *****************************************************************************/
 static int GetLuminanceAvg( picture_t * p_pic );
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static int AntiFlickerCallback( vlc_object_t *p_this, char const *psz_var,
                            vlc_value_t oldval, vlc_value_t newval,
                            void *p_data );
 
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 #define WINDOW_TEXT N_("Window size")
 #define WINDOW_LONGTEXT N_("Number of frames (0 to 100)")
@@ -94,11 +95,6 @@ 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
  *****************************************************************************
@@ -126,7 +122,7 @@ static int Create( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_filter->p_sys = p_sys;
 
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     /* Initialize the arguments */
     atomic_init( &p_sys->i_window_size,
@@ -207,16 +203,8 @@ static int GetLuminanceAvg( picture_t *p_pic )
  * The function uses moving average of past frames to adjust the luminance
  * of current frame also applies temporaral smoothening if enabled.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    if( !p_pic ) return NULL;
-
-    picture_t *p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
 
     /****************** Get variables *************************/
 
@@ -295,7 +283,7 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
 
     if (scene_changed || i_softening == 0)
     {
-       return CopyInfoAndRelease( p_outpic, p_pic );
+       return;
     }
 
     /******* Temporal softening phase. Adapted from code by Steven Don ******/
@@ -325,8 +313,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
                 p_yplane_out_old[i_line*i_video_width+i_col];
         }
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/ball.c b/modules/video_filter/ball.c
index 15086833117..3e5df31b243 100644
--- a/modules/video_filter/ball.c
+++ b/modules/video_filter/ball.c
@@ -75,7 +75,8 @@ typedef struct filter_sys_t filter_sys_t;
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 static void drawBall( filter_sys_t *p_sys, picture_t *p_outpic );
 static void drawPixelRGB24( filter_sys_t *p_sys, picture_t *p_outpic,
@@ -215,11 +216,6 @@ struct filter_sys_t
     } colorList[4];
 };
 
-static const struct vlc_filter_operations filter_ops =
-{
-    .filter_video = Filter,
-};
-
 /*****************************************************************************
 * Create: allocates Distort video thread output method
 *****************************************************************************
@@ -265,7 +261,7 @@ static int Create( vlc_object_t *p_this )
     if( p_sys->p_image == NULL )
         return VLC_EGENERIC;
 
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
                        p_filter->p_cfg );
@@ -353,28 +349,14 @@ static void Destroy( vlc_object_t *p_this )
 * until it is displayed and switch the two rendering buffers, preparing next
 * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
-
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     filter_sys_t *p_sys = p_filter->p_sys;
     vlc_mutex_lock( &p_sys->lock );
     FilterBall( p_filter, p_pic, p_outpic );
     vlc_mutex_unlock( &p_sys->lock );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
-
 /*****************************************************************************
 * Drawing functions
 *****************************************************************************/
diff --git a/modules/video_filter/colorthres.c b/modules/video_filter/colorthres.c
index 5f7e483b117..37f60196ff5 100644
--- a/modules/video_filter/colorthres.c
+++ b/modules/video_filter/colorthres.c
@@ -45,8 +45,9 @@
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static picture_t *FilterPacked( filter_t *, picture_t * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 /*****************************************************************************
  * Module descriptor
@@ -102,11 +103,6 @@ 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,
@@ -125,7 +121,7 @@ static int Create( vlc_object_t *p_this )
     switch( p_filter->fmt_in.video.i_chroma )
     {
         CASE_PLANAR_YUV
-            p_filter->ops = &planar_filter_ops;
+            p_filter->ops = &Filter_ops;
             break;
 
         CASE_PACKED_YUV_422
@@ -214,23 +210,13 @@ static bool IsSimilar( int u, int v,
  * waits until it is displayed and switch the two rendering buffers, preparing
  * next frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     filter_sys_t *p_sys = p_filter->p_sys;
     int i_simthres = atomic_load( &p_sys->i_simthres );
     int i_satthres = atomic_load( &p_sys->i_satthres );
     int i_color = atomic_load( &p_sys->i_color );
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     /* Copy the Y plane */
     plane_CopyPixels( &p_outpic->p[Y_PLANE], &p_pic->p[Y_PLANE] );
 
@@ -266,8 +252,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             p_src_v++;
         }
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 static picture_t *FilterPacked( filter_t *p_filter, picture_t *p_pic )
diff --git a/modules/video_filter/croppadd.c b/modules/video_filter/croppadd.c
index 07e14f6c562..35c126cc0e8 100644
--- a/modules/video_filter/croppadd.c
+++ b/modules/video_filter/croppadd.c
@@ -33,14 +33,14 @@
 #include <vlc_plugin.h>
 #include <vlc_filter.h>
 #include <vlc_picture.h>
-#include "filter_picture.h"
 
 /****************************************************************************
  * Local prototypes
  ****************************************************************************/
 static int  OpenFilter ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER(Filter)
 
 #define CROPTOP_TEXT N_( "Pixels to crop from top" )
 #define CROPTOP_LONGTEXT N_( \
@@ -121,11 +121,6 @@ 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
  *****************************************************************************/
@@ -189,7 +184,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->ops = &filter_ops;
+    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,
@@ -209,25 +204,14 @@ static int OpenFilter( vlc_object_t *p_this )
 /****************************************************************************
  * Filter: the whole thing
  ****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
     filter_sys_t *p_sys = p_filter->p_sys;
-    picture_t *p_outpic;
     int i_width, i_height, i_xcrop, i_ycrop,
         i_outwidth, i_outheight, i_xpadd, i_ypadd;
 
     const int p_padd_color[] = { 0x00, 0x80, 0x80, 0xff };
 
-    if( !p_pic ) return NULL;
-
-    /* Request output picture */
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     for( int i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
     /* p_pic and p_outpic have the same chroma/number of planes but that's
      * about it. */
@@ -302,6 +286,4 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
         memset( p_out, i_padd_color,
                  ( i_outheight - i_ypadd - i_height ) * p_outplane->i_pitch );
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
diff --git a/modules/video_filter/erase.c b/modules/video_filter/erase.c
index 0ec8df77d50..14567b46a09 100644
--- a/modules/video_filter/erase.c
+++ b/modules/video_filter/erase.c
@@ -35,7 +35,6 @@
 #include <vlc_filter.h>
 #include <vlc_picture.h>
 #include <vlc_url.h>
-#include "filter_picture.h"
 
 /*****************************************************************************
  * Local prototypes
@@ -43,10 +42,11 @@
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static void FilterErase( filter_t *, picture_t *, picture_t * );
 static int EraseCallback( vlc_object_t *, char const *,
                           vlc_value_t, vlc_value_t, void * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 /*****************************************************************************
  * Module descriptor
@@ -122,11 +122,6 @@ 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
  *****************************************************************************/
@@ -158,7 +153,7 @@ static int Create( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_sys = p_filter->p_sys;
 
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
                        p_filter->p_cfg );
@@ -208,20 +203,10 @@ static void Destroy( vlc_object_t *p_this )
 /*****************************************************************************
  * Filter
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     /* If the mask is empty: just copy the image */
     vlc_mutex_lock( &p_sys->lock );
     if( p_sys->p_mask )
@@ -229,8 +214,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
     else
         picture_CopyPixels( p_outpic, p_pic );
     vlc_mutex_unlock( &p_sys->lock );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/extract.c b/modules/video_filter/extract.c
index ca5708792c3..41a619bee93 100644
--- a/modules/video_filter/extract.c
+++ b/modules/video_filter/extract.c
@@ -42,9 +42,10 @@
 static int  Create      ( vlc_object_t * );
 static void Destroy     ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static int ExtractCallback( vlc_object_t *, char const *,
                             vlc_value_t, vlc_value_t, void * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 static void make_projection_matrix( filter_t *, int color, int *matrix );
 static void get_custom_from_yuv( picture_t *, picture_t *, int const, int const, int const, int const * );
@@ -89,11 +90,6 @@ typedef struct
     uint32_t i_color;
 } filter_sys_t;
 
-static const struct vlc_filter_operations filter_ops =
-{
-    .filter_video = Filter,
-};
-
 /*****************************************************************************
  * Create
  *****************************************************************************/
@@ -147,7 +143,7 @@ static int Create( vlc_object_t *p_this )
     var_AddCallback( p_filter, FILTER_PREFIX "component",
                      ExtractCallback, p_sys );
 
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     return VLC_SUCCESS;
 }
@@ -169,20 +165,10 @@ static void Destroy( vlc_object_t *p_this )
 /*****************************************************************************
  * Render
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     vlc_mutex_lock( &p_sys->lock );
     switch( p_pic->format.i_chroma )
     {
@@ -201,15 +187,9 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             break;
 
     default:
-        vlc_mutex_unlock( &p_sys->lock );
-        msg_Warn( p_filter, "Unsupported input chroma (%4.4s)",
-                  (char*)&(p_pic->format.i_chroma) );
-        picture_Release( p_pic );
-        return NULL;
+        vlc_assert_unreachable();
     }
     vlc_mutex_unlock( &p_sys->lock );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 #define U8 128
diff --git a/modules/video_filter/gaussianblur.c b/modules/video_filter/gaussianblur.c
index ea0aa41167e..ff6870609b4 100644
--- a/modules/video_filter/gaussianblur.c
+++ b/modules/video_filter/gaussianblur.c
@@ -32,7 +32,6 @@
 #include <vlc_plugin.h>
 #include <vlc_filter.h>
 #include <vlc_picture.h>
-#include "filter_picture.h"
 
 #include <math.h>                                          /* exp(), sqrt() */
 
@@ -72,7 +71,8 @@ vlc_module_end ()
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 static const char *const ppsz_filter_options[] = {
     "sigma", NULL
@@ -123,11 +123,6 @@ 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;
@@ -160,7 +155,7 @@ static int Create( vlc_object_t *p_this )
     config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
                        p_filter->p_cfg );
 
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     p_sys->f_sigma =
         var_CreateGetFloat( p_filter, FILTER_PREFIX "sigma" );
@@ -191,23 +186,14 @@ static void Destroy( vlc_object_t *p_this )
     free( p_sys );
 }
 
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     filter_sys_t *p_sys = p_filter->p_sys;
     const int i_dim = p_sys->i_dim;
     type_t *pt_buffer;
     type_t *pt_scale;
     const type_t *pt_distribution = p_sys->pt_distribution;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
     if( !p_sys->pt_buffer )
     {
         p_sys->pt_buffer = realloc_or_free( p_sys->pt_buffer,
@@ -297,6 +283,4 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             }
         }
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
diff --git a/modules/video_filter/gradfun.c b/modules/video_filter/gradfun.c
index 01f0042486a..880769a209b 100644
--- a/modules/video_filter/gradfun.c
+++ b/modules/video_filter/gradfun.c
@@ -98,8 +98,9 @@ vlc_module_end()
 #include <stdalign.h>
 #include "gradfun.h"
 
-static picture_t *Filter(filter_t *, picture_t *);
+static void Filter(filter_t *, picture_t *, picture_t *);
 static int Callback(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *);
+VIDEO_FILTER_WRAPPER( Filter )
 
 typedef struct
 {
@@ -110,11 +111,6 @@ 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;
@@ -162,7 +158,7 @@ static int Open(vlc_object_t *object)
         cfg->filter_line = filter_line_c;
 
     filter->p_sys = sys;
-    filter->ops   = &filter_ops;
+    filter->ops   = &Filter_ops;
     return VLC_SUCCESS;
 }
 
@@ -177,16 +173,10 @@ static void Close(vlc_object_t *object)
     free(sys);
 }
 
-static picture_t *Filter(filter_t *filter, picture_t *src)
+static void Filter(filter_t *filter, picture_t *src, picture_t *dst)
 {
     filter_sys_t *sys = filter->p_sys;
 
-    picture_t *dst = filter_NewPicture(filter);
-    if (!dst) {
-        picture_Release(src);
-        return NULL;
-    }
-
     vlc_mutex_lock(&sys->lock);
     float strength = VLC_CLIP(sys->strength, STRENGTH_MIN, STRENGTH_MAX);
     int   radius   = VLC_CLIP((sys->radius + 1) & ~1, RADIUS_MIN, RADIUS_MAX);
@@ -219,10 +209,6 @@ static picture_t *Filter(filter_t *filter, picture_t *src)
             plane_CopyPixels(dstp, srcp);
         }
     }
-
-    picture_CopyProperties(dst, src);
-    picture_Release(src);
-    return dst;
 }
 
 static int Callback(vlc_object_t *object, char const *cmd,
diff --git a/modules/video_filter/gradient.c b/modules/video_filter/gradient.c
index b7c599d2266..7b433a6a50b 100644
--- a/modules/video_filter/gradient.c
+++ b/modules/video_filter/gradient.c
@@ -46,10 +46,11 @@ enum { GRADIENT, EDGE, HOUGH };
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static int GradientCallback( vlc_object_t *, char const *,
                              vlc_value_t, vlc_value_t,
                              void * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 static void FilterGradient( filter_t *, picture_t *, picture_t * );
 static void FilterEdge    ( filter_t *, picture_t *, picture_t * );
@@ -124,11 +125,6 @@ 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
  *****************************************************************************
@@ -156,7 +152,7 @@ static int Create( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_filter->p_sys = p_sys;
 
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     p_sys->p_pre_hough = NULL;
 
@@ -244,19 +240,8 @@ static void Destroy( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
-
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     filter_sys_t *p_sys = p_filter->p_sys;
 
     vlc_mutex_lock( &p_sys->lock );
@@ -278,8 +263,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             break;
     }
     vlc_mutex_unlock( &p_sys->lock );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/grain.c b/modules/video_filter/grain.c
index b63f836c6eb..3aaa89abdeb 100644
--- a/modules/video_filter/grain.c
+++ b/modules/video_filter/grain.c
@@ -42,6 +42,8 @@
  *****************************************************************************/
 static int  Open (vlc_object_t *);
 static void Close(vlc_object_t *);
+static void Filter(filter_t *filter, picture_t *src, picture_t *dst);
+VIDEO_FILTER_WRAPPER( Filter )
 
 #define BANK_SIZE (64)
 
@@ -249,16 +251,10 @@ static void PlaneFilter(filter_t *filter,
         sys->emms();
 }
 
-static picture_t *Filter(filter_t *filter, picture_t *src)
+static void Filter(filter_t *filter, picture_t *src, picture_t *dst)
 {
     filter_sys_t *sys = filter->p_sys;
 
-    picture_t *dst = filter_NewPicture(filter);
-    if (!dst) {
-        picture_Release(src);
-        return NULL;
-    }
-
     vlc_mutex_lock(&sys->cfg.lock);
     const double variance = VLC_CLIP(sys->cfg.variance, VARIANCE_MIN, VARIANCE_MAX);
     vlc_mutex_unlock(&sys->cfg.lock);
@@ -283,10 +279,6 @@ static picture_t *Filter(filter_t *filter, picture_t *src)
             plane_CopyPixels(dstp, srcp);
         }
     }
-
-    picture_CopyProperties(dst, src);
-    picture_Release(src);
-    return dst;
 }
 
 /**
@@ -378,11 +370,6 @@ 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;
@@ -425,7 +412,7 @@ static int Open(vlc_object_t *object)
     var_AddCallback(filter, CFG_PREFIX "variance", Callback, NULL);
 
     filter->p_sys = sys;
-    filter->ops   = &filter_ops;
+    filter->ops   = &Filter_ops;
     return VLC_SUCCESS;
 }
 
diff --git a/modules/video_filter/invert.c b/modules/video_filter/invert.c
index e147b38cb60..b2f712de43a 100644
--- a/modules/video_filter/invert.c
+++ b/modules/video_filter/invert.c
@@ -32,14 +32,14 @@
 #include <vlc_plugin.h>
 #include <vlc_filter.h>
 #include <vlc_picture.h>
-#include "filter_picture.h"
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
 static int  Create      ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER(Filter)
 
 /*****************************************************************************
  * Module descriptor
@@ -75,11 +75,7 @@ static int Create( vlc_object_t *p_this )
      || p_chroma->pixel_size * 8 != p_chroma->pixel_bits )
         return VLC_EGENERIC;
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
     return VLC_SUCCESS;
 }
 
@@ -90,21 +86,11 @@ static int Create( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
+    VLC_UNUSED(p_filter);
     int i_planes;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        msg_Warn( p_filter, "can't get output picture" );
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     if( p_pic->format.i_chroma == VLC_CODEC_YUVA )
     {
         /* We don't want to invert the alpha plane */
@@ -161,6 +147,4 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
                      - p_outpic->p[i_index].i_visible_pitch;
         }
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
diff --git a/modules/video_filter/mirror.c b/modules/video_filter/mirror.c
index 57a1dea39c4..b92bde98ea9 100644
--- a/modules/video_filter/mirror.c
+++ b/modules/video_filter/mirror.c
@@ -43,7 +43,7 @@
 static int  Create      ( vlc_object_t * );
 static void Destroy     ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static void VerticalMirror( picture_t *, picture_t *, int plane, bool );
 static void HorizontalMirror( picture_t *, picture_t *, int, bool );
 static void PlanarVerticalMirror( picture_t *, picture_t *, int plane, bool );
@@ -52,6 +52,7 @@ static void RV24VerticalMirror( picture_t *, picture_t *, int plane, bool );
 static void RV32VerticalMirror( picture_t *, picture_t *, int plane, bool );
 
 static void YUV422Mirror2Pixels( uint8_t *, uint8_t *, bool );
+VIDEO_FILTER_WRAPPER( Filter )
 
 static const char *const ppsz_filter_options[] = {
     "split", "direction", NULL
@@ -155,11 +156,7 @@ 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 );
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     return VLC_SUCCESS;
 }
@@ -186,25 +183,14 @@ static void Destroy( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     bool b_vertical_split, b_left_to_right;
 
-    if( !p_pic ) return NULL;
-
     filter_sys_t *p_sys = p_filter->p_sys;
     b_vertical_split = !atomic_load( &p_sys->i_split );
     b_left_to_right = !atomic_load( &p_sys->i_direction );
 
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        msg_Warn( p_filter, "can't get output picture" );
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     for( int i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
     {
         if ( b_vertical_split )
@@ -212,8 +198,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
         else
             HorizontalMirror( p_pic, p_outpic, i_index, b_left_to_right );
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/motionblur.c b/modules/video_filter/motionblur.c
index b536c0a4520..1008596f845 100644
--- a/modules/video_filter/motionblur.c
+++ b/modules/video_filter/motionblur.c
@@ -36,7 +36,6 @@
 #include <vlc_sout.h>
 #include <vlc_filter.h>
 #include <vlc_picture.h>
-#include "filter_picture.h"
 
 /*****************************************************************************
  * Local protypes
@@ -45,10 +44,11 @@ typedef struct filter_sys_t filter_sys_t;
 
 static int  Create       ( vlc_object_t * );
 static void Destroy      ( vlc_object_t * );
-static picture_t *Filter ( filter_t *, picture_t * );
+static void Filter ( filter_t *, picture_t *, picture_t * );
 static void RenderBlur   ( filter_sys_t *, picture_t *, picture_t * );
 static int MotionBlurCallback( vlc_object_t *, char const *,
                                vlc_value_t, vlc_value_t, void * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 /*****************************************************************************
  * Module descriptor
@@ -113,11 +113,7 @@ static int Create( vlc_object_t *p_this )
     }
     p_sys->b_first = true;
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
                        p_filter->p_cfg );
@@ -149,20 +145,10 @@ static void Destroy( vlc_object_t *p_this )
 /*****************************************************************************
  * Filter
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t * p_outpic )
 {
-    picture_t * p_outpic;
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     if( p_sys->b_first )
     {
         picture_CopyPixels( p_sys->p_tmp, p_pic );
@@ -173,8 +159,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
     RenderBlur( p_sys, p_pic, p_outpic );
 
     picture_CopyPixels( p_sys->p_tmp, p_outpic );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/posterize.c b/modules/video_filter/posterize.c
index 99d69cac17f..5ffa53fe0ab 100644
--- a/modules/video_filter/posterize.c
+++ b/modules/video_filter/posterize.c
@@ -43,12 +43,13 @@
 static int  Create      ( vlc_object_t * );
 static void Destroy     ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static void PlanarYUVPosterize( picture_t *, picture_t *, int);
 static void PackedYUVPosterize( picture_t *, picture_t *, int);
 static void RVPosterize( picture_t *, picture_t *, bool, int );
 static void YuvPosterization( uint8_t *, uint8_t *, uint8_t *, uint8_t *,
                     uint8_t, uint8_t, uint8_t, uint8_t, int );
+VIDEO_FILTER_WRAPPER( Filter )
 
 static const char *const ppsz_filter_options[] = {
     "level", NULL
@@ -134,11 +135,7 @@ static int Create( vlc_object_t *p_this )
 
     var_AddCallback( p_filter, CFG_PREFIX "level", FilterCallback, p_sys );
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     return VLC_SUCCESS;
 }
@@ -164,23 +161,11 @@ static void Destroy( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
-
-    if( !p_pic ) return NULL;
-
     filter_sys_t *p_sys = p_filter->p_sys;
     int level = atomic_load( &p_sys->i_level );
 
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        msg_Warn( p_filter, "can't get output picture" );
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     switch( p_pic->format.i_chroma )
     {
         case VLC_CODEC_RGB24:
@@ -198,8 +183,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
         default:
             vlc_assert_unreachable();
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/postproc.c b/modules/video_filter/postproc.c
index 24fa4bc9ba7..452609da0b5 100644
--- a/modules/video_filter/postproc.c
+++ b/modules/video_filter/postproc.c
@@ -40,8 +40,6 @@
 #include <vlc_picture.h>
 #include <vlc_cpu.h>
 
-#include "filter_picture.h"
-
 #ifdef HAVE_POSTPROC_POSTPROCESS_H
 #   include <postproc/postprocess.h>
 #else
@@ -58,7 +56,8 @@
 static int OpenPostproc( vlc_object_t * );
 static void ClosePostproc( vlc_object_t * );
 
-static picture_t *PostprocPict( filter_t *, picture_t * );
+static void PostprocPict( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER( PostprocPict )
 
 static int PPQCallback( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
@@ -252,11 +251,7 @@ 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 );
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = PostprocPict,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &PostprocPict_ops;
 
     msg_Warn( p_filter, "Quantification table was not set by video decoder. "
                         "Postprocessing won't look good." );
@@ -284,17 +279,10 @@ static void ClosePostproc( vlc_object_t *p_this )
 /*****************************************************************************
  * PostprocPict
  *****************************************************************************/
-static picture_t *PostprocPict( filter_t *p_filter, picture_t *p_pic )
+static void PostprocPict( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    picture_t *p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     /* Lock to prevent issues if pp_mode is changed */
     vlc_mutex_lock( &p_sys->lock );
     if( p_sys->pp_mode != NULL )
@@ -322,8 +310,6 @@ static picture_t *PostprocPict( filter_t *p_filter, picture_t *p_pic )
     else
         picture_CopyPixels( p_outpic, p_pic );
     vlc_mutex_unlock( &p_sys->lock );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/psychedelic.c b/modules/video_filter/psychedelic.c
index 5295ffce441..d4ec4afca15 100644
--- a/modules/video_filter/psychedelic.c
+++ b/modules/video_filter/psychedelic.c
@@ -36,7 +36,6 @@
 #include <vlc_filter.h>
 #include <vlc_picture.h>
 #include <vlc_image.h>
-#include "filter_picture.h"
 
 /*****************************************************************************
  * Local prototypes
@@ -44,7 +43,8 @@
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 /*****************************************************************************
  * Module descriptor
@@ -96,11 +96,7 @@ static int Create( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_filter->p_sys = p_sys;
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     p_sys->x = 10;
     p_sys->y = 10;
@@ -139,25 +135,14 @@ static void Destroy( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
-
     unsigned int w, h;
     uint8_t u,v;
 
     picture_t *p_converted;
     video_format_t fmt_out;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     filter_sys_t *p_sys = p_filter->p_sys;
 
     if( !p_sys->p_image )
@@ -259,6 +244,4 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
         else if( p_sys->u == 0 )
             p_sys->v += 1;
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
diff --git a/modules/video_filter/ripple.c b/modules/video_filter/ripple.c
index 9355f60ca2e..2db2b922211 100644
--- a/modules/video_filter/ripple.c
+++ b/modules/video_filter/ripple.c
@@ -42,7 +42,8 @@
  *****************************************************************************/
 static int  Create    ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER(Filter)
 
 /*****************************************************************************
  * Module descriptor
@@ -90,11 +91,7 @@ static int Create( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_filter->p_sys = p_sys;
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     p_sys->f_angle = 0.0;
     p_sys->last_date = 0;
@@ -109,21 +106,11 @@ static int Create( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     double f_angle;
     vlc_tick_t new_date = vlc_tick_now();
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     filter_sys_t *p_sys = p_filter->p_sys;
 
     p_sys->f_angle -= 10.0f * secf_from_vlc_tick(p_sys->last_date - new_date);
@@ -221,6 +208,4 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             p_out += p_outpic->p[i_index].i_pitch;
         }
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
diff --git a/modules/video_filter/rotate.c b/modules/video_filter/rotate.c
index 48b9d92cb3a..a2b56118b67 100644
--- a/modules/video_filter/rotate.c
+++ b/modules/video_filter/rotate.c
@@ -45,8 +45,9 @@
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static picture_t *FilterPacked( filter_t *, picture_t * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 static int RotateCallback( vlc_object_t *p_this, char const *psz_var,
                            vlc_value_t oldval, vlc_value_t newval,
@@ -118,11 +119,6 @@ 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,
@@ -145,7 +141,7 @@ static int Create( vlc_object_t *p_this )
     switch( p_filter->fmt_in.video.i_chroma )
     {
         CASE_PLANAR_YUV
-            p_filter->ops = &planar_filter_ops;
+            p_filter->ops = &Filter_ops;
             break;
 
         CASE_PACKED_YUV_422
@@ -210,20 +206,10 @@ static void Destroy( vlc_object_t *p_this )
 /*****************************************************************************
  *
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     filter_sys_t *p_sys = p_filter->p_sys;
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     if( p_sys->p_motion != NULL )
     {
         int i_angle = motion_get_angle( p_sys->p_motion );
@@ -331,8 +317,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             i_col_orig0 += i_col_next;
         }
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 /*****************************************************************************
diff --git a/modules/video_filter/scale.c b/modules/video_filter/scale.c
index 648be69e4ab..f33b8c0cb92 100644
--- a/modules/video_filter/scale.c
+++ b/modules/video_filter/scale.c
@@ -38,7 +38,8 @@
  * Local prototypes
  ****************************************************************************/
 static int  OpenFilter ( vlc_object_t * );
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
+VIDEO_FILTER_WRAPPER(Filter)
 
 /*****************************************************************************
  * Module descriptor
@@ -75,11 +76,7 @@ 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 );
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    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,
@@ -91,23 +88,11 @@ static int OpenFilter( vlc_object_t *p_this )
 /****************************************************************************
  * Filter: the whole thing
  ****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_pic_dst )
 {
-    picture_t *p_pic_dst;
-
-    if( !p_pic ) return NULL;
-
 #warning Converter cannot (really) change output format.
     video_format_ScaleCropAr( &p_filter->fmt_out.video, &p_filter->fmt_in.video );
 
-    /* Request output picture */
-    p_pic_dst = filter_NewPicture( p_filter );
-    if( !p_pic_dst )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_RGBA &&
         p_filter->fmt_in.video.i_chroma != VLC_CODEC_ARGB &&
         p_filter->fmt_in.video.i_chroma != VLC_CODEC_BGRA &&
@@ -201,8 +186,4 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             }
         }
     }
-
-    picture_CopyProperties( p_pic_dst, p_pic );
-    picture_Release( p_pic );
-    return p_pic_dst;
 }
diff --git a/modules/video_filter/sepia.c b/modules/video_filter/sepia.c
index aa653ffdc83..86364004862 100644
--- a/modules/video_filter/sepia.c
+++ b/modules/video_filter/sepia.c
@@ -47,10 +47,11 @@ static void Destroy     ( vlc_object_t * );
 static void RVSepia( picture_t *, picture_t *, int );
 static void PlanarI420Sepia( picture_t *, picture_t *, int);
 static void PackedYUVSepia( picture_t *, picture_t *, int);
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static const char *const ppsz_filter_options[] = {
     "intensity", NULL
 };
+VIDEO_FILTER_WRAPPER( Filter )
 
 /*****************************************************************************
  * Module descriptor
@@ -143,11 +144,7 @@ static int Create( vlc_object_t *p_this )
              var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "intensity" ) );
     var_AddCallback( p_filter, CFG_PREFIX "intensity", FilterCallback, NULL );
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     return VLC_SUCCESS;
 }
@@ -173,26 +170,12 @@ static void Destroy( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
-
-    if( !p_pic ) return NULL;
-
     filter_sys_t *p_sys = p_filter->p_sys;
     int intensity = atomic_load( &p_sys->i_intensity );
 
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        msg_Warn( p_filter, "can't get output picture" );
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     p_sys->pf_sepia( p_pic, p_outpic, intensity );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 #if defined(CAN_COMPILE_SSE2)
diff --git a/modules/video_filter/sharpen.c b/modules/video_filter/sharpen.c
index a53ca5c5001..1933414d339 100644
--- a/modules/video_filter/sharpen.c
+++ b/modules/video_filter/sharpen.c
@@ -42,7 +42,6 @@
 #include <vlc_plugin.h>
 #include <vlc_filter.h>
 #include <vlc_picture.h>
-#include "filter_picture.h"
 
 #define SIG_TEXT N_("Sharpen strength (0-2)")
 #define SIG_LONGTEXT N_("Set the Sharpen strength, between 0 and 2. Defaults to 0.05.")
@@ -53,9 +52,10 @@
 static int  Create    ( vlc_object_t * );
 static void Destroy   ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 static int SharpenCallback( vlc_object_t *, char const *,
                             vlc_value_t, vlc_value_t, void * );
+VIDEO_FILTER_WRAPPER( Filter )
 
 #define SHARPEN_HELP N_("Augment contrast between contours.")
 #define FILTER_PREFIX "sharpen-"
@@ -118,11 +118,7 @@ static int Create( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_filter->p_sys = p_sys;
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     config_ChainParse( p_filter, FILTER_PREFIX, ppsz_filter_options,
                    p_filter->p_cfg );
@@ -208,21 +204,13 @@ static void Destroy( vlc_object_t *p_this )
                i_visible_pitch);                                        \
     } while (0)
 
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     const int v1 = -1;
     const int v2 = 3; /* 2^3 = 8 */
     const unsigned i_visible_lines = p_pic->p[Y_PLANE].i_visible_lines;
     const unsigned i_visible_pitch = p_pic->p[Y_PLANE].i_visible_pitch;
 
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     filter_sys_t *p_sys = p_filter->p_sys;
 
     if (!IS_YUV_420_10BITS(p_pic->format.i_chroma))
@@ -232,8 +220,6 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
 
     plane_CopyPixels( &p_outpic->p[U_PLANE], &p_pic->p[U_PLANE] );
     plane_CopyPixels( &p_outpic->p[V_PLANE], &p_pic->p[V_PLANE] );
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
 static int SharpenCallback( vlc_object_t *p_this, char const *psz_var,
diff --git a/modules/video_filter/wave.c b/modules/video_filter/wave.c
index e732251cacc..e1c0f5f4f60 100644
--- a/modules/video_filter/wave.c
+++ b/modules/video_filter/wave.c
@@ -42,7 +42,7 @@
  *****************************************************************************/
 static int  Create    ( vlc_object_t * );
 
-static picture_t *Filter( filter_t *, picture_t * );
+static void Filter( filter_t *, picture_t *, picture_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -58,6 +58,8 @@ vlc_module_begin ()
     set_callback( Create )
 vlc_module_end ()
 
+VIDEO_FILTER_WRAPPER(Filter)
+
 /*****************************************************************************
  * filter_sys_t: Distort video output method descriptor
  *****************************************************************************
@@ -90,11 +92,7 @@ static int Create( vlc_object_t *p_this )
     if( !p_sys )
         return VLC_ENOMEM;
 
-    static const struct vlc_filter_operations filter_ops =
-    {
-        .filter_video = Filter,
-    };
-    p_filter->ops = &filter_ops;
+    p_filter->ops = &Filter_ops;
 
     p_sys->f_angle = 0.0;
     p_sys->last_date = 0;
@@ -109,21 +107,11 @@ static int Create( vlc_object_t *p_this )
  * until it is displayed and switch the two rendering buffers, preparing next
  * frame.
  *****************************************************************************/
-static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+static void Filter( filter_t *p_filter, picture_t *p_pic, picture_t *p_outpic )
 {
-    picture_t *p_outpic;
     double f_angle;
     vlc_tick_t new_date = vlc_tick_now();
 
-    if( !p_pic ) return NULL;
-
-    p_outpic = filter_NewPicture( p_filter );
-    if( !p_outpic )
-    {
-        picture_Release( p_pic );
-        return NULL;
-    }
-
     filter_sys_t *p_sys = p_filter->p_sys;
 
     p_sys->f_angle += 5.0f * secf_from_vlc_tick(new_date - p_sys->last_date);
@@ -206,6 +194,4 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
             p_out += p_outpic->p[i_index].i_pitch;
         }
     }
-
-    return CopyInfoAndRelease( p_outpic, p_pic );
 }
-- 
2.26.2



More information about the vlc-devel mailing list