aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Gisquet <christophe.gisquet@gmail.com>2015-10-12 19:37:49 +0200
committerMichael Niedermayer <michael@niedermayer.cc>2015-10-13 15:34:32 +0200
commit7ece8b50b19e140ace13eda6f1a9f45f868c2528 (patch)
treeee4e986a0913996db69ad2054cc03f464cd717d8
parent4369b9dc7b2b0da594223ce46615ba8e2b4cead6 (diff)
downloadffmpeg-7ece8b50b19e140ace13eda6f1a9f45f868c2528.tar.gz
x86: simple_idct: 12bits versions
On 12 frames of a 444p 12 bits DNxHR sequence, _put function: C: 78902 decicycles in idct, 262071 runs, 73 skips avx: 32478 decicycles in idct, 262045 runs, 99 skips Difference between the 2: stddev: 0.39 PSNR:104.47 MAXDIFF: 2 This is unavoidable and due to the scale factors used in the x86 version, which cannot match the C ones. In addition, the trick of adding an initial bias to the input of a pass can overflow, as the input coefficients are already 15bits, which is the maximum this function can handle. Overall, however, the omse on 12 bits samples goes from 0.16916 to 0.16883. Reducing rowshift by 1 improves to 0.0908, but causes overflows. Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavcodec/x86/idctdsp_init.c22
-rw-r--r--libavcodec/x86/simple_idct.h6
-rw-r--r--libavcodec/x86/simple_idct10.asm16
3 files changed, 42 insertions, 2 deletions
diff --git a/libavcodec/x86/idctdsp_init.c b/libavcodec/x86/idctdsp_init.c
index 6ab262097c..bcf7e5be0e 100644
--- a/libavcodec/x86/idctdsp_init.c
+++ b/libavcodec/x86/idctdsp_init.c
@@ -86,8 +86,8 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx,
c->add_pixels_clamped = ff_add_pixels_clamped_sse2;
}
- if (ARCH_X86_64 &&
- avctx->bits_per_raw_sample == 10 && avctx->lowres == 0 &&
+ if (ARCH_X86_64 && avctx->lowres == 0) {
+ if (avctx->bits_per_raw_sample == 10 &&
(avctx->idct_algo == FF_IDCT_AUTO ||
avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
avctx->idct_algo == FF_IDCT_SIMPLE)) {
@@ -104,5 +104,23 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx,
c->idct = ff_simple_idct10_avx;
c->perm_type = FF_IDCT_PERM_TRANSPOSE;
}
+ }
+
+ if (avctx->bits_per_raw_sample == 12 &&
+ (avctx->idct_algo == FF_IDCT_AUTO ||
+ avctx->idct_algo == FF_IDCT_SIMPLEMMX)) {
+ if (EXTERNAL_SSE2(cpu_flags)) {
+ c->idct_put = ff_simple_idct12_put_sse2;
+ c->idct_add = NULL;
+ c->idct = ff_simple_idct12_sse2;
+ c->perm_type = FF_IDCT_PERM_TRANSPOSE;
+ }
+ if (EXTERNAL_AVX(cpu_flags)) {
+ c->idct_put = ff_simple_idct12_put_avx;
+ c->idct_add = NULL;
+ c->idct = ff_simple_idct12_avx;
+ c->perm_type = FF_IDCT_PERM_TRANSPOSE;
+ }
+ }
}
}
diff --git a/libavcodec/x86/simple_idct.h b/libavcodec/x86/simple_idct.h
index e8f59c1865..8eeb31e299 100644
--- a/libavcodec/x86/simple_idct.h
+++ b/libavcodec/x86/simple_idct.h
@@ -31,4 +31,10 @@ void ff_simple_idct10_avx(int16_t *block);
void ff_simple_idct10_put_sse2(uint8_t *dest, int line_size, int16_t *block);
void ff_simple_idct10_put_avx(uint8_t *dest, int line_size, int16_t *block);
+void ff_simple_idct12_sse2(int16_t *block);
+void ff_simple_idct12_avx(int16_t *block);
+
+void ff_simple_idct12_put_sse2(uint8_t *dest, int line_size, int16_t *block);
+void ff_simple_idct12_put_avx(uint8_t *dest, int line_size, int16_t *block);
+
#endif /* AVCODEC_X86_SIMPLE_IDCT_H */
diff --git a/libavcodec/x86/simple_idct10.asm b/libavcodec/x86/simple_idct10.asm
index 3af2042f08..ec388f99ed 100644
--- a/libavcodec/x86/simple_idct10.asm
+++ b/libavcodec/x86/simple_idct10.asm
@@ -29,9 +29,12 @@
SECTION_RODATA
+cextern pw_2
cextern pw_16
cextern pw_1023
+cextern pw_4095
pd_round_12: times 4 dd 1<<(12-1)
+pd_round_15: times 4 dd 1<<(15-1)
pd_round_19: times 4 dd 1<<(19-1)
%include "libavcodec/x86/simple_idct10_template.asm"
@@ -46,6 +49,19 @@ cglobal simple_idct10, 1, 1, 16
cglobal simple_idct10_put, 3, 3, 16
IDCT_FN "", 12, "", 19, 0, pw_1023
RET
+
+cglobal simple_idct12, 1, 1, 16
+ ; coeffs are already 15bits, adding the offset would cause
+ ; overflow in the input
+ IDCT_FN "", 15, pw_2, 16
+ RET
+
+cglobal simple_idct12_put, 3, 3, 16
+ ; range isn't known, so the C simple_idct range is used
+ ; Also, using a bias on input overflows, so use the bias
+ ; on output of the first butterfly instead
+ IDCT_FN "", 15, pw_2, 16, 0, pw_4095
+ RET
%endmacro
INIT_XMM sse2