From d80c53eedd398fd580c16d6c6ec42bd1cff6260f Mon Sep 17 00:00:00 2001 From: Shaun Loo Date: Sun, 13 Aug 2023 15:17:41 -0500 Subject: [PATCH 1/3] vvc_deblock: add checkasm for vvc deblocker Signed-off-by: Shaun Loo --- tests/checkasm/Makefile | 2 +- tests/checkasm/checkasm.c | 1 + tests/checkasm/checkasm.h | 1 + tests/checkasm/vvc_deblock.c | 124 +++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 tests/checkasm/vvc_deblock.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 9a2105da3b3..2c5c00904f3 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -35,7 +35,7 @@ AVCODECOBJS-$(CONFIG_V210_DECODER) += v210dec.o AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o AVCODECOBJS-$(CONFIG_VORBIS_DECODER) += vorbisdsp.o AVCODECOBJS-$(CONFIG_VP9_DECODER) += vp9dsp.o -AVCODECOBJS-$(CONFIG_VVC_DECODER) += vvc_alf.o vvc_sao.o vvc_mc.o +AVCODECOBJS-$(CONFIG_VVC_DECODER) += vvc_alf.o vvc_sao.o vvc_mc.o vvc_deblock.o CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes) diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index c4f80ece513..243c355ea87 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -179,6 +179,7 @@ static const struct { { "vvc_alf", checkasm_check_vvc_alf }, { "vvc_sao", checkasm_check_vvc_sao }, { "vvc_mc", checkasm_check_vvc_mc }, + { "vvc_deblock", checkasm_check_vvc_deblock }, #endif #endif #if CONFIG_AVFILTER diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index a82e157a4ea..12a184bb1b6 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -97,6 +97,7 @@ void checkasm_check_vorbisdsp(void); void checkasm_check_vvc_alf(void); void checkasm_check_vvc_sao(void); void checkasm_check_vvc_mc(void); +void checkasm_check_vvc_deblock(void); struct CheckasmPerf; diff --git a/tests/checkasm/vvc_deblock.c b/tests/checkasm/vvc_deblock.c new file mode 100644 index 00000000000..853e4a19b37 --- /dev/null +++ b/tests/checkasm/vvc_deblock.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2023 Shaun Loo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + +#include "libavcodec/avcodec.h" + +#include "libavcodec/vvc/vvcdsp.h" +#include "libavcodec/vvc/vvcdec.h" + +#include "checkasm.h" + +static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define BUF_STRIDE (8 * 2) +#define BUF_LINES (8) +#define BUF_OFFSET (BUF_STRIDE * BUF_LINES) +#define BUF_SIZE (BUF_STRIDE * BUF_LINES + BUF_OFFSET * 2) + +#define randomize_buffers(buf0, buf1, size) \ + do { \ + uint32_t mask = pixel_mask[(bit_depth - 8) >> 1]; \ + int k; \ + for (k = 0; k < size; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf0 + k, r); \ + AV_WN32A(buf1 + k, r); \ + } \ + } while (0) + +static void check_deblock_chroma(VVCDSPContext *h, int bit_depth) +{ + // To-do: figure out values to test this properly + int beta = 0; + int32_t tc = 0; + // no_p and no_q must be 0 for the simpler asm version + uint8_t no_p = 0; + uint8_t no_q = 0; + // Shift == 0 for now, we're only writing the most simple + // version + int shift = 0; + // Assembly version is only called (for now) if max_len_p != 3 && max_len_q != 3, + // labelled as "weak." HEVC has a similar hack. max_len_p == 0 || max_len_q == 0 + // will trigger immediate exit, so 1 will have to do. + int max_len_p = 1; + int max_len_q = 1; + + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, + int shift,uint8_t no_p, uint8_t no_q, int max_len_p, int max_len_q); + if (check_func(h->lf.filter_chroma[0], "vvc_h_loop_filter_chroma%d weak", bit_depth)) { + for (int i = 0; i < 4; i++) { + randomize_buffers(buf0, buf1, BUF_SIZE); + // Largest betatable value is 88, see vvc_filter.c + beta = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + tc = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + + call_ref(buf0 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + call_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + if (memcmp(buf0, buf1, BUF_SIZE)) + fail(); + } + bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, no_p, no_q, shift, max_len_p, max_len_q); + } + + if (check_func(h->lf.filter_chroma[1], "vvc_v_loop_filter_chroma%d", bit_depth)) { + int diff = 0; + max_len_p = 2; + max_len_q = 2; + for (int i = 0; i < 4; i++) { + randomize_buffers(buf0, buf1, BUF_SIZE); + // Largest betatable value is 88, see vvc_filter.c + beta = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + tc = (rnd() & 63) + (rnd() & 15) + (rnd() & 7) + (rnd() & 3); + + call_ref(buf0 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + call_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, shift, no_p, no_q, max_len_p, max_len_q); + if (diff = (memcmp(buf0, buf1, BUF_SIZE))) { + { + printf("diff: %d\n", diff); + fail(); + } + + } + + } + bench_new(buf1 + BUF_OFFSET, BUF_STRIDE, beta, tc, no_p, no_q, shift, max_len_p, max_len_q); + } +} + +void checkasm_check_vvc_deblock(void) +{ + int bit_depth; + + for (bit_depth = 8; bit_depth <= 12; bit_depth += 2) { + VVCDSPContext h; + ff_vvc_dsp_init(&h, bit_depth); + check_deblock_chroma(&h, bit_depth); + } + report("chroma"); +} From fe34cb470cb7d46cc68539456a609024df5638b7 Mon Sep 17 00:00:00 2001 From: Shaun Loo Date: Mon, 21 Aug 2023 20:52:26 -0500 Subject: [PATCH 2/3] vvc_deblock: add simple AVX2-accelerated chroma deblocker Signed-off-by: Shaun Loo --- libavcodec/vvc/vvc_filter.c | 19 +- libavcodec/vvc/vvc_filter_template.c | 2 + libavcodec/vvc/vvcdsp.h | 2 + libavcodec/x86/Makefile | 3 +- libavcodec/x86/vvc_deblock.asm | 402 +++++++++++++++++++++++++++ libavcodec/x86/vvcdsp_init.c | 18 ++ 6 files changed, 441 insertions(+), 5 deletions(-) create mode 100644 libavcodec/x86/vvc_deblock.asm diff --git a/libavcodec/vvc/vvc_filter.c b/libavcodec/vvc/vvc_filter.c index ab6d75d06f7..12b39d5a42b 100644 --- a/libavcodec/vvc/vvc_filter.c +++ b/libavcodec/vvc/vvc_filter.c @@ -921,8 +921,13 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0) fc->vvcdsp.lf.filter_luma[1](src, fc->frame->linesize[c_idx], beta, tc, no_p, no_q, max_len_p, max_len_q, 0); } else { - fc->vvcdsp.lf.filter_chroma[1](src, - fc->frame->linesize[c_idx], beta, tc, no_p, no_q, vs, max_len_p, max_len_q); + if (vs || (no_p || no_q) || (max_len_p == 3 || max_len_q == 3) || (!max_len_p || !max_len_q)) { + fc->vvcdsp.lf.filter_chroma_c[1](src, + fc->frame->linesize[c_idx], beta, tc, no_p, no_q, vs, max_len_p, max_len_q); + } else { + fc->vvcdsp.lf.filter_chroma_c[1](src, + fc->frame->linesize[c_idx], beta, tc, no_p, no_q, vs, max_len_p, max_len_q); + } } } } @@ -990,8 +995,14 @@ void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0) fc->vvcdsp.lf.filter_luma[0](src, fc->frame->linesize[c_idx], beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge); } else { - fc->vvcdsp.lf.filter_chroma[0](src, fc->frame->linesize[c_idx], beta, - tc, no_p, no_q, hs, max_len_p, max_len_q); + if (hs || (no_p || no_q) || (!max_len_p || !max_len_q) || (max_len_p == 3 || max_len_q == 3)) { + fc->vvcdsp.lf.filter_chroma_c[0](src, fc->frame->linesize[c_idx], beta, + tc, no_p, no_q, hs, max_len_p, max_len_q); + } else { + fc->vvcdsp.lf.filter_chroma[0](src, fc->frame->linesize[c_idx], beta, + tc, no_p, no_q, hs, max_len_p, max_len_q); + } + } } } diff --git a/libavcodec/vvc/vvc_filter_template.c b/libavcodec/vvc/vvc_filter_template.c index 2ce3e93ff1e..6cea412ae51 100644 --- a/libavcodec/vvc/vvc_filter_template.c +++ b/libavcodec/vvc/vvc_filter_template.c @@ -1066,6 +1066,8 @@ static void FUNC(ff_vvc_lf_dsp_init)(VVCLFDSPContext *const lf) lf->filter_luma[1] = FUNC(vvc_v_loop_filter_luma); lf->filter_chroma[0] = FUNC(vvc_h_loop_filter_chroma); lf->filter_chroma[1] = FUNC(vvc_v_loop_filter_chroma); + lf->filter_chroma_c[0] = FUNC(vvc_h_loop_filter_chroma); + lf->filter_chroma_c[1] = FUNC(vvc_v_loop_filter_chroma); } static void FUNC(ff_vvc_sao_dsp_init)(VVCSAODSPContext *const sao) diff --git a/libavcodec/vvc/vvcdsp.h b/libavcodec/vvc/vvcdsp.h index cb1c7c33121..0ad1b41ec86 100644 --- a/libavcodec/vvc/vvcdsp.h +++ b/libavcodec/vvc/vvcdsp.h @@ -130,6 +130,8 @@ typedef struct VVCLFDSPContext { uint8_t no_p, uint8_t no_q, uint8_t max_len_p, uint8_t max_len_q, int hor_ctu_edge); void (*filter_chroma[2 /* h, v */])(uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, int max_len_p, int max_len_q); + void (*filter_chroma_c[2 /* h, v */])(uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, + uint8_t no_p, uint8_t no_q, int shift, int max_len_p, int max_len_q); } VVCLFDSPContext; struct SAOParams; diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index 71a1cdf63e7..84fe4cfddd3 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -206,5 +206,6 @@ X86ASM-OBJS-$(CONFIG_VP9_DECODER) += x86/vp9intrapred.o \ X86ASM-OBJS-$(CONFIG_VVC_DECODER) += x86/vvc_alf.o \ x86/vvc_sao.o \ x86/vvc_sao_10bit.o \ - x86/vvc_mc.o + x86/vvc_mc.o \ + x86/vvc_deblock.o X86ASM-OBJS-$(CONFIG_WEBP_DECODER) += x86/vp8dsp.o diff --git a/libavcodec/x86/vvc_deblock.asm b/libavcodec/x86/vvc_deblock.asm new file mode 100644 index 00000000000..58153bc71f7 --- /dev/null +++ b/libavcodec/x86/vvc_deblock.asm @@ -0,0 +1,402 @@ +;***************************************************************************** +;* AVX2-optimized VVC deblocking code +;***************************************************************************** +;* Copyright (C) 2013 VTT +;* Copyright (C) 2023 Shaun Loo +;* +;* Authors: Seppo Tomperi +;* Shaun Loo +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pw_1023 +%define pw_pixel_max_10 pw_1023 +pw_pixel_max_12: times 8 dw ((1 << 12)-1) +pw_m2: times 8 dw -2 +pd_1 : times 4 dd 1 +pw_2 : times 8 dw 2 +pd_2 : times 4 dd 2 + +cextern pw_4 +cextern pw_8 +cextern pw_m1 + +SECTION .text +INIT_XMM avx2 + +; in: 8 rows of 4 bytes in %0..%8 +; out: 4 rows of 8 words in m0..m3 +%macro TRANSPOSE4x8B_LOAD 8 + movd m0, %1 + movd m2, %2 + movd m1, %3 + movd m3, %4 + + punpcklbw m0, m2 + punpcklbw m1, m3 + punpcklwd m0, m1 + + movd m4, %5 + movd m6, %6 + movd m5, %7 + movd m3, %8 + + punpcklbw m4, m6 + punpcklbw m5, m3 + punpcklwd m4, m5 + + punpckhdq m2, m0, m4 + punpckldq m0, m4 + + pxor m5, m5 + punpckhbw m1, m0, m5 + punpcklbw m0, m5 + punpckhbw m3, m2, m5 + punpcklbw m2, m5 +%endmacro + +; in: 4 rows of 8 words in m0..m3 +; out: 8 rows of 4 bytes in %1..%8 +%macro TRANSPOSE8x4B_STORE 8 + packuswb m0, m2 + packuswb m1, m3 + SBUTTERFLY bw, 0, 1, 2 + SBUTTERFLY wd, 0, 1, 2 + + movd %1, m0 + pshufd m0, m0, 0x39 + movd %2, m0 + pshufd m0, m0, 0x39 + movd %3, m0 + pshufd m0, m0, 0x39 + movd %4, m0 + + movd %5, m1 + pshufd m1, m1, 0x39 + movd %6, m1 + pshufd m1, m1, 0x39 + movd %7, m1 + pshufd m1, m1, 0x39 + movd %8, m1 +%endmacro + +; in: 8 rows of 4 words in %4..%11 +; out: 4 rows of 8 words in m0..m3 +%macro TRANSPOSE4x8W_LOAD 8 + movq m0, %1 + movq m2, %2 + movq m1, %3 + movq m3, %4 + + punpcklwd m0, m2 + punpcklwd m1, m3 + punpckhdq m2, m0, m1 + punpckldq m0, m1 + + movq m4, %5 + movq m6, %6 + movq m5, %7 + movq m3, %8 + + punpcklwd m4, m6 + punpcklwd m5, m3 + punpckhdq m6, m4, m5 + punpckldq m4, m5 + + punpckhqdq m1, m0, m4 + punpcklqdq m0, m4 + punpckhqdq m3, m2, m6 + punpcklqdq m2, m6 + +%endmacro + +; in: 4 rows of 8 words in m0..m3 +; out: 8 rows of 4 words in %1..%8 +%macro TRANSPOSE8x4W_STORE 9 + TRANSPOSE4x4W 0, 1, 2, 3, 4 + + pxor m5, m5; zeros reg + CLIPW m0, m5, %9 + CLIPW m1, m5, %9 + CLIPW m2, m5, %9 + CLIPW m3, m5, %9 + + movq %1, m0 + movhps %2, m0 + movq %3, m1 + movhps %4, m1 + movq %5, m2 + movhps %6, m2 + movq %7, m3 + movhps %8, m3 +%endmacro + +; in: 8 rows of 8 bytes in %1..%8 +; out: 8 rows of 8 words in m0..m7 +%macro TRANSPOSE8x8B_LOAD 8 + movq m7, %1 + movq m2, %2 + movq m1, %3 + movq m3, %4 + + punpcklbw m7, m2 + punpcklbw m1, m3 + punpcklwd m3, m7, m1 + punpckhwd m7, m1 + + movq m4, %5 + movq m6, %6 + movq m5, %7 + movq m15, %8 + + punpcklbw m4, m6 + punpcklbw m5, m15 + punpcklwd m9, m4, m5 + punpckhwd m4, m5 + + punpckldq m1, m3, m9; 0, 1 + punpckhdq m3, m9; 2, 3 + + punpckldq m5, m7, m4; 4, 5 + punpckhdq m7, m4; 6, 7 + + pxor m13, m13 + + punpcklbw m0, m1, m13; 0 in 16 bit + punpckhbw m1, m13; 1 in 16 bit + + punpcklbw m2, m3, m13; 2 + punpckhbw m3, m13; 3 + + punpcklbw m4, m5, m13; 4 + punpckhbw m5, m13; 5 + + punpcklbw m6, m7, m13; 6 + punpckhbw m7, m13; 7 +%endmacro + +; in: 8 rows of 8 words in m0..m8 +; out: 8 rows of 8 bytes in %1..%8 +%macro TRANSPOSE8x8B_STORE 8 + packuswb m0, m4 + packuswb m1, m5 + packuswb m2, m6 + packuswb m3, m7 + TRANSPOSE2x4x4B 0, 1, 2, 3, 4 + + movq %1, m0 + movhps %2, m0 + movq %3, m1 + movhps %4, m1 + movq %5, m2 + movhps %6, m2 + movq %7, m3 + movhps %8, m3 +%endmacro + +; in: 8 rows of 8 words in %1..%8 +; out: 8 rows of 8 words in m0..m7 +%macro TRANSPOSE8x8W_LOAD 8 + movdqu m0, %1 + movdqu m1, %2 + movdqu m2, %3 + movdqu m3, %4 + movdqu m4, %5 + movdqu m5, %6 + movdqu m6, %7 + movdqu m7, %8 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 +%endmacro + +; in: 8 rows of 8 words in m0..m8 +; out: 8 rows of 8 words in %1..%8 +%macro TRANSPOSE8x8W_STORE 9 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 + + pxor m8, m8 + CLIPW m0, m8, %9 + CLIPW m1, m8, %9 + CLIPW m2, m8, %9 + CLIPW m3, m8, %9 + CLIPW m4, m8, %9 + CLIPW m5, m8, %9 + CLIPW m6, m8, %9 + CLIPW m7, m8, %9 + + movdqu %1, m0 + movdqu %2, m1 + movdqu %3, m2 + movdqu %4, m3 + movdqu %5, m4 + movdqu %6, m5 + movdqu %7, m6 + movdqu %8, m7 +%endmacro + +; in: %2 clobbered +; out: %1 +; mask in m11 +; clobbers m10 +%macro MASKED_COPY 2 + pand %2, m11 ; and mask + pandn m10, m11, %1; and -mask + por %2, m10 + mova %1, %2 +%endmacro + +; in: %2 clobbered +; out: %1 +; mask in %3, will be clobbered +%macro MASKED_COPY2 3 + pand %2, %3 ; and mask + pandn %3, %1; and -mask + por %2, %3 + mova %1, %2 +%endmacro + +ALIGN 16 +; input in m0 ... m3 and tcs in r2. Output in m1 and m2 +%macro CHROMA_DEBLOCK_BODY 1 + psubw m4, m2, m1; q0 - p0 + psubw m5, m0, m3; p1 - q1 + psllw m4, 2; << 2 + paddw m5, m4; + + ;tc calculations + movq m6, tcq; tc + punpcklwd m6, m6 + pshufd m6, m6, 0xA0 +%if %1 == 8 + paddw m6, [pw_2] + psraw m6, 2 +%elif %1 == 12 + psllw m6, 2 +%endif + psignw m4, m6, [pw_m1] + ;end tc calculations + + paddw m5, [pw_4]; +4 + psraw m5, 3; >> 3 + + pmaxsw m5, m4 + pminsw m5, m6 + paddw m1, m5; p0 + delta0 + psubw m2, m5; q0 - delta0 +%endmacro + + + +%macro LOOP_FILTER_CHROMA 0 + +; void ff_vvc_h_loop_filter_chroma_(uint8_t *pix, ptrdiff_t stride, +; int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, +; int max_len_p, int max_len_q) + +cglobal vvc_h_loop_filter_chroma_8, 5, 6, 7, pix, stride, beta, tc, shift, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movq m0, [pix0q]; p1 + movq m1, [pix0q+strideq]; p0 + movq m2, [pixq]; q0 + movq m3, [pixq+strideq]; q1 + pxor m5, m5; zeros reg + punpcklbw m0, m5 + punpcklbw m1, m5 + punpcklbw m2, m5 + punpcklbw m3, m5 + CHROMA_DEBLOCK_BODY 8 + packuswb m1, m2 + movh[pix0q+strideq], m1 + movhps [pixq], m1 + RET + +cglobal vvc_h_loop_filter_chroma_10, 5, 6, 7, pix, stride, beta, tc, shift, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movu m0, [pix0q]; p1 + movu m1, [pix0q+strideq]; p0 + movu m2, [pixq]; q0 + movu m3, [pixq+strideq]; q1 + CHROMA_DEBLOCK_BODY 10 + pxor m5, m5; zeros reg + CLIPW m1, m5, [pw_pixel_max_10] + CLIPW m2, m5, [pw_pixel_max_10] + movu [pix0q+strideq], m1 + movu [pixq], m2 + RET + +cglobal vvc_h_loop_filter_chroma_12, 4, 5, 7, pix, stride, beta, tc, pix0 + mov pix0q, pixq + sub pix0q, strideq + sub pix0q, strideq + movu m0, [pix0q]; p1 + movu m1, [pix0q+strideq]; p0 + movu m2, [pixq]; q0 + movu m3, [pixq+strideq]; q1 + CHROMA_DEBLOCK_BODY 12 + pxor m5, m5; zeros reg + CLIPW m1, m5, [pw_pixel_max_12] + CLIPW m2, m5, [pw_pixel_max_12] + movu [pix0q+strideq], m1 + movu [pixq], m2 + RET + +; void ff_vvc_v_loop_filter_chroma_(uint8_t *pix, ptrdiff_t stride, +; int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, +; int max_len_p, int max_len_q) + +cglobal vvc_v_loop_filter_chroma_8, 5, 7, 7, pix, stride, beta, tc, shift, pix0, r3stride + sub pixq, 2 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8B_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 8 + TRANSPOSE8x4B_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq) + RET + +cglobal vvc_v_loop_filter_chroma_10, 5, 7, 7, pix, stride, beta, tc, shift, pix0, r3stride + sub pixq, 4 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8W_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 10 + TRANSPOSE8x4W_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq), [pw_pixel_max_10] + RET + +cglobal vvc_v_loop_filter_chroma_12, 4, 6, 7, pix, stride, beta, tc, pix0, r3stride + sub pixq, 4 + lea r3strideq, [3*strideq] + mov pix0q, pixq + add pixq, r3strideq + TRANSPOSE4x8W_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) + CHROMA_DEBLOCK_BODY 12 + TRANSPOSE8x4W_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq), [pw_pixel_max_12] + RET + +%endmacro + +INIT_XMM avx2 +LOOP_FILTER_CHROMA diff --git a/libavcodec/x86/vvcdsp_init.c b/libavcodec/x86/vvcdsp_init.c index a5849e3a2ed..b13fec0677d 100644 --- a/libavcodec/x86/vvcdsp_init.c +++ b/libavcodec/x86/vvcdsp_init.c @@ -196,6 +196,18 @@ SAO_EDGE_FILTER_FUNCS(12, avx2) c->sao.edge_filter[8] = ff_vvc_sao_edge_filter_128_##bitd##_##opt; \ } while (0) +#define LOOP_FILTER_FUNCS(bitd, opt) \ +void ff_vvc_h_loop_filter_chroma_##bitd##_##opt(uint8_t *pix, ptrdiff_t stride, \ + int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, \ + int max_len_p, int max_len_q); \ +void ff_vvc_v_loop_filter_chroma_##bitd##_##opt(uint8_t *pix, ptrdiff_t stride, \ + int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, \ + int max_len_p, int max_len_q); \ + +LOOP_FILTER_FUNCS(8, avx2) +LOOP_FILTER_FUNCS(10, avx2) +LOOP_FILTER_FUNCS(12, avx2) + #define PUT_VVC_LUMA_8_FUNC(dir, opt) \ void ff_vvc_put_vvc_luma_##dir##_8_##opt(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src_stride, \ const int height, const intptr_t mx, const intptr_t my, const int width, \ @@ -252,15 +264,21 @@ void ff_vvc_dsp_init_x86(VVCDSPContext *const c, const int bit_depth) PUT_VVC_LUMA_INIT(8, avx2); c->sao.band_filter[0] = ff_vvc_sao_band_filter_8_8_avx2; c->sao.band_filter[1] = ff_vvc_sao_band_filter_16_8_avx2; + c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_8_avx2; + c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_8_avx2; break; case 10: ALF_DSP(10); PUT_VVC_LUMA_INIT(10, avx2); c->sao.band_filter[0] = ff_vvc_sao_band_filter_8_10_avx2; + c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_10_avx2; + c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_10_avx2; break; case 12: ALF_DSP(12); PUT_VVC_LUMA_INIT(12, avx2); + c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_12_avx2; + c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_12_avx2; break; default: break; From f16e8060a75f33367213ede530cbb03e6297409a Mon Sep 17 00:00:00 2001 From: Shaun Loo Date: Tue, 22 Aug 2023 02:44:17 -0500 Subject: [PATCH 3/3] Add luma deblocker; has issues Signed-off-by: Shaun Loo --- libavcodec/vvc/vvc_filter.c | 19 +- libavcodec/vvc/vvc_filter_template.c | 2 + libavcodec/vvc/vvcdsp.h | 2 + libavcodec/x86/vvc_deblock.asm | 449 ++++++++++++++++++++++++++- libavcodec/x86/vvcdsp_init.c | 17 + 5 files changed, 480 insertions(+), 9 deletions(-) diff --git a/libavcodec/vvc/vvc_filter.c b/libavcodec/vvc/vvc_filter.c index 12b39d5a42b..b822496c5a2 100644 --- a/libavcodec/vvc/vvc_filter.c +++ b/libavcodec/vvc/vvc_filter.c @@ -918,8 +918,13 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0) max_filter_length(fc, x, y, c_idx, 1, 0, bs, &max_len_p, &max_len_q); if (!c_idx) { - fc->vvcdsp.lf.filter_luma[1](src, - fc->frame->linesize[c_idx], beta, tc, no_p, no_q, max_len_p, max_len_q, 0); + if ((no_p || no_q) || (max_len_p == 3 || max_len_q == 3)) { + fc->vvcdsp.lf.filter_luma_c[1](src, + fc->frame->linesize[c_idx], beta, tc, no_p, no_q, max_len_p, max_len_q, 0); + } else { + fc->vvcdsp.lf.filter_luma[1](src, + fc->frame->linesize[c_idx], beta, tc, no_p, no_q, max_len_p, max_len_q, 0); + } } else { if (vs || (no_p || no_q) || (max_len_p == 3 || max_len_q == 3) || (!max_len_p || !max_len_q)) { fc->vvcdsp.lf.filter_chroma_c[1](src, @@ -992,8 +997,14 @@ void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0) max_filter_length(fc, x, y, c_idx, 0, horizontal_ctu_edge, bs, &max_len_p, &max_len_q); if (!c_idx) { - fc->vvcdsp.lf.filter_luma[0](src, fc->frame->linesize[c_idx], - beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge); + if ((no_p || no_q) || ((max_len_p > 3 && !horizontal_ctu_edge) || max_len_q > 3)) { + fc->vvcdsp.lf.filter_luma_c[0](src, fc->frame->linesize[c_idx], + beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge); + } else { + fc->vvcdsp.lf.filter_luma[0](src, fc->frame->linesize[c_idx], + beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge); + } + } else { if (hs || (no_p || no_q) || (!max_len_p || !max_len_q) || (max_len_p == 3 || max_len_q == 3)) { fc->vvcdsp.lf.filter_chroma_c[0](src, fc->frame->linesize[c_idx], beta, diff --git a/libavcodec/vvc/vvc_filter_template.c b/libavcodec/vvc/vvc_filter_template.c index 6cea412ae51..b83c5d303dd 100644 --- a/libavcodec/vvc/vvc_filter_template.c +++ b/libavcodec/vvc/vvc_filter_template.c @@ -1066,6 +1066,8 @@ static void FUNC(ff_vvc_lf_dsp_init)(VVCLFDSPContext *const lf) lf->filter_luma[1] = FUNC(vvc_v_loop_filter_luma); lf->filter_chroma[0] = FUNC(vvc_h_loop_filter_chroma); lf->filter_chroma[1] = FUNC(vvc_v_loop_filter_chroma); + lf->filter_luma_c[0] = FUNC(vvc_h_loop_filter_luma); + lf->filter_luma_c[1] = FUNC(vvc_v_loop_filter_luma); lf->filter_chroma_c[0] = FUNC(vvc_h_loop_filter_chroma); lf->filter_chroma_c[1] = FUNC(vvc_v_loop_filter_chroma); } diff --git a/libavcodec/vvc/vvcdsp.h b/libavcodec/vvc/vvcdsp.h index 0ad1b41ec86..62f6dc6d3fe 100644 --- a/libavcodec/vvc/vvcdsp.h +++ b/libavcodec/vvc/vvcdsp.h @@ -130,6 +130,8 @@ typedef struct VVCLFDSPContext { uint8_t no_p, uint8_t no_q, uint8_t max_len_p, uint8_t max_len_q, int hor_ctu_edge); void (*filter_chroma[2 /* h, v */])(uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, int max_len_p, int max_len_q); + void (*filter_luma_c[2 /* h, v */])(uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, + uint8_t no_p, uint8_t no_q, uint8_t max_len_p, uint8_t max_len_q, int hor_ctu_edge); void (*filter_chroma_c[2 /* h, v */])(uint8_t *pix, ptrdiff_t stride, int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, int max_len_p, int max_len_q); } VVCLFDSPContext; diff --git a/libavcodec/x86/vvc_deblock.asm b/libavcodec/x86/vvc_deblock.asm index 58153bc71f7..f7d72a3aa68 100644 --- a/libavcodec/x86/vvc_deblock.asm +++ b/libavcodec/x86/vvc_deblock.asm @@ -32,9 +32,11 @@ cextern pw_1023 %define pw_pixel_max_10 pw_1023 pw_pixel_max_12: times 8 dw ((1 << 12)-1) pw_m2: times 8 dw -2 +pw_m3: times 8 dw -3 pd_1 : times 4 dd 1 pw_2 : times 8 dw 2 -pd_2 : times 4 dd 2 +pw_3 : times 8 dw 3 +pw_8 : times 8 dw 8 cextern pw_4 cextern pw_8 @@ -303,13 +305,349 @@ ALIGN 16 psubw m2, m5; q0 - delta0 %endmacro +; input in m0 ... m7, beta in r2 tcs in r3. Output in m1...m6 +%macro LUMA_DEBLOCK_BODY 2 + psllw m9, m2, 1; *2 + psubw m10, m1, m9 + paddw m10, m3 + ABS1 m10, m11 ; 0dp0, 0dp3 , 1dp0, 1dp3 + + psllw m9, m5, 1; *2 + psubw m11, m6, m9 + paddw m11, m4 + ABS1 m11, m13 ; 0dq0, 0dq3 , 1dq0, 1dq3 + + ;beta calculations +%if %1 > 8 + shl betaq, %1 - 8 +%endif + movd m13, betad + SPLATW m13, m13, 0 + ;end beta calculations + + paddw m9, m10, m11; 0d0, 0d3 , 1d0, 1d3 + + pshufhw m14, m9, 0x0f ;0b00001111; 0d3 0d3 0d0 0d0 in high + pshuflw m14, m14, 0x0f ;0b00001111; 1d3 1d3 1d0 1d0 in low + + pshufhw m9, m9, 0xf0 ;0b11110000; 0d0 0d0 0d3 0d3 + pshuflw m9, m9, 0xf0 ;0b11110000; 1d0 1d0 1d3 1d3 + + paddw m14, m9; 0d0+0d3, 1d0+1d3 + + ;compare d0 + d3 to beta + pcmpgtw m15, m13, m14 + movmskps r13, m15 ;filtering mask 0d0 + 0d3 < beta0 (bit 2 or 3) , 1d0 + 1d3 < beta1 (bit 0 or 1) + test r13, r13 + je .bypassluma + + ;weak / strong decision compare to beta_2 + psraw m15, m13, 2; beta >> 2 + psllw m8, m9, 1; + pcmpgtw m15, m8; (d0 << 1) < beta_2, (d3 << 1) < beta_2 + movmskps r6, m15; + ;end weak / strong decision + + ; weak filter nd_p/q calculation + pshufd m8, m10, 0x31 + psrld m8, 16 + paddw m8, m10 + movd r7d, m8 + pshufd m8, m8, 0x4E + movd r8d, m8 + + pshufd m8, m11, 0x31 + psrld m8, 16 + paddw m8, m11 + movd r9d, m8 + pshufd m8, m8, 0x4E + movd r10d, m8 + ; end calc for weak filter + + ; filtering mask + mov r11, r13 + shr r11, 3 + movd m15, r11d + and r13, 1 + movd m11, r13d + shufps m11, m15, 0 + shl r11, 1 + or r13, r11 + + pcmpeqd m11, [pd_1]; filtering mask + + ;tc, tc25 calculations +%if %1 == 8 + add tcd, 2 + shr tcd, 2 +%elif %1 > 10 + shl tcd, 2 +%endif + movd m9, tcd; tc in m9 + punpcklwd m9, m9 + mova m8, m9 + psllw m8, 2; tc << 2 + pavgw m8, m9; + + ;end tc25 calculations + + ;----beta_3 comparison----- + psubw m12, m0, m3; p3 - p0 + ABS1 m12, m14; abs(p3 - p0) + + psubw m15, m7, m4; q3 - q0 + ABS1 m15, m14; abs(q3 - q0) + + paddw m12, m15; abs(p3 - p0) + abs(q3 - q0) + + pshufhw m12, m12, 0xf0 ;0b11110000; + pshuflw m12, m12, 0xf0 ;0b11110000; + + psraw m13, 3; beta >> 3 + pcmpgtw m13, m12; + movmskps r11, m13; + and r6, r11; strong mask , beta_2 and beta_3 comparisons + ;----beta_3 comparison end----- + ;----tc25 comparison--- + psubw m12, m3, m4; p0 - q0 + ABS1 m12, m14; abs(p0 - q0) + + pshufhw m12, m12, 0xf0 ;0b11110000; + pshuflw m12, m12, 0xf0 ;0b11110000; + + pcmpgtw m8, m12; tc25 comparisons + movmskps r11, m8; + and r6, r11; strong mask, beta_2, beta_3 and tc25 comparisons + ;----tc25 comparison end--- + mov r11, r6; + shr r11, 1; + and r6, r11; strong mask, bits 2 and 0 + and r6, 5; 0b101 + mov r11, r6; strong mask + shr r6, 2; + movd m12, r6d; store to xmm for mask generation + shl r6, 1 + and r11, 1 + movd m10, r11d; store to xmm for mask generation + or r6, r11; final strong mask, bits 1 and 0 + jz .weakfilter + + shufps m10, m12, 0 + pcmpeqd m10, [pd_1]; strong mask + + ; -tc3 and tc3 for clipping p0' + pmullw m14, m9, [pw_m3]; -tc * 3 + pmullw m9, m9, [pw_3]; tc * 3 + + mova m13, [pw_4]; 4 in every cell + pand m11, m10; combine filtering mask and strong mask + paddw m12, m2, m3; p1 + p0 + paddw m12, m4; p1 + p0 + q0 + mova m10, m12; copy + paddw m12, m12; 2*p1 + 2*p0 + 2*q0 + paddw m12, m1; p2 + 2*p1 + 2*p0 + 2*q0 + paddw m12, m5; p2 + 2*p1 + 2*p0 + 2*q0 + q1 + paddw m12, m13; p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 + psraw m12, 3; ((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4) >> 3) + psubw m12, m3; ((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4) >> 3) - p0 + pmaxsw m12, m14 + pminsw m12, m9; av_clip( , -2 * tc, 2 * tc) + paddw m12, m3; p0' + + ; -tc2 and tc2 for clipping p1' + movd m9, tcd; tc in m9 + punpcklwd m9, m9 + pmullw m14, m9, [pw_m2]; -tc * 2 + paddw m9, m9 + + paddw m15, m1, m10; p2 + p1 + p0 + q0 + psrlw m13, 1; 2 in every cell + paddw m15, m13; p2 + p1 + p0 + q0 + 2 + psraw m15, 2; (p2 + p1 + p0 + q0 + 2) >> 2 + psubw m15, m2;((p2 + p1 + p0 + q0 + 2) >> 2) - p1 + pmaxsw m15, m14 + pminsw m15, m9; av_clip( , -2 * tc, 2 * tc) + paddw m15, m2; p1' + + ; -tc and tc for clipping p2' + movd m9, tcd; tc in m9 + punpcklwd m9, m9 + psignw m14, m9, [pw_m1] + + paddw m8, m1, m0; p3 + p2 + paddw m8, m8; 2*p3 + 2*p2 + paddw m8, m1; 2*p3 + 3*p2 + paddw m8, m10; 2*p3 + 3*p2 + p1 + p0 + q0 + paddw m13, m13 + paddw m8, m13; 2*p3 + 3*p2 + p1 + p0 + q0 + 4 + psraw m8, 3; (2*p3 + 3*p2 + p1 + p0 + q0 + 4) >> 3 + psubw m8, m1; ((2*p3 + 3*p2 + p1 + p0 + q0 + 4) >> 3) - p2 + pmaxsw m8, m14 + pminsw m8, m9; av_clip( , -2 * tc, 2 * tc) + paddw m8, m1; p2' + MASKED_COPY m1, m8 + + ; -tc3 and tc3 for clipping q0' + movd m9, tcd; tc in m9 + punpcklwd m9, m9 + pmullw m14, m9, [pw_m3]; -tc * 3 + pmullw m9, m9, [pw_3]; tc * 3 + + paddw m8, m3, m4; p0 + q0 + paddw m8, m5; p0 + q0 + q1 + paddw m8, m8; 2*p0 + 2*q0 + 2*q1 + paddw m8, m2; p1 + 2*p0 + 2*q0 + 2*q1 + paddw m8, m6; p1 + 2*p0 + 2*q0 + 2*q1 + q2 + paddw m8, m13; p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 + psraw m8, 3; (p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4) >>3 + psubw m8, m4; + pmaxsw m8, m14 + pminsw m8, m9; av_clip( , -2 * tc, 2 * tc) + paddw m8, m4; q0' + MASKED_COPY m2, m15 + + ; -tc2 and tc2 for clipping q1' + movd m9, tcd; tc in m9 + punpcklwd m9, m9 + pmullw m14, m9, [pw_m2]; -tc * 2 + paddw m9, m9 + + paddw m15, m3, m4; p0 + q0 + paddw m15, m5; p0 + q0 + q1 + mova m10, m15; + paddw m15, m6; p0 + q0 + q1 + q2 + psrlw m13, 1; 2 in every cell + paddw m15, m13; p0 + q0 + q1 + q2 + 2 + psraw m15, 2; (p0 + q0 + q1 + q2 + 2) >> 2 + psubw m15, m5; ((p0 + q0 + q1 + q2 + 2) >> 2) - q1 + pmaxsw m15, m14 + pminsw m15, m9; av_clip( , -2 * tc, 2 * tc) + paddw m15, m5; q1' + + ; -tc and tc for clipping q2' + movd m9, tcd; tc in m9 + punpcklwd m9, m9 + psignw m14, m9, [pw_m1] + + paddw m13, m7; q3 + 2 + paddw m13, m6; q3 + q2 + 2 + paddw m13, m13; 2*q3 + 2*q2 + 4 + paddw m13, m6; 2*q3 + 3*q2 + 4 + paddw m13, m10; 2*q3 + 3*q2 + q1 + q0 + p0 + 4 + psraw m13, 3; (2*q3 + 3*q2 + q1 + q0 + p0 + 4) >> 3 + psubw m13, m6; ((2*q3 + 3*q2 + q1 + q0 + p0 + 4) >> 3) - q2 + pmaxsw m13, m14 + pminsw m13, m9; av_clip( , -2 * tc, 2 * tc) + paddw m13, m6; q2' + + MASKED_COPY m6, m13 + MASKED_COPY m5, m15 + MASKED_COPY m4, m8 + MASKED_COPY m3, m12 + +.weakfilter: + not r6; strong mask -> weak mask + and r6, r13; final weak filtering mask, bits 0 and 1 + jz .store + + ; weak filtering mask + mov r11, r6 + shr r11, 1 + movd m12, r11d + and r6, 1 + movd m11, r6d + shufps m11, m12, 0 + pcmpeqd m11, [pd_1]; filtering mask + + mov r13, betaq + shr r13, 1; + add betaq, r13 + shr betaq, 3; ((beta + (beta >> 1)) >> 3)) + + mova m13, [pw_8] + psubw m12, m4, m3 ; q0 - p0 + psllw m10, m12, 3; 8 * (q0 - p0) + paddw m12, m10 ; 9 * (q0 - p0) + + psubw m10, m5, m2 ; q1 - p1 + psllw m8, m10, 1; 2 * ( q1 - p1 ) + paddw m10, m8; 3 * ( q1 - p1 ) + psubw m12, m10; 9 * (q0 - p0) - 3 * ( q1 - p1 ) + paddw m12, m13; + 8 + psraw m12, 4; >> 4 , delta0 + PABSW m13, m12; abs(delta0) + + + psllw m10, m9, 2; 8 * tc + paddw m10, m9; 10 * tc + pcmpgtw m10, m13 + pand m11, m10 + + psraw m9, 1; tc * 2 -> tc + psraw m14, 1; -tc * 2 -> -tc + + pmaxsw m12, m14 + pminsw m12, m9; av_clip(delta0, -tc, tc) + + psraw m9, 1; tc -> tc / 2 +%if cpuflag(ssse3) + psignw m14, m9, [pw_m1]; -tc / 2 +%else + pmullw m14, m9, [pw_m1]; -tc / 2 +%endif + pavgw m15, m1, m3; (p2 + p0 + 1) >> 1 + psubw m15, m2; ((p2 + p0 + 1) >> 1) - p1 + paddw m15, m12; ((p2 + p0 + 1) >> 1) - p1 + delta0 + psraw m15, 1; (((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1 + pmaxsw m15, m14 + pminsw m15, m9; av_clip(deltap1, -tc/2, tc/2) + paddw m15, m2; p1' + + ;beta calculations + movd m10, betad + SPLATW m10, m10, 0 + + movd m13, r7d; 1dp0 + 1dp3 + movd m8, r8d; 0dp0 + 0dp3 + punpcklwd m8, m8 + punpcklwd m13, m13 + shufps m13, m8, 0; + pcmpgtw m8, m10, m13 + pand m8, m11 + ;end beta calculations + MASKED_COPY2 m2, m15, m8; write p1' + + pavgw m8, m6, m4; (q2 + q0 + 1) >> 1 + psubw m8, m5; ((q2 + q0 + 1) >> 1) - q1 + psubw m8, m12; ((q2 + q0 + 1) >> 1) - q1 - delta0) + psraw m8, 1; ((q2 + q0 + 1) >> 1) - q1 - delta0) >> 1 + pmaxsw m8, m14 + pminsw m8, m9; av_clip(deltaq1, -tc/2, tc/2) + paddw m8, m5; q1' + + movd m13, r9d; + movd m15, r10d; + punpcklwd m15, m15 + punpcklwd m13, m13 + shufps m13, m15, 0; dq0 + dq3 + + pcmpgtw m10, m13; compare to ((beta+(beta>>1))>>3) + pand m10, m11 + MASKED_COPY2 m5, m8, m10; write q1' + + paddw m15, m3, m12 ; p0 + delta0 + MASKED_COPY m3, m15 + + psubw m8, m4, m12 ; q0 - delta0 + MASKED_COPY m4, m8 +%endmacro -%macro LOOP_FILTER_CHROMA 0 - +;----------------------------------------------------------------------------- ; void ff_vvc_h_loop_filter_chroma_(uint8_t *pix, ptrdiff_t stride, ; int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, ; int max_len_p, int max_len_q) +;----------------------------------------------------------------------------- cglobal vvc_h_loop_filter_chroma_8, 5, 6, 7, pix, stride, beta, tc, shift, pix0 mov pix0q, pixq @@ -361,10 +699,11 @@ cglobal vvc_h_loop_filter_chroma_12, 4, 5, 7, pix, stride, beta, tc, pix0 movu [pix0q+strideq], m1 movu [pixq], m2 RET - +;----------------------------------------------------------------------------- ; void ff_vvc_v_loop_filter_chroma_(uint8_t *pix, ptrdiff_t stride, ; int beta, int32_t tc, uint8_t no_p, uint8_t no_q, int shift, ; int max_len_p, int max_len_q) +;----------------------------------------------------------------------------- cglobal vvc_v_loop_filter_chroma_8, 5, 7, 7, pix, stride, beta, tc, shift, pix0, r3stride sub pixq, 2 @@ -396,7 +735,107 @@ cglobal vvc_v_loop_filter_chroma_12, 4, 6, 7, pix, stride, beta, tc, pix0, r3str TRANSPOSE8x4W_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq), [pw_pixel_max_12] RET -%endmacro +;----------------------------------------------------------------------------- +; void ff_vvc_v_loop_filter_luma_(uint8_t *pix, ptrdiff_t stride, int beta, +; int32_t tc, uint8_t no_p, uint8_t no_q, uint8_t max_len_p, uint8_t max_len_q, +; int hor_ctu_edge); +;----------------------------------------------------------------------------- + +cglobal vvc_v_loop_filter_luma_8, 4, 14, 16, pix, stride, beta, tc, pix0, src3stride + sub pixq, 4 + lea pix0q, [3 * r1] + mov src3strideq, pixq + add pixq, pix0q + TRANSPOSE8x8B_LOAD PASS8ROWS(src3strideq, pixq, r1, pix0q) + LUMA_DEBLOCK_BODY 8, v +.store: + TRANSPOSE8x8B_STORE PASS8ROWS(src3strideq, pixq, r1, pix0q) +.bypassluma: + RET + +cglobal vvc_v_loop_filter_luma_10, 4, 14, 16, pix, stride, beta, tc, pix0, src3stride + sub pixq, 8 + lea pix0q, [3 * strideq] + mov src3strideq, pixq + add pixq, pix0q + TRANSPOSE8x8W_LOAD PASS8ROWS(src3strideq, pixq, strideq, pix0q) + LUMA_DEBLOCK_BODY 10, v +.store: + TRANSPOSE8x8W_STORE PASS8ROWS(src3strideq, pixq, r1, pix0q), [pw_pixel_max_10] +.bypassluma: + RET + +;----------------------------------------------------------------------------- +; void ff_vvc_h_loop_filter_luma_(uint8_t *pix, ptrdiff_t stride, int beta, +; int32_t tc, uint8_t no_p, uint8_t no_q, uint8_t max_len_p, uint8_t max_len_q, +; int hor_ctu_edge); +;----------------------------------------------------------------------------- +cglobal vvc_h_loop_filter_luma_8, 4, 14, 16, pix, stride, beta, tc, pix0, src3stride + lea src3strideq, [3 * strideq] + mov pix0q, pixq + sub pix0q, src3strideq + sub pix0q, strideq + movq m0, [pix0q]; p3 + movq m1, [pix0q + strideq]; p2 + movq m2, [pix0q + 2 * strideq]; p1 + movq m3, [pix0q + src3strideq]; p0 + movq m4, [pixq]; q0 + movq m5, [pixq + strideq]; q1 + movq m6, [pixq + 2 * strideq]; q2 + movq m7, [pixq + src3strideq]; q3 + pxor m8, m8 + punpcklbw m0, m8 + punpcklbw m1, m8 + punpcklbw m2, m8 + punpcklbw m3, m8 + punpcklbw m4, m8 + punpcklbw m5, m8 + punpcklbw m6, m8 + punpcklbw m7, m8 + LUMA_DEBLOCK_BODY 8, h +.store: + packuswb m1, m2 + packuswb m3, m4 + packuswb m5, m6 + movh [pix0q + strideq], m1 + movhps [pix0q + 2 * strideq], m1 + movh [pix0q + src3strideq], m3 + movhps [pixq ], m3 + movh [pixq + strideq], m5 + movhps [pixq + 2 * strideq], m5 +.bypassluma: + RET + +cglobal vvc_h_loop_filter_luma_10, 4, 14, 16, pix, stride, beta, tc, pix0, src3stride + lea src3strideq, [3 * strideq] + mov pix0q, pixq + sub pix0q, src3strideq + sub pix0q, strideq + movdqu m0, [pix0q]; p3 + movdqu m1, [pix0q + strideq]; p2 + movdqu m2, [pix0q + 2 * strideq]; p1 + movdqu m3, [pix0q + src3strideq]; p0 + movdqu m4, [pixq]; q0 + movdqu m5, [pixq + strideq]; q1 + movdqu m6, [pixq + 2 * strideq]; q2 + movdqu m7, [pixq + src3strideq]; q3 + LUMA_DEBLOCK_BODY 10, h +.store: + pxor m8, m8; zeros reg + CLIPW m1, m8, [pw_pixel_max_10] + CLIPW m2, m8, [pw_pixel_max_10] + CLIPW m3, m8, [pw_pixel_max_10] + CLIPW m4, m8, [pw_pixel_max_10] + CLIPW m5, m8, [pw_pixel_max_10] + CLIPW m6, m8, [pw_pixel_max_10] + movdqu [pix0q + strideq], m1; p2 + movdqu [pix0q + 2 * strideq], m2; p1 + movdqu [pix0q + src3strideq], m3; p0 + movdqu [pixq ], m4; q0 + movdqu [pixq + strideq], m5; q1 + movdqu [pixq + 2 * strideq], m6; q2 +.bypassluma: + RET INIT_XMM avx2 LOOP_FILTER_CHROMA diff --git a/libavcodec/x86/vvcdsp_init.c b/libavcodec/x86/vvcdsp_init.c index b13fec0677d..e79bab915d1 100644 --- a/libavcodec/x86/vvcdsp_init.c +++ b/libavcodec/x86/vvcdsp_init.c @@ -208,6 +208,19 @@ LOOP_FILTER_FUNCS(8, avx2) LOOP_FILTER_FUNCS(10, avx2) LOOP_FILTER_FUNCS(12, avx2) +#define LOOP_LUMA_FUNCS(bitd, opt) \ +void ff_vvc_h_loop_filter_luma_##bitd##_##opt(uint8_t *pix, ptrdiff_t stride, int beta, \ + int32_t tc, uint8_t no_p, uint8_t no_q, \ + uint8_t max_len_p, uint8_t max_len_q, \ + int hor_ctu_edge); \ +void ff_vvc_v_loop_filter_luma_##bitd##_##opt(uint8_t *pix, ptrdiff_t stride, int beta, \ + int32_t tc, uint8_t no_p, uint8_t no_q, \ + uint8_t max_len_p, uint8_t max_len_q, \ + int hor_ctu_edge); \ + +LOOP_LUMA_FUNCS(8, avx2) +LOOP_LUMA_FUNCS(10, avx2) + #define PUT_VVC_LUMA_8_FUNC(dir, opt) \ void ff_vvc_put_vvc_luma_##dir##_8_##opt(int16_t *dst, const uint8_t *_src, const ptrdiff_t _src_stride, \ const int height, const intptr_t mx, const intptr_t my, const int width, \ @@ -264,6 +277,8 @@ void ff_vvc_dsp_init_x86(VVCDSPContext *const c, const int bit_depth) PUT_VVC_LUMA_INIT(8, avx2); c->sao.band_filter[0] = ff_vvc_sao_band_filter_8_8_avx2; c->sao.band_filter[1] = ff_vvc_sao_band_filter_16_8_avx2; + c->lf.filter_luma[0] = ff_vvc_h_loop_filter_luma_8_avx2; + c->lf.filter_luma[1] = ff_vvc_v_loop_filter_luma_8_avx2; c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_8_avx2; c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_8_avx2; break; @@ -273,6 +288,8 @@ void ff_vvc_dsp_init_x86(VVCDSPContext *const c, const int bit_depth) c->sao.band_filter[0] = ff_vvc_sao_band_filter_8_10_avx2; c->lf.filter_chroma[0] = ff_vvc_h_loop_filter_chroma_10_avx2; c->lf.filter_chroma[1] = ff_vvc_v_loop_filter_chroma_10_avx2; + c->lf.filter_luma[0] = ff_vvc_h_loop_filter_luma_10_avx2; + c->lf.filter_luma[1] = ff_vvc_v_loop_filter_luma_10_avx2; break; case 12: ALF_DSP(12);