summaryrefslogtreecommitdiff
path: root/libavfilter/x86
diff options
context:
space:
mode:
authorThomas Mundt <tmundt75@gmail.com>2017-04-20 23:33:39 +0200
committerJames Almer <jamrial@gmail.com>2017-05-02 14:09:50 -0300
commit2da5bf4c2f4cb878bad794be2b76108afbbd899d (patch)
tree509008cb5a54e60151674017dae6c88bdcd9d6a7 /libavfilter/x86
parent20da4135020fdf66f6060bb14926befbcc42a7dd (diff)
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.asm60
-rw-r--r--libavfilter/x86/vf_interlace_init.c15
-rw-r--r--libavfilter/x86/vf_tinterlace_init.c15
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;
}