[vlc-devel] [PATCH 16/25] deinterlace: one function pointer per frame

Victorien Le Couviour--Tuffet victorien.lecouviour.tuffet at gmail.com
Tue Apr 14 12:40:27 CEST 2020


Instead of per feature line merging functions, have per CPU feature
frame deinterlacing implementations.
This prepares for having assembly seperate files of deinterlacing
methods, in the next commits.
---
 modules/video_filter/deinterlace/algo_basic.c | 400 +++++++++++++-----
 modules/video_filter/deinterlace/algo_basic.h |  12 +-
 modules/video_filter/deinterlace/algo_ivtc.c  |   6 +
 modules/video_filter/deinterlace/algo_ivtc.h  |   2 +-
 .../video_filter/deinterlace/algo_phosphor.c  |  12 +-
 .../video_filter/deinterlace/algo_phosphor.h  |   4 +-
 modules/video_filter/deinterlace/algo_x.c     |   8 +-
 modules/video_filter/deinterlace/algo_x.h     |   2 +-
 modules/video_filter/deinterlace/algo_yadif.c |  31 +-
 modules/video_filter/deinterlace/algo_yadif.h |   5 +-
 .../video_filter/deinterlace/deinterlace.c    |  37 +-
 .../video_filter/deinterlace/deinterlace.h    |   5 +
 12 files changed, 370 insertions(+), 154 deletions(-)

diff --git a/modules/video_filter/deinterlace/algo_basic.c b/modules/video_filter/deinterlace/algo_basic.c
index 1d652d634b..2ef7698c31 100644
--- a/modules/video_filter/deinterlace/algo_basic.c
+++ b/modules/video_filter/deinterlace/algo_basic.c
@@ -32,17 +32,17 @@
 #include <vlc_common.h>
 #include <vlc_picture.h>
 #include <vlc_filter.h>
-
-#include "merge.h"
-#include "deinterlace.h" /* definition of p_sys, needed for Merge() */
-
+#include <vlc_cpu.h>
+#include "deinterlace.h"
 #include "algo_basic.h"
+#include "merge.h"
 
 /*****************************************************************************
  * RenderDiscard: only keep TOP or BOTTOM field, discard the other.
  *****************************************************************************/
 
