diff options
author | Loren Merritt <lorenm@u.washington.edu> | 2009-02-08 17:45:30 +0000 |
---|---|---|
committer | Loren Merritt <lorenm@u.washington.edu> | 2009-02-08 17:45:30 +0000 |
commit | 3daa434a40c56deef91c9d545552349d661105e9 (patch) | |
tree | a6baca6ac5d30f4f665918fddd0cf3b5e774d5d9 | |
parent | 6166516d1f0df6cc8f96e7685e78ef75541b9698 (diff) | |
download | ffmpeg-3daa434a40c56deef91c9d545552349d661105e9.tar.gz |
ff_add_hfyu_median_prediction_mmx2
overall ffvhuff decoding speedup: 28% on core2, 25% on k8.
Originally committed as revision 17059 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/dsputil.c | 18 | ||||
-rw-r--r-- | libavcodec/dsputil.h | 1 | ||||
-rw-r--r-- | libavcodec/huffyuv.c | 32 | ||||
-rw-r--r-- | libavcodec/x86/dsputil_mmx.c | 44 | ||||
-rw-r--r-- | libavcodec/x86/dsputil_yasm.asm | 60 |
5 files changed, 130 insertions, 25 deletions
diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c index 9baa08dbda..d4d4d2d829 100644 --- a/libavcodec/dsputil.c +++ b/libavcodec/dsputil.c @@ -3542,6 +3542,23 @@ static void diff_bytes_c(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){ dst[i+0] = src1[i+0]-src2[i+0]; } +static void add_hfyu_median_prediction_c(uint8_t *dst, uint8_t *src1, uint8_t *diff, int w, int *left, int *left_top){ + int i; + uint8_t l, lt; + + l= *left; + lt= *left_top; + + for(i=0; i<w; i++){ + l= mid_pred(l, src1[i], (l + src1[i] - lt)&0xFF) + diff[i]; + lt= src1[i]; + dst[i]= l; + } + + *left= l; + *left_top= lt; +} + static void sub_hfyu_median_prediction_c(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top){ int i; uint8_t l, lt; @@ -4554,6 +4571,7 @@ void dsputil_init(DSPContext* c, AVCodecContext *avctx) c->add_bytes= add_bytes_c; c->add_bytes_l2= add_bytes_l2_c; c->diff_bytes= diff_bytes_c; + c->add_hfyu_median_prediction= add_hfyu_median_prediction_c; c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_c; c->bswap_buf= bswap_buf; #if CONFIG_PNG_DECODER diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h index fdbd90a6c1..35d870f2e6 100644 --- a/libavcodec/dsputil.h +++ b/libavcodec/dsputil.h @@ -345,6 +345,7 @@ typedef struct DSPContext { * note, this might read from src1[-1], src2[-1] */ void (*sub_hfyu_median_prediction)(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top); + void (*add_hfyu_median_prediction)(uint8_t *dst, uint8_t *top, uint8_t *diff, int w, int *left, int *left_top); /* this might write to dst[w] */ void (*add_png_paeth_prediction)(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp); void (*bswap_buf)(uint32_t *dst, const uint32_t *src, int w); diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index d3f6401b3d..741f9a49f9 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -31,7 +31,6 @@ #include "avcodec.h" #include "bitstream.h" #include "dsputil.h" -#include "mathops.h" #define VLC_BITS 11 @@ -148,23 +147,6 @@ static inline int add_left_prediction(uint8_t *dst, uint8_t *src, int w, int acc return acc; } -static inline void add_median_prediction(uint8_t *dst, uint8_t *src1, uint8_t *diff, int w, int *left, int *left_top){ - int i; - uint8_t l, lt; - - l= *left; - lt= *left_top; - - for(i=0; i<w; i++){ - l= mid_pred(l, src1[i], (l + src1[i] - lt)&0xFF) + diff[i]; - lt= src1[i]; - dst[i]= l; - } - - *left= l; - *left_top= lt; -} - static inline void add_left_prediction_bgr32(uint8_t *dst, uint8_t *src, int w, int *red, int *green, int *blue){ int i; int r,g,b; @@ -1106,12 +1088,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const /* next line except the first 4 pixels is median predicted */ lefttopy= p->data[0][3]; decode_422_bitstream(s, width-4); - add_median_prediction(p->data[0] + fake_ystride+4, p->data[0]+4, s->temp[0], width-4, &lefty, &lefttopy); + s->dsp.add_hfyu_median_prediction(p->data[0] + fake_ystride+4, p->data[0]+4, s->temp[0], width-4, &lefty, &lefttopy); if(!(s->flags&CODEC_FLAG_GRAY)){ lefttopu= p->data[1][1]; lefttopv= p->data[2][1]; - add_median_prediction(p->data[1] + fake_ustride+2, p->data[1]+2, s->temp[1], width2-2, &leftu, &lefttopu); - add_median_prediction(p->data[2] + fake_vstride+2, p->data[2]+2, s->temp[2], width2-2, &leftv, &lefttopv); + s->dsp.add_hfyu_median_prediction(p->data[1] + fake_ustride+2, p->data[1]+2, s->temp[1], width2-2, &leftu, &lefttopu); + s->dsp.add_hfyu_median_prediction(p->data[2] + fake_vstride+2, p->data[2]+2, s->temp[2], width2-2, &leftv, &lefttopv); } y++; cy++; @@ -1122,7 +1104,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const while(2*cy > y){ decode_gray_bitstream(s, width); ydst= p->data[0] + p->linesize[0]*y; - add_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); + s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); y++; } if(y>=height) break; @@ -1135,10 +1117,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const udst= p->data[1] + p->linesize[1]*cy; vdst= p->data[2] + p->linesize[2]*cy; - add_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); + s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); if(!(s->flags&CODEC_FLAG_GRAY)){ - add_median_prediction(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu); - add_median_prediction(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv); + s->dsp.add_hfyu_median_prediction(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu); + s->dsp.add_hfyu_median_prediction(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv); } } diff --git a/libavcodec/x86/dsputil_mmx.c b/libavcodec/x86/dsputil_mmx.c index a457d55ad7..0cab053c4e 100644 --- a/libavcodec/x86/dsputil_mmx.c +++ b/libavcodec/x86/dsputil_mmx.c @@ -548,6 +548,41 @@ static void add_bytes_l2_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){ dst[i] = src1[i] + src2[i]; } +#if HAVE_7REGS +static void add_hfyu_median_prediction_cmov(uint8_t *dst, uint8_t *top, uint8_t *diff, int w, int *left, int *left_top) { + x86_reg w2 = -w; + x86_reg x; + int l = *left & 0xff; + int tl = *left_top & 0xff; + int t; + __asm__ volatile( + "mov %7, %3 \n" + "1: \n" + "movzx (%3,%4), %2 \n" + "mov %2, %k3 \n" + "sub %b1, %b3 \n" + "add %b0, %b3 \n" + "mov %2, %1 \n" + "cmp %0, %2 \n" + "cmovg %0, %2 \n" + "cmovg %1, %0 \n" + "cmp %k3, %0 \n" + "cmovg %k3, %0 \n" + "mov %7, %3 \n" + "cmp %2, %0 \n" + "cmovl %2, %0 \n" + "add (%6,%4), %b0 \n" + "mov %b0, (%5,%4) \n" + "inc %4 \n" + "jl 1b \n" + :"+&q"(l), "+&q"(tl), "=&r"(t), "=&q"(x), "+&r"(w2) + :"r"(dst+w), "r"(diff+w), "rm"(top+w) + ); + *left = l; + *left_top = tl; +} +#endif + #define H263_LOOP_FILTER \ "pxor %%mm7, %%mm7 \n\t"\ "movq %0, %%mm0 \n\t"\ @@ -2328,6 +2363,7 @@ static void float_to_int16_sse2(int16_t *dst, const float *src, long len){ void ff_float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len); void ff_float_to_int16_interleave6_3dnow(int16_t *dst, const float **src, int len); void ff_float_to_int16_interleave6_3dn2(int16_t *dst, const float **src, int len); +void ff_add_hfyu_median_prediction_mmx2(uint8_t *dst, uint8_t *top, uint8_t *diff, int w, int *left, int *left_top); void ff_x264_deblock_v_luma_sse2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0); void ff_x264_deblock_h_luma_sse2(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0); void ff_x264_deblock_v8_luma_intra_mmxext(uint8_t *pix, int stride, int alpha, int beta); @@ -2760,6 +2796,14 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx) c->biweight_h264_pixels_tab[6]= ff_h264_biweight_4x4_mmx2; c->biweight_h264_pixels_tab[7]= ff_h264_biweight_4x2_mmx2; +#if HAVE_YASM + c->add_hfyu_median_prediction = ff_add_hfyu_median_prediction_mmx2; +#endif +#if HAVE_7REGS + if( mm_flags&FF_MM_3DNOW ) + c->add_hfyu_median_prediction = add_hfyu_median_prediction_cmov; +#endif + if (CONFIG_CAVS_DECODER) ff_cavsdsp_init_mmx2(c, avctx); diff --git a/libavcodec/x86/dsputil_yasm.asm b/libavcodec/x86/dsputil_yasm.asm index 91165f2fb7..9d5e62e57d 100644 --- a/libavcodec/x86/dsputil_yasm.asm +++ b/libavcodec/x86/dsputil_yasm.asm @@ -90,3 +90,63 @@ FLOAT_TO_INT16_INTERLEAVE6 3dnow FLOAT_TO_INT16_INTERLEAVE6 3dn2 %undef cvtps2pi + + +; void ff_add_hfyu_median_prediction_mmx2(uint8_t *dst, uint8_t *top, uint8_t *diff, int w, int *left, int *left_top) +cglobal add_hfyu_median_prediction_mmx2, 6,6,0, dst, top, diff, w, left, left_top + movq mm0, [topq] + movq mm2, mm0 + movd mm4, [left_topq] + psllq mm2, 8 + movq mm1, mm0 + por mm4, mm2 + movd mm3, [leftq] + psubb mm0, mm4 ; t-tl + add dstq, wq + add topq, wq + add diffq, wq + neg wq + jmp .skip +.loop: + movq mm4, [topq+wq] + movq mm0, mm4 + psllq mm4, 8 + por mm4, mm1 + movq mm1, mm0 ; t + psubb mm0, mm4 ; t-tl +.skip: + movq mm2, [diffq+wq] +%assign i 0 +%rep 8 + movq mm4, mm0 + paddb mm4, mm3 ; t-tl+l + movq mm5, mm3 + pmaxub mm3, mm1 + pminub mm5, mm1 + pminub mm3, mm4 + pmaxub mm3, mm5 ; median + paddb mm3, mm2 ; +residual +%if i==0 + movq mm7, mm3 + psllq mm7, 56 +%else + movq mm6, mm3 + psrlq mm7, 8 + psllq mm6, 56 + por mm7, mm6 +%endif +%if i<7 + psrlq mm0, 8 + psrlq mm1, 8 + psrlq mm2, 8 +%endif +%assign i i+1 +%endrep + movq [dstq+wq], mm7 + add wq, 8 + jl .loop + movzx r2d, byte [dstq-1] + mov [leftq], r2d + movzx r2d, byte [topq-1] + mov [left_topq], r2d + RET |