mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
vf_hqdn3d: x86 asm
13% faster on penryn, 16% on sandybridge, 15% on bulldozer Not simd; a compiler should have generated this, but gcc didn't.
This commit is contained in:
parent
566858a770
commit
7a1944b907
@ -41,8 +41,14 @@ typedef struct {
|
|||||||
double strength[4];
|
double strength[4];
|
||||||
int hsub, vsub;
|
int hsub, vsub;
|
||||||
int depth;
|
int depth;
|
||||||
|
void (*denoise_row[17])(uint8_t *src, uint8_t *dst, uint16_t *line_ant, uint16_t *frame_ant, ptrdiff_t w, int16_t *spatial, int16_t *temporal);
|
||||||
} HQDN3DContext;
|
} HQDN3DContext;
|
||||||
|
|
||||||
|
void ff_hqdn3d_row_8_x86(uint8_t *src, uint8_t *dst, uint16_t *line_ant, uint16_t *frame_ant, ptrdiff_t w, int16_t *spatial, int16_t *temporal);
|
||||||
|
void ff_hqdn3d_row_9_x86(uint8_t *src, uint8_t *dst, uint16_t *line_ant, uint16_t *frame_ant, ptrdiff_t w, int16_t *spatial, int16_t *temporal);
|
||||||
|
void ff_hqdn3d_row_10_x86(uint8_t *src, uint8_t *dst, uint16_t *line_ant, uint16_t *frame_ant, ptrdiff_t w, int16_t *spatial, int16_t *temporal);
|
||||||
|
void ff_hqdn3d_row_16_x86(uint8_t *src, uint8_t *dst, uint16_t *line_ant, uint16_t *frame_ant, ptrdiff_t w, int16_t *spatial, int16_t *temporal);
|
||||||
|
|
||||||
#define LUT_BITS (depth==16 ? 8 : 4)
|
#define LUT_BITS (depth==16 ? 8 : 4)
|
||||||
#define RIGHTSHIFT(a,b) (((a)+(((1<<(b))-1)>>1))>>(b))
|
#define RIGHTSHIFT(a,b) (((a)+(((1<<(b))-1)>>1))>>(b))
|
||||||
#define LOAD(x) ((depth==8 ? src[x] : AV_RN16A(src+(x)*2)) << (16-depth))
|
#define LOAD(x) ((depth==8 ? src[x] : AV_RN16A(src+(x)*2)) << (16-depth))
|
||||||
@ -79,7 +85,8 @@ static void denoise_temporal(uint8_t *src, uint8_t *dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
av_always_inline
|
av_always_inline
|
||||||
static void denoise_spatial(uint8_t *src, uint8_t *dst,
|
static void denoise_spatial(HQDN3DContext *hqdn3d,
|
||||||
|
uint8_t *src, uint8_t *dst,
|
||||||
uint16_t *line_ant, uint16_t *frame_ant,
|
uint16_t *line_ant, uint16_t *frame_ant,
|
||||||
int w, int h, int sstride, int dstride,
|
int w, int h, int sstride, int dstride,
|
||||||
int16_t *spatial, int16_t *temporal, int depth)
|
int16_t *spatial, int16_t *temporal, int depth)
|
||||||
@ -104,6 +111,10 @@ static void denoise_spatial(uint8_t *src, uint8_t *dst,
|
|||||||
src += sstride;
|
src += sstride;
|
||||||
dst += dstride;
|
dst += dstride;
|
||||||
frame_ant += w;
|
frame_ant += w;
|
||||||
|
if (hqdn3d->denoise_row[depth]) {
|
||||||
|
hqdn3d->denoise_row[depth](src, dst, line_ant, frame_ant, w, spatial, temporal);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
pixel_ant = LOAD(0);
|
pixel_ant = LOAD(0);
|
||||||
for (x = 0; x < w-1; x++) {
|
for (x = 0; x < w-1; x++) {
|
||||||
line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial, depth);
|
line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial, depth);
|
||||||
@ -118,7 +129,8 @@ static void denoise_spatial(uint8_t *src, uint8_t *dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
av_always_inline
|
av_always_inline
|
||||||
static void denoise_depth(uint8_t *src, uint8_t *dst,
|
static void denoise_depth(HQDN3DContext *hqdn3d,
|
||||||
|
uint8_t *src, uint8_t *dst,
|
||||||
uint16_t *line_ant, uint16_t **frame_ant_ptr,
|
uint16_t *line_ant, uint16_t **frame_ant_ptr,
|
||||||
int w, int h, int sstride, int dstride,
|
int w, int h, int sstride, int dstride,
|
||||||
int16_t *spatial, int16_t *temporal, int depth)
|
int16_t *spatial, int16_t *temporal, int depth)
|
||||||
@ -138,7 +150,7 @@ static void denoise_depth(uint8_t *src, uint8_t *dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (spatial[0])
|
if (spatial[0])
|
||||||
denoise_spatial(src, dst, line_ant, frame_ant,
|
denoise_spatial(hqdn3d, src, dst, line_ant, frame_ant,
|
||||||
w, h, sstride, dstride, spatial, temporal, depth);
|
w, h, sstride, dstride, spatial, temporal, depth);
|
||||||
else
|
else
|
||||||
denoise_temporal(src, dst, frame_ant,
|
denoise_temporal(src, dst, frame_ant,
|
||||||
@ -298,6 +310,13 @@ static int config_input(AVFilterLink *inlink)
|
|||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_YASM
|
||||||
|
hqdn3d->denoise_row[ 8] = ff_hqdn3d_row_8_x86;
|
||||||
|
hqdn3d->denoise_row[ 9] = ff_hqdn3d_row_9_x86;
|
||||||
|
hqdn3d->denoise_row[10] = ff_hqdn3d_row_10_x86;
|
||||||
|
hqdn3d->denoise_row[16] = ff_hqdn3d_row_16_x86;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +334,7 @@ static int end_frame(AVFilterLink *inlink)
|
|||||||
int ret, c;
|
int ret, c;
|
||||||
|
|
||||||
for (c = 0; c < 3; c++) {
|
for (c = 0; c < 3; c++) {
|
||||||
denoise(inpic->data[c], outpic->data[c],
|
denoise(hqdn3d, inpic->data[c], outpic->data[c],
|
||||||
hqdn3d->line, &hqdn3d->frame_prev[c],
|
hqdn3d->line, &hqdn3d->frame_prev[c],
|
||||||
inpic->video->w >> (!!c * hqdn3d->hsub),
|
inpic->video->w >> (!!c * hqdn3d->hsub),
|
||||||
inpic->video->h >> (!!c * hqdn3d->vsub),
|
inpic->video->h >> (!!c * hqdn3d->vsub),
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
MMX-OBJS-$(CONFIG_YADIF_FILTER) += x86/yadif.o
|
MMX-OBJS-$(CONFIG_YADIF_FILTER) += x86/yadif.o
|
||||||
MMX-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/gradfun.o
|
MMX-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/gradfun.o
|
||||||
|
YASM-OBJS-$(CONFIG_HQDN3D_FILTER) += x86/hqdn3d.o
|
||||||
|
106
libavfilter/x86/hqdn3d.asm
Normal file
106
libavfilter/x86/hqdn3d.asm
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
;******************************************************************************
|
||||||
|
;* Copyright (c) 2012 Loren Merritt
|
||||||
|
;*
|
||||||
|
;* This file is part of Libav.
|
||||||
|
;*
|
||||||
|
;* Libav 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.
|
||||||
|
;*
|
||||||
|
;* Libav 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 Libav; if not, write to the Free Software
|
||||||
|
;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
;******************************************************************************
|
||||||
|
|
||||||
|
%include "x86inc.asm"
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
|
||||||
|
%macro LOWPASS 3 ; prevsample, cursample, lut
|
||||||
|
sub %1q, %2q
|
||||||
|
%if lut_bits != 8
|
||||||
|
sar %1q, 8-lut_bits
|
||||||
|
%endif
|
||||||
|
movsx %1d, word [%3q+%1q*2]
|
||||||
|
add %1d, %2d
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro LOAD 3 ; dstreg, x, bitdepth
|
||||||
|
%if %3 == 8
|
||||||
|
movzx %1, byte [srcq+%2]
|
||||||
|
%else
|
||||||
|
movzx %1, word [srcq+(%2)*2]
|
||||||
|
%endif
|
||||||
|
%if %3 != 16
|
||||||
|
shl %1, 16-%3
|
||||||
|
%endif
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro HQDN3D_ROW 1 ; bitdepth
|
||||||
|
%if ARCH_X86_64
|
||||||
|
cglobal hqdn3d_row_%1_x86, 7,10,0, src, dst, lineant, frameant, width, spatial, temporal, pixelant, t0, t1
|
||||||
|
%else
|
||||||
|
cglobal hqdn3d_row_%1_x86, 7,7,0, src, dst, lineant, frameant, width, spatial, temporal
|
||||||
|
%endif
|
||||||
|
%assign bytedepth (%1+7)>>3
|
||||||
|
%assign lut_bits 4+4*(%1/16)
|
||||||
|
dec widthq
|
||||||
|
lea srcq, [srcq+widthq*bytedepth]
|
||||||
|
lea dstq, [dstq+widthq*bytedepth]
|
||||||
|
lea frameantq, [frameantq+widthq*2]
|
||||||
|
lea lineantq, [lineantq+widthq*2]
|
||||||
|
neg widthq
|
||||||
|
%define xq widthq
|
||||||
|
%if ARCH_X86_32
|
||||||
|
mov dstmp, dstq
|
||||||
|
mov srcmp, srcq
|
||||||
|
mov frameantmp, frameantq
|
||||||
|
mov lineantmp, lineantq
|
||||||
|
%define dstq r0
|
||||||
|
%define frameantq r0
|
||||||
|
%define lineantq r0
|
||||||
|
%define pixelantq r1
|
||||||
|
%define pixelantd r1d
|
||||||
|
DECLARE_REG_TMP 2,3
|
||||||
|
%endif
|
||||||
|
LOAD pixelantd, xq, %1
|
||||||
|
ALIGN 16
|
||||||
|
.loop:
|
||||||
|
movifnidn srcq, srcmp
|
||||||
|
LOAD t0d, xq+1, %1 ; skip on the last iteration to avoid overread
|
||||||
|
.loop2:
|
||||||
|
movifnidn lineantq, lineantmp
|
||||||
|
movzx t1d, word [lineantq+xq*2]
|
||||||
|
LOWPASS t1, pixelant, spatial
|
||||||
|
mov [lineantq+xq*2], t1w
|
||||||
|
LOWPASS pixelant, t0, spatial
|
||||||
|
movifnidn frameantq, frameantmp
|
||||||
|
movzx t0d, word [frameantq+xq*2]
|
||||||
|
LOWPASS t0, t1, temporal
|
||||||
|
mov [frameantq+xq*2], t0w
|
||||||
|
movifnidn dstq, dstmp
|
||||||
|
%if %1 != 16
|
||||||
|
add t0d, (1<<(15-%1))-1
|
||||||
|
shr t0d, 16-%1 ; could eliminate this by storing from t0h, but only with some contraints on register allocation
|
||||||
|
%endif
|
||||||
|
%if %1 == 8
|
||||||
|
mov [dstq+xq], t0b
|
||||||
|
%else
|
||||||
|
mov [dstq+xq*2], t0w
|
||||||
|
%endif
|
||||||
|
inc xq
|
||||||
|
jl .loop
|
||||||
|
je .loop2
|
||||||
|
REP_RET
|
||||||
|
%endmacro ; HQDN3D_ROW
|
||||||
|
|
||||||
|
HQDN3D_ROW 8
|
||||||
|
HQDN3D_ROW 9
|
||||||
|
HQDN3D_ROW 10
|
||||||
|
HQDN3D_ROW 16
|
@ -140,6 +140,7 @@ CPUNOP amdnop
|
|||||||
%define r%1w %2w
|
%define r%1w %2w
|
||||||
%define r%1b %2b
|
%define r%1b %2b
|
||||||
%define r%1h %2h
|
%define r%1h %2h
|
||||||
|
%define %2q %2
|
||||||
%if %0 == 2
|
%if %0 == 2
|
||||||
%define r%1m %2d
|
%define r%1m %2d
|
||||||
%define r%1mp %2
|
%define r%1mp %2
|
||||||
|
Loading…
Reference in New Issue
Block a user