-int RenderDiscard( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
+static int RenderDiscard( filter_t *p_filter,
+                          picture_t *p_outpic, picture_t *p_pic )
 {
     VLC_UNUSED(p_filter);
     int i_plane;
@@ -69,12 +69,19 @@ int RenderDiscard( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
     return VLC_SUCCESS;
 }
 
+single_pic_renderer_t DiscardRenderer(unsigned pixel_size)
+{
+    VLC_UNUSED(pixel_size);
+    return RenderDiscard;
+}
+
 /*****************************************************************************
  * RenderBob: renders a BOB picture - simple copy
  *****************************************************************************/
 
-int RenderBob( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic,
-               int order, int i_field )
+static int RenderBob( filter_t *p_filter,
+                      picture_t *p_outpic, picture_t *p_pic,
+                      int order, int i_field )
 {
     VLC_UNUSED(p_filter);
     VLC_UNUSED(order);
@@ -125,132 +132,305 @@ int RenderBob( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic,
     return VLC_SUCCESS;
 }
 
+ordered_renderer_t BobRenderer(unsigned pixel_size)
+{
+    VLC_UNUSED(pixel_size);
+    return RenderBob;
+}
+
 /*****************************************************************************
  * RenderLinear: BOB with linear interpolation
  *****************************************************************************/
 
-int RenderLinear( filter_t *p_filter,
-                  picture_t *p_outpic, picture_t *p_pic, int order, int i_field )
-{
-    VLC_UNUSED(order);
-    int i_plane;
-
-    filter_sys_t *p_sys = p_filter->p_sys;
-
-    /* Copy image and skip lines */
-    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
-    {
-        uint8_t *p_in, *p_out_end, *p_out;
-
-        p_in = p_pic->p[i_plane].p_pixels;
-        p_out = p_outpic->p[i_plane].p_pixels;
-        p_out_end = p_out + p_outpic->p[i_plane].i_pitch
-                             * p_outpic->p[i_plane].i_visible_lines;
-
-        /* For BOTTOM field we need to add the first line */
-        if( i_field == 1 )
-        {
-            memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
-            p_in += p_pic->p[i_plane].i_pitch;
-            p_out += p_outpic->p[i_plane].i_pitch;
-        }
-
-        p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;
-
-        for( ; p_out < p_out_end ; )
-        {
-            memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
-
-            p_out += p_outpic->p[i_plane].i_pitch;
-
-            Merge( p_out, p_in, p_in + 2 * p_pic->p[i_plane].i_pitch,
-                   p_pic->p[i_plane].i_pitch );
+#define RENDER_LINEAR(merge, bpc, feature)                                  \
+static int RenderLinear##bpc##Bit_##feature( filter_t *p_filter,            \
+                                             picture_t *p_outpic,           \
+                                             picture_t *p_pic,              \
+                                             int order, int i_field )       \
+{                                                                           \
+    VLC_UNUSED(p_filter); VLC_UNUSED(order);                                \
+    int i_plane;                                                            \
+                                                                            \
+    /* Copy image and skip lines */                                         \
+    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )              \
+    {                                                                       \
+        uint8_t *p_in, *p_out_end, *p_out;                                  \
+                                                                            \
+        p_in = p_pic->p[i_plane].p_pixels;                                  \
+        p_out = p_outpic->p[i_plane].p_pixels;                              \
+        p_out_end = p_out + p_outpic->p[i_plane].i_pitch                    \
+                             * p_outpic->p[i_plane].i_visible_lines;        \
+                                                                            \
+        /* For BOTTOM field we need to add the first line */                \
+        if( i_field == 1 )                                                  \
+        {                                                                   \
+            memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );               \
+            p_in += p_pic->p[i_plane].i_pitch;                              \
+            p_out += p_outpic->p[i_plane].i_pitch;                          \
+        }                                                                   \
+                                                                            \
+        p_out_end -= 2 * p_outpic->p[i_plane].i_pitch;                      \
+                                                                            \
+        for( ; p_out < p_out_end ; )                                        \
+        {                                                                   \
+            memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );               \
+                                                                            \
+            p_out += p_outpic->p[i_plane].i_pitch;                          \
+                                                                            \
+            ptrdiff_t stride = p_pic->p[i_plane].i_pitch;                   \
+            merge( p_out, p_in, p_in + 2 * stride, stride);                 \
+                                                                            \
+            p_in += 2 * p_pic->p[i_plane].i_pitch;                          \
+            p_out += p_outpic->p[i_plane].i_pitch;                          \
+        }                                                                   \
+                                                                            \
+        memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );                   \
+                                                                            \
+        /* For TOP field we need to add the last line */                    \
+        if( i_field == 0 )                                                  \
+        {                                                                   \
+            p_in += p_pic->p[i_plane].i_pitch;                              \
+            p_out += p_outpic->p[i_plane].i_pitch;                          \
+            memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );               \
+        }                                                                   \
+    }                                                                       \
+    return VLC_SUCCESS;                                                     \
+}
 
