diff options
author | Thomas Mundt <tmundt75@gmail.com> | 2017-04-20 23:33:39 +0200 |
---|---|---|
committer | James Almer <jamrial@gmail.com> | 2017-05-02 14:09:50 -0300 |
commit | 2da5bf4c2f4cb878bad794be2b76108afbbd899d (patch) | |
tree | 509008cb5a54e60151674017dae6c88bdcd9d6a7 /libavfilter/x86 | |
parent | 20da4135020fdf66f6060bb14926befbcc42a7dd (diff) | |
download | ffmpeg-2da5bf4c2f4cb878bad794be2b76108afbbd899d.tar.gz |
avfilter/interlace: add complex vertical low-pass filter
This complex (-1 2 6 2 -1) filter slightly less reduces interlace 'twitter' but better retain detail and subjective sharpness impression compared to the linear (1 2 1) filter.
Signed-off-by: Thomas Mundt <tmundt75@gmail.com>
Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavfilter/x86')
-rw-r--r-- | libavfilter/x86/vf_interlace.asm | 60 | ||||
-rw-r--r-- | libavfilter/x86/vf_interlace_init.c | 15 | ||||
-rw-r--r-- | libavfilter/x86/vf_tinterlace_init.c | 15 |
3 files changed, 84 insertions, 6 deletions
diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm index 8a0dd3bdea..c601fd7bf4 100644 --- a/libavfilter/x86/vf_interlace.asm +++ b/libavfilter/x86/vf_interlace.asm @@ -3,6 +3,7 @@ ;* ;* Copyright (C) 2014 Kieran Kunhya <kierank@obe.tv> ;* Copyright (c) 2014 Michael Niedermayer <michaelni@gmx.at> +;* Copyright (c) 2017 Thomas Mundt <tmundt75@gmail.com> ;* ;* This file is part of FFmpeg. ;* @@ -25,6 +26,8 @@ SECTION_RODATA +pw_4: times 8 dw 4 + SECTION .text %macro LOWPASS_LINE 0 @@ -56,6 +59,60 @@ cglobal lowpass_line, 5, 5, 7, dst, h, src, mref, pref add hq, 2*mmsize jl .loop REP_RET + +%endmacro + +%macro LOWPASS_LINE_COMPLEX 0 +cglobal lowpass_line_complex, 5, 5, 7, dst, h, src, mref, pref + pxor m6, m6 +.loop: + mova m0, [srcq+mrefq] + mova m2, [srcq+prefq] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m6 + punpcklbw m2, m6 + punpckhbw m1, m6 + punpckhbw m3, m6 + paddw m0, m2 + paddw m1, m3 + mova m2, [srcq+mrefq*2] + mova m4, [srcq+prefq*2] + mova m3, m2 + mova m5, m4 + punpcklbw m2, m6 + punpcklbw m4, m6 + punpckhbw m3, m6 + punpckhbw m5, m6 + paddw m2, m4 + paddw m3, m5 + mova m4, [srcq] + mova m5, m4 + punpcklbw m4, m6 + punpckhbw m5, m6 + paddw m0, m4 + paddw m1, m5 + psllw m0, 1 + psllw m1, 1 + psllw m4, 2 + psllw m5, 2 + paddw m0, m4 + paddw m1, m5 + paddw m0, [pw_4] + paddw m1, [pw_4] + psubusw m0, m2 + psubusw m1, m3 + psrlw m0, 3 + psrlw m1, 3 + packuswb m0, m1 + mova [dstq], m0 + + add dstq, mmsize + add srcq, mmsize + sub hd, mmsize + jg .loop +REP_RET + %endmacro INIT_XMM sse2 @@ -63,3 +120,6 @@ LOWPASS_LINE INIT_XMM avx LOWPASS_LINE + +INIT_XMM sse2 +LOWPASS_LINE_COMPLEX diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c index 7d8acd6143..c0f04dcd97 100644 --- a/libavfilter/x86/vf_interlace_init.c +++ b/libavfilter/x86/vf_interlace_init.c @@ -33,12 +33,21 @@ void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref); +void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, + ptrdiff_t mref, ptrdiff_t pref); + av_cold void ff_interlace_init_x86(InterlaceContext *s) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_SSE2(cpu_flags)) - s->lowpass_line = ff_lowpass_line_sse2; + if (EXTERNAL_SSE2(cpu_flags)) { + if (s->lowpass == VLPF_LIN) + s->lowpass_line = ff_lowpass_line_sse2; + else if (s->lowpass == VLPF_CMP) + s->lowpass_line = ff_lowpass_line_complex_sse2; + } if (EXTERNAL_AVX(cpu_flags)) - s->lowpass_line = ff_lowpass_line_avx; + if (s->lowpass == VLPF_LIN) + s->lowpass_line = ff_lowpass_line_avx; } diff --git a/libavfilter/x86/vf_tinterlace_init.c b/libavfilter/x86/vf_tinterlace_init.c index 175b5cff01..2b10e1b74c 100644 --- a/libavfilter/x86/vf_tinterlace_init.c +++ b/libavfilter/x86/vf_tinterlace_init.c @@ -34,12 +34,21 @@ void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp, ptrdiff_t mref, ptrdiff_t pref); +void ff_lowpass_line_complex_sse2(uint8_t *dstp, ptrdiff_t linesize, + const uint8_t *srcp, + ptrdiff_t mref, ptrdiff_t pref); + av_cold void ff_tinterlace_init_x86(TInterlaceContext *s) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_SSE2(cpu_flags)) - s->lowpass_line = ff_lowpass_line_sse2; + if (EXTERNAL_SSE2(cpu_flags)) { + if (!(s->flags & TINTERLACE_FLAG_CVLPF)) + s->lowpass_line = ff_lowpass_line_sse2; + else + s->lowpass_line = ff_lowpass_line_complex_sse2; + } if (EXTERNAL_AVX(cpu_flags)) - s->lowpass_line = ff_lowpass_line_avx; + if (!(s->flags & TINTERLACE_FLAG_CVLPF)) + s->lowpass_line = ff_lowpass_line_avx; } |