changeset 8760:31138c296ac6 libavcodec

ff_add_hfyu_median_prediction_mmx2 overall ffvhuff decoding speedup: 28% on core2, 25% on k8.
author lorenm
date Sun, 08 Feb 2009 17:45:30 +0000
parents 4cea2f47219a
children 2a43b46067c4
files dsputil.c dsputil.h huffyuv.c x86/dsputil_mmx.c x86/dsputil_yasm.asm
diffstat 5 files changed, 130 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/dsputil.c	Sun Feb 08 17:44:04 2009 +0000
+++ b/dsputil.c	Sun Feb 08 17:45:30 2009 +0000
@@ -3542,6 +3542,23 @@
         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 @@
     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
--- a/dsputil.h	Sun Feb 08 17:44:04 2009 +0000
+++ b/dsputil.h	Sun Feb 08 17:45:30 2009 +0000
@@ -345,6 +345,7 @@
      * 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);
--- a/huffyuv.c	Sun Feb 08 17:44:04 2009 +0000
+++ b/huffyuv.c	Sun Feb 08 17:45:30 2009 +0000
@@ -31,7 +31,6 @@
 #include "avcodec.h"
 #include "bitstream.h"
 #include "dsputil.h"
-#include "mathops.h"
 
 #define VLC_BITS 11
 
@@ -148,23 +147,6 @@
     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 @@
                 /* 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 @@
                         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 @@
                     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);
                     }
                 }
 
--- a/x86/dsputil_mmx.c	Sun Feb 08 17:44:04 2009 +0000
+++ b/x86/dsputil_mmx.c	Sun Feb 08 17:45:30 2009 +0000
@@ -548,6 +548,41 @@
         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 @@
 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 @@
             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);
 
--- a/x86/dsputil_yasm.asm	Sun Feb 08 17:44:04 2009 +0000
+++ b/x86/dsputil_yasm.asm	Sun Feb 08 17:45:30 2009 +0000
@@ -90,3 +90,63 @@
 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