-            p_in += 2 * p_pic->p[i_plane].i_pitch;
-            p_out += p_outpic->p[i_plane].i_pitch;
-        }
+#define RENDER_LINEAR_SIMD(bpc, feature) \
+    RENDER_LINEAR(Merge##bpc##Bit##feature, bpc, feature)
+#define RENDER_LINEAR_ARM(bpc, feature) \
+    RENDER_LINEAR(merge##bpc##_##feature, bpc, feature)
 
-        memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
+RENDER_LINEAR(Merge8BitGeneric, 8, c)
+RENDER_LINEAR(Merge16BitGeneric, 16, c)
+#if defined(CAN_COMPILE_SSE2)
+RENDER_LINEAR_SIMD(8, SSE2)
+RENDER_LINEAR_SIMD(16, SSE2)
+#endif
+#if defined(CAN_COMPILE_ARM)
+RENDER_LINEAR_ARM(8, arm_neon)
+RENDER_LINEAR_ARM(16, arm_neon)
+RENDER_LINEAR_ARM(8, armv6)
+RENDER_LINEAR_ARM(16, armv6)
+#endif
+#if defined(CAN_COMPILE_SVE)
+RENDER_LINEAR_ARM(8, arm_sve)
+RENDER_LINEAR_ARM(16, arm_sve)
+#endif
+#if defined(CAN_COMPULE_ARM64)
+RENDER_LINEAR_ARM(8, arm64_neon)
+RENDER_LINEAR_ARM(16, arm64_neon)
+#endif
 
-        /* For TOP field we need to add the last line */
-        if( i_field == 0 )
-        {
-            p_in += p_pic->p[i_plane].i_pitch;
-            p_out += p_outpic->p[i_plane].i_pitch;
-            memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
-        }
-    }
-    return VLC_SUCCESS;
+ordered_renderer_t LinearRenderer(unsigned pixel_size)
+{
+#if defined(CAN_COMPILE_SSE2)
+    if (vlc_CPU_SSE2())
+        return pixel_size & 1 ? RenderLinear8Bit_SSE2 : RenderLinear16Bit_SSE2;
+    else
+#endif
+#if defined(CAN_COMPILE_ARM)
+    if (vlc_CPU_ARM_NEON())
+        return pixel_size & 1 ? RenderLinear8Bit_arm_neon : RenderLinear16Bit_arm_neon;
+    else
+    if (vlc_CPU_ARMv6())
+        return pixel_size & 1 ? RenderLinear8Bit_armv6 : RenderLinear16Bit_armv6;
+    else
+#endif
+#if defined(CAN_COMPILE_SVE)
+    if (vlc_CPU_ARM_SVE())
+        return pixel_size & 1 ? RenderLinear8Bit_arm_sve : RenderLinear16Bit_arm_sve;
+    else
+#endif
+#if defined(CAN_COMPULE_ARM64)
+    if (vlc_CPU_ARM_NEON())
+        return pixel_size & 1 ? RenderLinear8Bit_arm64_neon : RenderLinear16Bit_arm64_neon;
+    else
+#endif
+        return pixel_size & 1 ? RenderLinear8Bit_c : RenderLinear16Bit_c;
 }
 
 /*****************************************************************************
  * RenderMean: Half-resolution blender
  *****************************************************************************/
 
-int RenderMean( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
-{
-    int i_plane;
-
-    filter_sys_t *p_sys = p_filter->p_sys;
-
-    /* Copy image and skip lines */
-    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
-    {
-        uint8_t *p_in, *p_out_end, *p_out;
-
-        p_in = p_pic->p[i_plane].p_pixels;
+#define RENDER_MEAN(merge, bpc, feature)                                    \
+static int RenderMean##bpc##Bit_##feature( filter_t *p_filter,              \
+                                          picture_t *p_outpic,              \
+                                          picture_t *p_pic )                \
+{                                                                           \
+    VLC_UNUSED(p_filter);                                                   \
+    int i_plane;                                                            \
+                                                                            \
+    /* Copy image and skip lines */                                         \
+    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )              \
+    {                                                                       \
+        uint8_t *p_in, *p_out_end, *p_out;                                  \
+                                                                            \
+        p_in = p_pic->p[i_plane].p_pixels;                                  \
+                                                                            \
+        p_out = p_outpic->p[i_plane].p_pixels;                              \
+        p_out_end = p_out + p_outpic->p[i_plane].i_pitch                    \
+                             * p_outpic->p[i_plane].i_visible_lines;        \
+                                                                            \
+        /* All lines: mean value */                                         \
+        for( ; p_out < p_out_end ; )                                        \
+        {                                                                   \
+            merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,           \
+                   p_pic->p[i_plane].i_pitch );                             \
+                                                                            \
+            p_out += p_outpic->p[i_plane].i_pitch;                          \
+            p_in += 2 * p_pic->p[i_plane].i_pitch;                          \
+        }                                                                   \
+    }                                                                       \
+    return VLC_SUCCESS;                                                     \
+}
 
-        p_out = p_outpic->p[i_plane].p_pixels;
-        p_out_end = p_out + p_outpic->p[i_plane].i_pitch
-                             * p_outpic->p[i_plane].i_visible_lines;
+#define RENDER_MEAN_SIMD(bpc, feature) \
+    RENDER_MEAN(Merge##bpc##Bit##feature, bpc, feature)
+#define RENDER_MEAN_ARM(bpc, feature) \
+    RENDER_MEAN(merge##bpc##_##feature, bpc, feature)
 
-        /* All lines: mean value */
-        for( ; p_out < p_out_end ; )
-        {
-            Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
-                   p_pic->p[i_plane].i_pitch );
+RENDER_MEAN(Merge8BitGeneric, 8, c)
+RENDER_MEAN(Merge16BitGeneric, 16, c)
+#if defined(CAN_COMPILE_SSE2)
+RENDER_MEAN_SIMD(8, SSE2)
+RENDER_MEAN_SIMD(16, SSE2)
+#endif
+#if defined(CAN_COMPILE_ARM)
+RENDER_MEAN_ARM(8, arm_neon)
+RENDER_MEAN_ARM(16, arm_neon)
+RENDER_MEAN_ARM(8, armv6)
+RENDER_MEAN_ARM(16, armv6)
+#endif
+#if defined(CAN_COMPILE_SVE)
+RENDER_MEAN_ARM(8, arm_sve)
+RENDER_MEAN_ARM(16, arm_sve)
+#endif
+#if defined(CAN_COMPULE_ARM64)
+RENDER_MEAN_ARM(8, arm64_neon)
+RENDER_MEAN_ARM(16, arm64_neon)
+#endif
 
-            p_out += p_outpic->p[i_plane].i_pitch;
-            p_in += 2 * p_pic->p[i_plane].i_pitch;
-        }
-    }
-    return VLC_SUCCESS;
+single_pic_renderer_t MeanRenderer(unsigned pixel_size)
+{
+#if defined(CAN_COMPILE_SSE2)
+    if (vlc_CPU_SSE2())
+        return pixel_size & 1 ? RenderMean8Bit_SSE2 : RenderMean16Bit_SSE2;
+    else
+#endif
+#if defined(CAN_COMPILE_ARM)
+    if (vlc_CPU_ARM_NEON())
+        return pixel_size & 1 ? RenderMean8Bit_arm_neon : RenderMean16Bit_arm_neon;
+    else
+    if (vlc_CPU_ARMv6())
+        return pixel_size & 1 ? RenderMean8Bit_armv6 : RenderMean16Bit_armv6;
+    else
+#endif
+#if defined(CAN_COMPILE_SVE)
+    if (vlc_CPU_ARM_SVE())
+        return pixel_size & 1 ? RenderMean8Bit_arm_sve : RenderMean16Bit_arm_sve;
+    else
+#endif
+#if defined(CAN_COMPULE_ARM64)
+    if (vlc_CPU_ARM_NEON())
+        return pixel_size & 1 ? RenderMean8Bit_arm64_neon : RenderMean16Bit_arm64_neon;
+    else
+#endif
+        return pixel_size & 1 ? RenderMean8Bit_c : RenderMean16Bit_c;
 }
 
 /*****************************************************************************
  * RenderBlend: Full-resolution blender
  *****************************************************************************/
 
-int RenderBlend( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
-{
-    int i_plane;
-
-    filter_sys_t *p_sys = p_filter->p_sys;
-
-    /* Copy image and skip lines */
-    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
-    {
-        uint8_t *p_in, *p_out_end, *p_out;
-
-        p_in = p_pic->p[i_plane].p_pixels;
-
-        p_out = p_outpic->p[i_plane].p_pixels;
-        p_out_end = p_out + p_outpic->p[i_plane].i_pitch
-                             * p_outpic->p[i_plane].i_visible_lines;
+#define RENDER_BLEND(merge, bpc, feature)                                   \
+static int RenderBlend##bpc##Bit_##feature( filter_t *p_filter,             \
+                                            picture_t *p_outpic,            \
+                                            picture_t *p_pic )              \
+{                                                                           \
+    VLC_UNUSED(p_filter);                                                   \
+    int i_plane;                                                            \
+                                                                            \
+    /* Copy image and skip lines */                                         \
+    for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )              \
+    {                                                                       \
+        uint8_t *p_in, *p_out_end, *p_out;                                  \
+                                                                            \
+        p_in = p_pic->p[i_plane].p_pixels;                                  \
+                                                                            \
+        p_out = p_outpic->p[i_plane].p_pixels;                              \
+        p_out_end = p_out + p_outpic->p[i_plane].i_pitch                    \
+                             * p_outpic->p[i_plane].i_visible_lines;        \
+                                                                            \
+        /* First line: simple copy */                                       \
+        memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );                   \
+        p_out += p_outpic->p[i_plane].i_pitch;                              \
+                                                                            \
+        /* Remaining lines: mean value */                                   \
+        for( ; p_out < p_out_end ; )                                        \
+        {                                                                   \
+            merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,           \
+                   p_pic->p[i_plane].i_pitch );                             \
+                                                                            \
+            p_out += p_outpic->p[i_plane].i_pitch;                          \
+            p_in  += p_pic->p[i_plane].i_pitch;                             \
+        }                                                                   \
+    }                                                                       \
+    return VLC_SUCCESS;                                                     \
+}
 
