diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 57f5809acb..9a100cd665 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -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 diff --git a/libavfilter/bwdifdsp.c b/libavfilter/bwdifdsp.c new file mode 100644 index 0000000000..af217481a5 --- /dev/null +++ b/libavfilter/bwdifdsp.c @@ -0,0 +1,251 @@ +/* + * BobWeaver Deinterlacing Filter DSP functions + * Copyright (C) 2016 Thomas Mundt + * + * Based on YADIF (Yet Another Deinterlacing Filter) + * Copyright (C) 2006-2011 Michael Niedermayer + * 2010 James Darnley + * + * 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 +#include + +#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 +} diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index 282aef5698..137cd5ef13 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -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