@@ -214,7 +214,7 @@ OBJS-$(CONFIG_BM3D_FILTER) += vf_bm3d.o framesync.o
OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o boxblur.o
OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \
opencl/avgblur.o boxblur.o
-OBJS-$(CONFIG_BWDIF_FILTER) += vf_bwdif.o yadif_common.o
+OBJS-$(CONFIG_BWDIF_FILTER) += vf_bwdif.o bwdifdsp.o yadif_common.o
OBJS-$(CONFIG_BWDIF_CUDA_FILTER) += vf_bwdif_cuda.o vf_bwdif_cuda.ptx.o \
yadif_common.o
OBJS-$(CONFIG_BWDIF_VULKAN_FILTER) += vf_bwdif_vulkan.o yadif_common.o vulkan.o vulkan_filter.o
new file mode 100644
@@ -0,0 +1,251 @@
+/*
+ * BobWeaver Deinterlacing Filter DSP functions
+ * Copyright (C) 2016 Thomas Mundt <loudmax@yahoo.de>
+ *
+ * Based on YADIF (Yet Another Deinterlacing Filter)
+ * Copyright (C) 2006-2011 Michael Niedermayer <michaelni@gmx.at>
+ * 2010 James Darnley <james.darnley@gmail.com>
+ *
+ * With use of Weston 3 Field Deinterlacing Filter algorithm
+ * Copyright (C) 2012 British Broadcasting Corporation, All Rights Reserved
+ * Author of de-interlace algorithm: Jim Easterbrook for BBC R&D
+ * Based on the process described by Martin Weston for BBC R&D
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "config.h"
+
+#include "bwdifdsp.h"
+#include "libavutil/attributes.h"
+#include "libavutil/common.h"
+#include "libavutil/macros.h"
+
+/*
+ * Filter coefficients coef_lf and coef_hf taken from BBC PH-2071 (Weston 3 Field Deinterlacer).
+ * Used when there is spatial and temporal interpolation.
+ * Filter coefficients coef_sp are used when there is spatial interpolation only.
+ * Adjusted for matching visual sharpness impression of spatial and temporal interpolation.
+ */
+static const uint16_t coef_lf[2] = { 4309, 213 };
+static const uint16_t coef_hf[3] = { 5570, 3801, 1016 };
+static const uint16_t coef_sp[2] = { 5077, 981 };
+
+
+#define FILTER_INTRA() \
+ for (x = 0; x < w; x++) { \
+ interpol = (coef_sp[0] * (cur[mrefs] + cur[prefs]) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
+ dst[0] = av_clip(interpol, 0, clip_max); \
+ \
+ dst++; \
+ cur++; \
+ }
+
+#define FILTER1() \
+ for (x = 0; x < w; x++) { \
+ int c = cur[mrefs]; \
+ int d = (prev2[0] + next2[0]) >> 1; \
+ int e = cur[prefs]; \
+ int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
+ int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e)) >> 1; \
+ int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e)) >> 1; \
+ int diff = FFMAX3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); \
+ \
+ if (!diff) { \
+ dst[0] = d; \
+ } else {
+
+#define SPAT_CHECK() \
+ int b = ((prev2[mrefs2] + next2[mrefs2]) >> 1) - c; \
+ int f = ((prev2[prefs2] + next2[prefs2]) >> 1) - e; \
+ int dc = d - c; \
+ int de = d - e; \
+ int max = FFMAX3(de, dc, FFMIN(b, f)); \
+ int min = FFMIN3(de, dc, FFMAX(b, f)); \
+ diff = FFMAX3(diff, min, -max);
+
+#define FILTER_LINE() \
+ SPAT_CHECK() \
+ if (FFABS(c - e) > temporal_diff0) { \
+ interpol = (((coef_hf[0] * (prev2[0] + next2[0]) \
+ - coef_hf[1] * (prev2[mrefs2] + next2[mrefs2] + prev2[prefs2] + next2[prefs2]) \
+ + coef_hf[2] * (prev2[mrefs4] + next2[mrefs4] + prev2[prefs4] + next2[prefs4])) >> 2) \
+ + coef_lf[0] * (c + e) - coef_lf[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
+ } else { \
+ interpol = (coef_sp[0] * (c + e) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
+ }
+
+#define FILTER_EDGE() \
+ if (spat) { \
+ SPAT_CHECK() \
+ } \
+ interpol = (c + e) >> 1;
+
+#define FILTER2() \
+ if (interpol > d + diff) \
+ interpol = d + diff; \
+ else if (interpol < d - diff) \
+ interpol = d - diff; \
+ \
+ dst[0] = av_clip(interpol, 0, clip_max); \
+ } \
+ \
+ dst++; \
+ cur++; \
+ prev++; \
+ next++; \
+ prev2++; \
+ next2++; \
+ }
+
+void ff_bwdif_filter_intra_c(void *dst1, void *cur1, int w, int prefs, int mrefs,
+ int prefs3, int mrefs3, int parity, int clip_max)
+{
+ uint8_t *dst = dst1;
+ uint8_t *cur = cur1;
+ int interpol, x;
+
+ FILTER_INTRA()
+}
+
+void ff_bwdif_filter_line_c(void *dst1, void *prev1, void *cur1, void *next1,
+ int w, int prefs, int mrefs, int prefs2, int mrefs2,
+ int prefs3, int mrefs3, int prefs4, int mrefs4,
+ int parity, int clip_max)
+{
+ uint8_t *dst = dst1;
+ uint8_t *prev = prev1;
+ uint8_t *cur = cur1;
+ uint8_t *next = next1;
+ uint8_t *prev2 = parity ? prev : cur ;
+ uint8_t *next2 = parity ? cur : next;
+ int interpol, x;
+
+ FILTER1()
+ FILTER_LINE()
+ FILTER2()
+}
+
+#define NEXT_LINE()\
+ dst += d_stride; \
+ prev += prefs; \
+ cur += prefs; \
+ next += prefs;
+
+void ff_bwdif_filter_line3_c(void * dst1, int d_stride,
+ const void * prev1, const void * cur1, const void * next1, int s_stride,
+ int w, int parity, int clip_max)
+{
+ const int prefs = s_stride;
+ uint8_t * dst = dst1;
+ const uint8_t * prev = prev1;
+ const uint8_t * cur = cur1;
+ const uint8_t * next = next1;
+
+ ff_bwdif_filter_line_c(dst, (void*)prev, (void*)cur, (void*)next, w,
+ prefs, -prefs, prefs * 2, - prefs * 2, prefs * 3, -prefs * 3, prefs * 4, -prefs * 4, parity, clip_max);
+ NEXT_LINE();
+ memcpy(dst, cur, w);
+ NEXT_LINE();
+ ff_bwdif_filter_line_c(dst, (void*)prev, (void*)cur, (void*)next, w,
+ prefs, -prefs, prefs * 2, - prefs * 2, prefs * 3, -prefs * 3, prefs * 4, -prefs * 4, parity, clip_max);
+}
+
+void ff_bwdif_filter_edge_c(void *dst1, void *prev1, void *cur1, void *next1,
+ int w, int prefs, int mrefs, int prefs2, int mrefs2,
+ int parity, int clip_max, int spat)
+{
+ uint8_t *dst = dst1;
+ uint8_t *prev = prev1;
+ uint8_t *cur = cur1;
+ uint8_t *next = next1;
+ uint8_t *prev2 = parity ? prev : cur ;
+ uint8_t *next2 = parity ? cur : next;
+ int interpol, x;
+
+ FILTER1()
+ FILTER_EDGE()
+ FILTER2()
+}
+
+static void filter_intra_16bit(void *dst1, void *cur1, int w, int prefs, int mrefs,
+ int prefs3, int mrefs3, int parity, int clip_max)
+{
+ uint16_t *dst = dst1;
+ uint16_t *cur = cur1;
+ int interpol, x;
+
+ FILTER_INTRA()
+}
+
+static void filter_line_c_16bit(void *dst1, void *prev1, void *cur1, void *next1,
+ int w, int prefs, int mrefs, int prefs2, int mrefs2,
+ int prefs3, int mrefs3, int prefs4, int mrefs4,
+ int parity, int clip_max)
+{
+ uint16_t *dst = dst1;
+ uint16_t *prev = prev1;
+ uint16_t *cur = cur1;
+ uint16_t *next = next1;
+ uint16_t *prev2 = parity ? prev : cur ;
+ uint16_t *next2 = parity ? cur : next;
+ int interpol, x;
+
+ FILTER1()
+ FILTER_LINE()
+ FILTER2()
+}
+
+static void filter_edge_16bit(void *dst1, void *prev1, void *cur1, void *next1,
+ int w, int prefs, int mrefs, int prefs2, int mrefs2,
+ int parity, int clip_max, int spat)
+{
+ uint16_t *dst = dst1;
+ uint16_t *prev = prev1;
+ uint16_t *cur = cur1;
+ uint16_t *next = next1;
+ uint16_t *prev2 = parity ? prev : cur ;
+ uint16_t *next2 = parity ? cur : next;
+ int interpol, x;
+
+ FILTER1()
+ FILTER_EDGE()
+ FILTER2()
+}
+
+av_cold void ff_bwdif_init_filter_line(BWDIFDSPContext *s, int bit_depth)
+{
+ s->filter_line3 = 0;
+ if (bit_depth > 8) {
+ s->filter_intra = filter_intra_16bit;
+ s->filter_line = filter_line_c_16bit;
+ s->filter_edge = filter_edge_16bit;
+ } else {
+ s->filter_intra = ff_bwdif_filter_intra_c;
+ s->filter_line = ff_bwdif_filter_line_c;
+ s->filter_edge = ff_bwdif_filter_edge_c;
+ }
+
+#if ARCH_X86
+ ff_bwdif_init_x86(s, bit_depth);
+#elif ARCH_AARCH64
+ ff_bwdif_init_aarch64(s, bit_depth);
+#endif
+}
@@ -37,16 +37,6 @@
#include "internal.h"
#include "yadif.h"
-/*
- * Filter coefficients coef_lf and coef_hf taken from BBC PH-2071 (Weston 3 Field Deinterlacer).
- * Used when there is spatial and temporal interpolation.
- * Filter coefficients coef_sp are used when there is spatial interpolation only.
- * Adjusted for matching visual sharpness impression of spatial and temporal interpolation.
- */
-static const uint16_t coef_lf[2] = { 4309, 213 };
-static const uint16_t coef_hf[3] = { 5570, 3801, 1016 };
-static const uint16_t coef_sp[2] = { 5077, 981 };
-
typedef struct BWDIFContext {
YADIFContext yadif;
BWDIFDSPContext dsp;
@@ -60,187 +50,6 @@ typedef struct ThreadData {
int tff;
} ThreadData;
-#define FILTER_INTRA() \
- for (x = 0; x < w; x++) { \
- interpol = (coef_sp[0] * (cur[mrefs] + cur[prefs]) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
- dst[0] = av_clip(interpol, 0, clip_max); \
- \
- dst++; \
- cur++; \
- }
-
-#define FILTER1() \
- for (x = 0; x < w; x++) { \
- int c = cur[mrefs]; \
- int d = (prev2[0] + next2[0]) >> 1; \
- int e = cur[prefs]; \
- int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
- int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e)) >> 1; \
- int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e)) >> 1; \
- int diff = FFMAX3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); \
- \
- if (!diff) { \
- dst[0] = d; \
- } else {
-
-#define SPAT_CHECK() \
- int b = ((prev2[mrefs2] + next2[mrefs2]) >> 1) - c; \
- int f = ((prev2[prefs2] + next2[prefs2]) >> 1) - e; \
- int dc = d - c; \
- int de = d - e; \
- int max = FFMAX3(de, dc, FFMIN(b, f)); \
- int min = FFMIN3(de, dc, FFMAX(b, f)); \
- diff = FFMAX3(diff, min, -max);
-
-#define FILTER_LINE() \
- SPAT_CHECK() \
- if (FFABS(c - e) > temporal_diff0) { \
- interpol = (((coef_hf[0] * (prev2[0] + next2[0]) \
- - coef_hf[1] * (prev2[mrefs2] + next2[mrefs2] + prev2[prefs2] + next2[prefs2]) \
- + coef_hf[2] * (prev2[mrefs4] + next2[mrefs4] + prev2[prefs4] + next2[prefs4])) >> 2) \
- + coef_lf[0] * (c + e) - coef_lf[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
- } else { \
- interpol = (coef_sp[0] * (c + e) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
- }
-
-#define FILTER_EDGE() \
- if (spat) { \
- SPAT_CHECK() \
- } \
- interpol = (c + e) >> 1;
-
-#define FILTER2() \
- if (interpol > d + diff) \
- interpol = d + diff; \
- else if (interpol < d - diff) \
- interpol = d - diff; \
- \
- dst[0] = av_clip(interpol, 0, clip_max); \
- } \
- \
- dst++; \
- cur++; \
- prev++; \
- next++; \
- prev2++; \
- next2++; \
- }
-
-void ff_bwdif_filter_intra_c(void *dst1, void *cur1, int w, int prefs, int mrefs,
- int prefs3, int mrefs3, int parity, int clip_max)
-{
- uint8_t *dst = dst1;
- uint8_t *cur = cur1;
- int interpol, x;
-
- FILTER_INTRA()
-}
-
-void ff_bwdif_filter_line_c(void *dst1, void *prev1, void *cur1, void *next1,
- int w, int prefs, int mrefs, int prefs2, int mrefs2,
- int prefs3, int mrefs3, int prefs4, int mrefs4,
- int parity, int clip_max)
-{
- uint8_t *dst = dst1;
- uint8_t *prev = prev1;
- uint8_t *cur = cur1;
- uint8_t *next = next1;
- uint8_t *prev2 = parity ? prev : cur ;
- uint8_t *next2 = parity ? cur : next;
- int interpol, x;
-
- FILTER1()
- FILTER_LINE()
- FILTER2()
-}
-
-#define NEXT_LINE()\
- dst += d_stride; \
- prev += prefs; \
- cur += prefs; \
- next += prefs;
-
-void ff_bwdif_filter_line3_c(void * dst1, int d_stride,
- const void * prev1, const void * cur1, const void * next1, int s_stride,
- int w, int parity, int clip_max)
-{
- const int prefs = s_stride;
- uint8_t * dst = dst1;
- const uint8_t * prev = prev1;
- const uint8_t * cur = cur1;
- const uint8_t * next = next1;
-
- ff_bwdif_filter_line_c(dst, (void*)prev, (void*)cur, (void*)next, w,
- prefs, -prefs, prefs * 2, - prefs * 2, prefs * 3, -prefs * 3, prefs * 4, -prefs * 4, parity, clip_max);
- NEXT_LINE();
- memcpy(dst, cur, w);
- NEXT_LINE();
- ff_bwdif_filter_line_c(dst, (void*)prev, (void*)cur, (void*)next, w,
- prefs, -prefs, prefs * 2, - prefs * 2, prefs * 3, -prefs * 3, prefs * 4, -prefs * 4, parity, clip_max);
-}
-
-void ff_bwdif_filter_edge_c(void *dst1, void *prev1, void *cur1, void *next1,
- int w, int prefs, int mrefs, int prefs2, int mrefs2,
- int parity, int clip_max, int spat)
-{
- uint8_t *dst = dst1;
- uint8_t *prev = prev1;
- uint8_t *cur = cur1;
- uint8_t *next = next1;
- uint8_t *prev2 = parity ? prev : cur ;
- uint8_t *next2 = parity ? cur : next;
- int interpol, x;
-
- FILTER1()
- FILTER_EDGE()
- FILTER2()
-}
-
-static void filter_intra_16bit(void *dst1, void *cur1, int w, int prefs, int mrefs,
- int prefs3, int mrefs3, int parity, int clip_max)
-{
- uint16_t *dst = dst1;
- uint16_t *cur = cur1;
- int interpol, x;
-
- FILTER_INTRA()
-}
-
-static void filter_line_c_16bit(void *dst1, void *prev1, void *cur1, void *next1,
- int w, int prefs, int mrefs, int prefs2, int mrefs2,
- int prefs3, int mrefs3, int prefs4, int mrefs4,
- int parity, int clip_max)
-{
- uint16_t *dst = dst1;
- uint16_t *prev = prev1;
- uint16_t *cur = cur1;
- uint16_t *next = next1;
- uint16_t *prev2 = parity ? prev : cur ;
- uint16_t *next2 = parity ? cur : next;
- int interpol, x;
-
- FILTER1()
- FILTER_LINE()
- FILTER2()
-}
-
-static void filter_edge_16bit(void *dst1, void *prev1, void *cur1, void *next1,
- int w, int prefs, int mrefs, int prefs2, int mrefs2,
- int parity, int clip_max, int spat)
-{
- uint16_t *dst = dst1;
- uint16_t *prev = prev1;
- uint16_t *cur = cur1;
- uint16_t *next = next1;
- uint16_t *prev2 = parity ? prev : cur ;
- uint16_t *next2 = parity ? cur : next;
- int interpol, x;
-
- FILTER1()
- FILTER_EDGE()
- FILTER2()
-}
-
// Round job start line down to multiple of 4 so that if filter_line3 exists
// and the frame is a multiple of 4 high then filter_line will never be called
static inline int job_start(const int jobnr, const int nb_jobs, const int h)
@@ -394,26 +203,6 @@ static int config_props(AVFilterLink *link)
return 0;
}
-av_cold void ff_bwdif_init_filter_line(BWDIFDSPContext *s, int bit_depth)
-{
- s->filter_line3 = 0;
- if (bit_depth > 8) {
- s->filter_intra = filter_intra_16bit;
- s->filter_line = filter_line_c_16bit;
- s->filter_edge = filter_edge_16bit;
- } else {
- s->filter_intra = ff_bwdif_filter_intra_c;
- s->filter_line = ff_bwdif_filter_line_c;
- s->filter_edge = ff_bwdif_filter_edge_c;
- }
-
-#if ARCH_X86
- ff_bwdif_init_x86(s, bit_depth);
-#elif ARCH_AARCH64
- ff_bwdif_init_aarch64(s, bit_depth);
-#endif
-}
-
#define OFFSET(x) offsetof(YADIFContext, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
Otherwise checkasm/vf_bwdif.c pulls in vf_bwdif.c and then all of libavfilter. Besides being bad size-wise this also has the downside that it pulls in avpriv_(cga|vga16)_font from libavutil which are marked as being imported from another library when building libavfilter as a DLL and this breaks checkasm because it links both lavfi and lavu statically. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> --- libavfilter/Makefile | 2 +- libavfilter/bwdifdsp.c | 251 +++++++++++++++++++++++++++++++++++++++++ libavfilter/vf_bwdif.c | 211 ---------------------------------- 3 files changed, 252 insertions(+), 212 deletions(-) create mode 100644 libavfilter/bwdifdsp.c