-        /* First line: simple copy */
-        memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch );
-        p_out += p_outpic->p[i_plane].i_pitch;
+#define RENDER_BLEND_SIMD(bpc, feature) \
+    RENDER_BLEND(Merge##bpc##Bit##feature, bpc, feature)
+#define RENDER_BLEND_ARM(bpc, feature) \
+    RENDER_BLEND(merge##bpc##_##feature, bpc, feature)
 
-        /* Remaining lines: mean value */
-        for( ; p_out < p_out_end ; )
-        {
-            Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch,
-                   p_pic->p[i_plane].i_pitch );
+RENDER_BLEND(Merge8BitGeneric, 8, c)
+RENDER_BLEND(Merge16BitGeneric, 16, c)
+#if defined(CAN_COMPILE_SSE2)
+RENDER_BLEND_SIMD(8, SSE2)
+RENDER_BLEND_SIMD(16, SSE2)
+#endif
+#if defined(CAN_COMPILE_ARM)
+RENDER_BLEND_ARM(8, arm_neon)
+RENDER_BLEND_ARM(16, arm_neon)
+RENDER_BLEND_ARM(8, armv6)
+RENDER_BLEND_ARM(16, armv6)
+#endif
+#if defined(CAN_COMPILE_SVE)
+RENDER_BLEND_ARM(8, arm_sve)
+RENDER_BLEND_ARM(16, arm_sve)
+#endif
+#if defined(CAN_COMPULE_ARM64)
+RENDER_BLEND_ARM(8, arm64_neon)
+RENDER_BLEND_ARM(16, arm64_neon)
+#endif
 
-            p_out += p_outpic->p[i_plane].i_pitch;
-            p_in  += p_pic->p[i_plane].i_pitch;
-        }
-    }
-    return VLC_SUCCESS;
+single_pic_renderer_t BlendRenderer(unsigned pixel_size)
+{
+#if defined(CAN_COMPILE_SSE2)
+    if (vlc_CPU_SSE2())
+        return pixel_size & 1 ? RenderBlend8Bit_SSE2 : RenderBlend16Bit_SSE2;
+    else
+#endif
+#if defined(CAN_COMPILE_ARM)
+    if (vlc_CPU_ARM_NEON())
+        return pixel_size & 1 ? RenderBlend8Bit_arm_neon : RenderBlend16Bit_arm_neon;
+    else
+    if (vlc_CPU_ARMv6())
+        return pixel_size & 1 ? RenderBlend8Bit_armv6 : RenderBlend16Bit_armv6;
+    else
+#endif
+#if defined(CAN_COMPILE_SVE)
+    if (vlc_CPU_ARM_SVE())
+        return pixel_size & 1 ? RenderBlend8Bit_arm_sve : RenderBlend16Bit_arm_sve;
+    else
+#endif
+#if defined(CAN_COMPULE_ARM64)
+    if (vlc_CPU_ARM_NEON())
+        return pixel_size & 1 ? RenderBlend8Bit_arm64_neon : RenderBlend16Bit_arm64_neon;
+    else
+#endif
+        return pixel_size & 1 ? RenderBlend8Bit_c : RenderBlend16Bit_c;
 }
diff --git a/modules/video_filter/deinterlace/algo_basic.h b/modules/video_filter/deinterlace/algo_basic.h
index 1f25563ab8..d6dce2a4e8 100644
--- a/modules/video_filter/deinterlace/algo_basic.h
+++ b/modules/video_filter/deinterlace/algo_basic.h
@@ -48,7 +48,7 @@ struct picture_t;
  * @see RenderBob()
  * @see Deinterlace()
  */
-int RenderDiscard( filter_t *, picture_t *p_outpic, picture_t *p_pic );
+single_pic_renderer_t DiscardRenderer(unsigned pixel_size);
 
 /**
  * RenderBob: basic framerate doubler.
@@ -63,8 +63,7 @@ int RenderDiscard( filter_t *, picture_t *p_outpic, picture_t *p_pic );
  * @see RenderLinear()
  * @see Deinterlace()
  */
-int RenderBob( filter_t *,
-               picture_t *p_outpic, picture_t *p_pic, int order, int i_field );
+ordered_renderer_t BobRenderer(unsigned pixel_size);
 
 /**
  * RenderLinear: Bob with linear interpolation.
@@ -78,8 +77,7 @@ int RenderBob( filter_t *,
  * @see RenderBob()
  * @see Deinterlace()
  */
-int RenderLinear( filter_t *p_filter,
-                  picture_t *p_outpic, picture_t *p_pic, int order, int i_field );
+ordered_renderer_t LinearRenderer(unsigned pixel_size);
 
 /**
  * RenderMean: half-resolution blender.
@@ -93,7 +91,7 @@ int RenderLinear( filter_t *p_filter,
  * @param p_pic Input frame. Must exist.
  * @see Deinterlace()
  */
-int RenderMean( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic );
+single_pic_renderer_t MeanRenderer(unsigned pixel_size);
 
 /**
  * RenderBlend: full-resolution blender.
@@ -108,6 +106,6 @@ int RenderMean( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic );
  * @param p_pic Input frame. Must exist.
  * @see Deinterlace()
  */
-int RenderBlend( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic );
+single_pic_renderer_t BlendRenderer(unsigned pixel_size);
 
 #endif
diff --git a/modules/video_filter/deinterlace/algo_ivtc.c b/modules/video_filter/deinterlace/algo_ivtc.c
index 2e6d09b69d..242d8c01cb 100644
--- a/modules/video_filter/deinterlace/algo_ivtc.c
+++ b/modules/video_filter/deinterlace/algo_ivtc.c
@@ -1570,6 +1570,12 @@ int RenderIVTC( filter_t *p_filter, picture_t *p_dst, picture_t *p_pic )
     }
 }
 
+single_pic_renderer_t IVTCRenderer(unsigned pixel_size)
+{
+    VLC_UNUSED(pixel_size);
+    return RenderIVTC;
+}
+
 /* See function doc in header. */
 void IVTCClearState( filter_t *p_filter )
 {
diff --git a/modules/video_filter/deinterlace/algo_ivtc.h b/modules/video_filter/deinterlace/algo_ivtc.h
index f032d7e21b..5f04669927 100644
--- a/modules/video_filter/deinterlace/algo_ivtc.h
+++ b/modules/video_filter/deinterlace/algo_ivtc.h
@@ -138,7 +138,7 @@ typedef struct
  * @see CalculateInterlaceScore()
  * @see EstimateNumBlocksWithMotion()
  */
-int RenderIVTC( filter_t *p_filter, picture_t *p_dst, picture_t *p_pic );
+single_pic_renderer_t IVTCRenderer(unsigned pixel_size);
 
 /**
  * Clears the inverse telecine subsystem state.
diff --git a/modules/video_filter/deinterlace/algo_phosphor.c b/modules/video_filter/deinterlace/algo_phosphor.c
index 289eed783b..71f631e0d5 100644
--- a/modules/video_filter/deinterlace/algo_phosphor.c
+++ b/modules/video_filter/deinterlace/algo_phosphor.c
@@ -276,9 +276,9 @@ static void DarkenFieldMMX( picture_t *p_dst,
  *****************************************************************************/
 
 /* See header for function doc. */
-int RenderPhosphor( filter_t *p_filter,
-                    picture_t *p_dst, picture_t *p_pic,
-                    int i_order, int i_field )
+static int RenderPhosphor( filter_t *p_filter,
+                           picture_t *p_dst, picture_t *p_pic,
+                           int i_order, int i_field )
 {
     VLC_UNUSED(p_pic);
     assert( p_filter != NULL );
@@ -370,3 +370,9 @@ int RenderPhosphor( filter_t *p_filter,
     }
     return VLC_SUCCESS;
 }
+
+ordered_renderer_t PhosphorRenderer(unsigned pixel_size)
+{
+    VLC_UNUSED(pixel_size);
+    return RenderPhosphor;
+}
diff --git a/modules/video_filter/deinterlace/algo_phosphor.h b/modules/video_filter/deinterlace/algo_phosphor.h
index 3cc5aaca46..6cae0e2cad 100644
--- a/modules/video_filter/deinterlace/algo_phosphor.h
+++ b/modules/video_filter/deinterlace/algo_phosphor.h
@@ -99,9 +99,7 @@ typedef struct
  * @see RenderLinear()
  * @see Deinterlace()
  */
-int RenderPhosphor( filter_t *p_filter,
-                    picture_t *p_dst, picture_t *p_pic,
-                    int i_order, int i_field );
+ordered_renderer_t PhosphorRenderer(unsigned pixel_size);
 
 /*****************************************************************************
  * Extra documentation
diff --git a/modules/video_filter/deinterlace/algo_x.c b/modules/video_filter/deinterlace/algo_x.c
index 411351d1cd..205f5e8286 100644
--- a/modules/video_filter/deinterlace/algo_x.c
+++ b/modules/video_filter/deinterlace/algo_x.c
@@ -511,7 +511,7 @@ static inline void XDeintBand8x8MMXEXT( uint8_t *dst, int i_dst,
  * Public functions
  *****************************************************************************/
 
-int RenderX( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
+static int RenderX( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
 {
     VLC_UNUSED(p_filter);
     int i_plane;
@@ -571,3 +571,9 @@ int RenderX( filter_t *p_filter, picture_t *p_outpic, picture_t *p_pic )
 #endif
     return VLC_SUCCESS;
 }
+
+single_pic_renderer_t XRenderer(unsigned pixel_size)
+{
+    VLC_UNUSED(pixel_size);
+    return RenderX;
+}
diff --git a/modules/video_filter/deinterlace/algo_x.h b/modules/video_filter/deinterlace/algo_x.h
index dd70cbd732..4e6bd6b323 100644
--- a/modules/video_filter/deinterlace/algo_x.h
+++ b/modules/video_filter/deinterlace/algo_x.h
@@ -49,6 +49,6 @@ struct picture_t;
  * @param[out] p_outpic Output frame. Must be allocated by caller.
  * @see Deinterlace()
  */
-int RenderX( filter_t *, picture_t *p_outpic, picture_t *p_pic );
+single_pic_renderer_t XRenderer(unsigned pixel_size);
 
 #endif
diff --git a/modules/video_filter/deinterlace/algo_yadif.c b/modules/video_filter/deinterlace/algo_yadif.c
index 6fdecf53a5..fe1bf427cb 100644
--- a/modules/video_filter/deinterlace/algo_yadif.c
+++ b/modules/video_filter/deinterlace/algo_yadif.c
@@ -46,13 +46,8 @@
    Necessary preprocessor macros are defined in common.h. */
 #include "yadif.h"
 
-int RenderYadifSingle( filter_t *p_filter, picture_t *p_dst, picture_t *p_src )
-{
-    return RenderYadif( p_filter, p_dst, p_src, 0, 0 );
-}
-
-int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
-                 int i_order, int i_field )
+static int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
+                        int i_order, int i_field )
 {
     VLC_UNUSED(p_src);
 
@@ -184,8 +179,9 @@ int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
                  as set by Open() or SetFilterMethod(). It is always 0. */
 
         /* FIXME not good as it does not use i_order/i_field */
-        RenderX( p_filter, p_dst, p_next );
-        return VLC_SUCCESS;
+        const vlc_chroma_description_t *chroma =
+            vlc_fourcc_GetChromaDescription( p_filter->fmt_in.video.i_chroma );
+        return XRenderer( chroma->pixel_size )( p_filter, p_dst, p_next );
     }
     else
     {
@@ -194,3 +190,20 @@ int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
         return VLC_EGENERIC;
     }
 }
+
+static int RenderYadifSingle( filter_t *p_filter, picture_t *p_dst, picture_t *p_src )
+{
+    return RenderYadif( p_filter, p_dst, p_src, 0, 0 );
+}
+
+ordered_renderer_t YadifRenderer(unsigned pixel_size)
+{
+    VLC_UNUSED(pixel_size);
+    return RenderYadif;
+}
+
+single_pic_renderer_t YadifSingleRenderer(unsigned pixel_size)
+{
+    VLC_UNUSED(pixel_size);
+    return RenderYadifSingle;
+}
diff --git a/modules/video_filter/deinterlace/algo_yadif.h b/modules/video_filter/deinterlace/algo_yadif.h
index 483ca48f67..09cecf7eed 100644
--- a/modules/video_filter/deinterlace/algo_yadif.h
+++ b/modules/video_filter/deinterlace/algo_yadif.h
@@ -82,12 +82,11 @@ struct picture_t;
  * @retval VLC_EGENERIC Frame dropped; only occurs at the second frame after start.
  * @see Deinterlace()
  */
-int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src,
-                 int i_order, int i_field );
+ordered_renderer_t YadifRenderer(unsigned pixel_size);
 
 /**
  * Same as RenderYadif() but with no temporal references
  */
-int RenderYadifSingle( filter_t *p_filter, picture_t *p_dst, picture_t *p_src );
+single_pic_renderer_t YadifSingleRenderer(unsigned pixel_size);
 
 #endif
diff --git a/modules/video_filter/deinterlace/deinterlace.c b/modules/video_filter/deinterlace/deinterlace.c
index 9d33d434a9..8469a6ac8e 100644
--- a/modules/video_filter/deinterlace/deinterlace.c
+++ b/modules/video_filter/deinterlace/deinterlace.c
@@ -340,36 +340,35 @@ struct filter_mode_t
 {
     const char           *psz_mode;
     union {
-    int (*pf_render_ordered)(filter_t *, picture_t *p_dst, picture_t *p_pic,
-                             int order, int i_field);
-    int (*pf_render_single_pic)(filter_t *, picture_t *p_dst, picture_t *p_pic);
+    ordered_renderer_t (*pf_ordered_renderer)( unsigned pixel_size );
+    single_pic_renderer_t (*pf_single_pic_renderer)( unsigned pixel_size );
     };
     deinterlace_algo     settings;
     bool                 can_pack;         /**< can handle packed pixel */
     bool                 b_high_bit_depth; /**< can handle high bit depth */
 };
 static struct filter_mode_t filter_mode [] = {
-    { "discard", .pf_render_single_pic = RenderDiscard,
+    { "discard", .pf_single_pic_renderer = DiscardRenderer,
                  { false, false, false, true }, true, true },
-    { "bob", .pf_render_ordered = RenderBob,
+    { "bob", .pf_ordered_renderer = BobRenderer,
                  { true, false, false, false }, true, true },
-    { "progressive-scan", .pf_render_ordered = RenderBob,
+    { "progressive-scan", .pf_ordered_renderer = BobRenderer,
                  { true, false, false, false }, true, true },
-    { "linear", .pf_render_ordered = RenderLinear,
+    { "linear", .pf_ordered_renderer = LinearRenderer,
                  { true, false, false, false }, true, true },
-    { "mean", .pf_render_single_pic = RenderMean,
+    { "mean", .pf_single_pic_renderer = MeanRenderer,
                  { false, false, false, true }, true, true },
-    { "blend", .pf_render_single_pic = RenderBlend,
+    { "blend", .pf_single_pic_renderer = BlendRenderer,
                  { false, false, false, false }, true, true },
-    { "yadif", .pf_render_single_pic = RenderYadifSingle,
+    { "yadif", .pf_single_pic_renderer = YadifSingleRenderer,
                  { false, true, false, false }, false, true },
-    { "yadif2x", .pf_render_ordered = RenderYadif,
+    { "yadif2x", .pf_ordered_renderer = YadifRenderer,
                  { true, true, false, false }, false, true },
-    { "x", .pf_render_single_pic = RenderX,
+    { "x", .pf_single_pic_renderer = XRenderer,
                  { false, false, false, false }, false, false },
-    { "phosphor", .pf_render_ordered = RenderPhosphor,
+    { "phosphor", .pf_ordered_renderer = PhosphorRenderer,
                  { true, true, false, false }, false, false },
-    { "ivtc", .pf_render_single_pic = RenderIVTC,
+    { "ivtc", .pf_single_pic_renderer = IVTCRenderer,
                  { false, true, true, false }, false, false },
 };
 
@@ -407,10 +406,16 @@ static void SetFilterMethod( filter_t *p_filter, const char *mode, bool pack )
                 SetFilterMethod( p_filter, "blend", pack );
                 return;
             }
-
             msg_Dbg( p_filter, "using %s deinterlace method", mode );
+
+            const vlc_fourcc_t fourcc = p_filter->fmt_in.video.i_chroma;
+            const vlc_chroma_description_t *chroma =
+                vlc_fourcc_GetChromaDescription( fourcc );
+            assert( chroma->pixel_size < 2 );
+
             p_sys->context.settings = filter_mode[i].settings;
-            p_sys->context.pf_render_ordered = filter_mode[i].pf_render_ordered;
+            p_sys->context.pf_render_ordered =
+                filter_mode[i].pf_ordered_renderer( chroma->pixel_size );
             return;
         }
     }
diff --git a/modules/video_filter/deinterlace/deinterlace.h b/modules/video_filter/deinterlace/deinterlace.h
index 959cd6ae96..8d2342d02f 100644
--- a/modules/video_filter/deinterlace/deinterlace.h
+++ b/modules/video_filter/deinterlace/deinterlace.h
@@ -33,8 +33,13 @@ struct picture_t;
 struct vlc_object_t;
 
 #include <vlc_common.h>
+#include <vlc_fourcc.h>
 #include <vlc_mouse.h>
 
+typedef int (*single_pic_renderer_t)(filter_t *, picture_t *, picture_t *);
+typedef int (*ordered_renderer_t)(filter_t *, picture_t *, picture_t *,
+                                  int order, int field);
+
 /* Local algorithm headers */
 #include "algo_basic.h"
 #include "algo_x.h"
-- 
2.24.1



More information about the vlc-devel mailing list