changeset 1784:65f7bd09f37b libavcodec

quantizer noise shaping optimization
author michael
date Fri, 06 Feb 2004 02:12:37 +0000
parents 66ae3c109d90
children 14d918d0ef42
files dsputil.c dsputil.h i386/dsputil_mmx.c mpegvideo.c
diffstat 4 files changed, 132 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/dsputil.c	Thu Feb 05 05:22:44 2004 +0000
+++ b/dsputil.c	Fri Feb 06 02:12:37 2004 +0000
@@ -2532,6 +2532,29 @@
     return s;
 }
 
+static int try_8x8basis_c(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale){
+    int i;
+    unsigned int sum=0;
+
+    for(i=0; i<8*8; i++){
+        int b= rem[i] + ((basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT));
+        int w= weight[i];
+        b>>= RECON_SHIFT;
+        assert(-512<b && b<512);
+
+        sum += (w*b)*(w*b)>>4;
+    }
+    return sum>>2;
+}
+
+static void add_8x8basis_c(int16_t rem[64], int16_t basis[64], int scale){
+    int i;
+
+    for(i=0; i<8*8; i++){
+        rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT);
+    }    
+}
+
 /**
  * permutes an 8x8 block.
  * @param block the block which will be permuted according to the given permutation vector
@@ -3235,6 +3258,9 @@
     
     c->h263_h_loop_filter= h263_h_loop_filter_c;
     c->h263_v_loop_filter= h263_v_loop_filter_c;
+    
+    c->try_8x8basis= try_8x8basis_c;
+    c->add_8x8basis= add_8x8basis_c;
 
 #ifdef HAVE_MMX
     dsputil_init_mmx(c, avctx);
--- a/dsputil.h	Thu Feb 05 05:22:44 2004 +0000
+++ b/dsputil.h	Fri Feb 06 02:12:37 2004 +0000
@@ -285,6 +285,11 @@
 #define FF_SIMPLE_IDCT_PERM 3
 #define FF_TRANSPOSE_IDCT_PERM 4
 
+    int (*try_8x8basis)(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale);
+    void (*add_8x8basis)(int16_t rem[64], int16_t basis[64], int scale);
+#define BASIS_SHIFT 16
+#define RECON_SHIFT 6
+
 } DSPContext;
 
 void dsputil_static_init(void);
--- a/i386/dsputil_mmx.c	Thu Feb 05 05:22:44 2004 +0000
+++ b/i386/dsputil_mmx.c	Fri Feb 06 02:12:37 2004 +0000
@@ -1973,6 +1973,92 @@
     c->put_no_rnd_ ## postfix1 = put_no_rnd_ ## postfix2;\
     c->avg_ ## postfix1 = avg_ ## postfix2;
 
+static int try_8x8basis_mmx(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale){
+    int i=0;
+    
+    assert(ABS(scale) < 256);
+    scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
+
+    asm volatile(
+        "pcmpeqw %%mm6, %%mm6		\n\t" // -1w
+        "psrlw $15, %%mm6		\n\t" //  1w
+        "pxor %%mm7, %%mm7		\n\t"
+        "movd  %4, %%mm5		\n\t" 
+        "punpcklwd %%mm5, %%mm5		\n\t" 
+        "punpcklwd %%mm5, %%mm5		\n\t" 
+        "1:				\n\t"
+        "movq  (%1, %0), %%mm0		\n\t" 
+        "movq  8(%1, %0), %%mm1		\n\t"
+        "pmulhw %%mm5, %%mm0		\n\t"
+        "pmulhw %%mm5, %%mm1		\n\t"
+        "paddw %%mm6, %%mm0		\n\t"
+        "paddw %%mm6, %%mm1		\n\t"
+        "psraw $1, %%mm0		\n\t"
+        "psraw $1, %%mm1		\n\t"
+        "paddw (%2, %0), %%mm0		\n\t"
+        "paddw 8(%2, %0), %%mm1		\n\t"
+        "psraw $6, %%mm0		\n\t"
+        "psraw $6, %%mm1		\n\t"
+        "pmullw (%3, %0), %%mm0		\n\t"
+        "pmullw 8(%3, %0), %%mm1	\n\t"
+        "pmaddwd %%mm0, %%mm0		\n\t"
+        "pmaddwd %%mm1, %%mm1		\n\t"
+        "paddd %%mm1, %%mm0		\n\t"
+        "psrld $4, %%mm0		\n\t"
+        "paddd %%mm0, %%mm7		\n\t"
+        "addl $16, %0			\n\t"
+        "cmpl $128, %0			\n\t" //FIXME optimize & bench
+        " jb 1b				\n\t"
+        "movq %%mm7, %%mm6		\n\t"
+        "psrlq $32, %%mm7		\n\t"
+        "paddd %%mm6, %%mm7		\n\t"
+        "psrld $2, %%mm7		\n\t"
+        "movd %%mm7, %0			\n\t"
+        
+        : "+r" (i)
+        : "r"(basis), "r"(rem), "r"(weight), "g"(scale)
+    );
+    return i;
+}
+
+static void add_8x8basis_mmx(int16_t rem[64], int16_t basis[64], int scale){
+    int i=0;
+    
+    if(ABS(scale) < 256){
+        scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
+        asm volatile(
+                "pcmpeqw %%mm6, %%mm6		\n\t" // -1w
+                "psrlw $15, %%mm6		\n\t" //  1w
+                "movd  %3, %%mm5		\n\t" 
+                "punpcklwd %%mm5, %%mm5		\n\t" 
+                "punpcklwd %%mm5, %%mm5		\n\t" 
+                "1:				\n\t"
+                "movq  (%1, %0), %%mm0		\n\t" 
+                "movq  8(%1, %0), %%mm1		\n\t"
+                "pmulhw %%mm5, %%mm0		\n\t"
+                "pmulhw %%mm5, %%mm1		\n\t"
+                "paddw %%mm6, %%mm0		\n\t" 
+                "paddw %%mm6, %%mm1		\n\t"
+                "psraw $1, %%mm0		\n\t"
+                "psraw $1, %%mm1		\n\t"
+                "paddw (%2, %0), %%mm0		\n\t"
+                "paddw 8(%2, %0), %%mm1		\n\t"
+                "movq %%mm0, (%2, %0)		\n\t"
+                "movq %%mm1, 8(%2, %0)		\n\t"
+                "addl $16, %0			\n\t"
+                "cmpl $128, %0			\n\t" //FIXME optimize & bench
+                " jb 1b				\n\t"
+                
+                : "+r" (i)
+                : "r"(basis), "r"(rem), "g"(scale)
+        );
+    }else{
+        for(i=0; i<8*8; i++){
+            rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT);
+        }    
+    }
+}
+    
 /* external functions, from idct_mmx.c */
 void ff_mmx_idct(DCTELEM *block);
 void ff_mmxext_idct(DCTELEM *block);
@@ -2125,10 +2211,16 @@
         if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
             c->vsad[0] = vsad16_mmx;
         }
+        
+        if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
+            c->try_8x8basis= try_8x8basis_mmx;
+        }
+        c->add_8x8basis= add_8x8basis_mmx;
+        
 #endif //CONFIG_ENCODERS
 
         c->h263_v_loop_filter= h263_v_loop_filter_mmx;
-        c->h263_h_loop_filter= h263_h_loop_filter_mmx;
+        c->h263_h_loop_filter= h263_h_loop_filter_mmx;        
         
         if (mm_flags & MM_MMXEXT) {
             c->put_pixels_tab[0][1] = put_pixels16_x2_mmx2;
--- a/mpegvideo.c	Thu Feb 05 05:22:44 2004 +0000
+++ b/mpegvideo.c	Fri Feb 06 02:12:37 2004 +0000
@@ -4915,8 +4915,6 @@
     return last_non_zero;
 }
 
-#define BASIS_SHIFT 16
-#define RECON_SHIFT 6
 //#define REFINE_STATS 1
 static int16_t basis[64][64];
 
@@ -4939,29 +4937,6 @@
     }
 }
 
-static int try_basis(int16_t rem[64], int16_t weight[64], int index, int scale){
-    int i;
-    unsigned int sum=0;
-
-    for(i=0; i<8*8; i++){
-        int b= rem[i] - ((basis[index][i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT));
-        int w= weight[i];
-        b= (b + (1<<(RECON_SHIFT-1))) >> RECON_SHIFT;
-        assert(-512<b && b<512);
-
-        sum += (w*b)*(w*b)>>4;
-    }
-    return sum>>2;
-}
-
-static void add_basis(int16_t rem[64], int index, int scale){
-    int i;
-
-    for(i=0; i<8*8; i++){
-        rem[i] -= (basis[index][i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT);
-    }    
-}
-
 static int dct_quantize_refine(MpegEncContext *s, //FIXME breaks denoise?
                         DCTELEM *block, int16_t *weight, DCTELEM *orig,
                         int n, int qscale){
@@ -5028,8 +5003,9 @@
 #ifdef REFINE_STATS
 {START_TIMER
 #endif
-    for(i=0; i<64; i++){ //FIXME memsetw or similar
-        rem[i]= (orig[i]<<RECON_SHIFT) - dc; //FIXME  use orig dirrectly insteadof copying to rem[]
+    dc += (1<<(RECON_SHIFT-1));
+    for(i=0; i<64; i++){
+        rem[i]= dc - (orig[i]<<RECON_SHIFT); //FIXME  use orig dirrectly insteadof copying to rem[]
     }
 #ifdef REFINE_STATS
 STOP_TIMER("memset rem[]")}
@@ -5067,7 +5043,7 @@
             run_tab[rle_index++]=run;
             run=0;
 
-            add_basis(rem, j, coeff);
+            s->dsp.add_8x8basis(rem, basis[j], coeff);
         }else{
             run++;
         }
@@ -5081,7 +5057,7 @@
 {START_TIMER
 #endif
     for(;;){
-        int best_score=try_basis(rem, weight, 0, 0);
+        int best_score=s->dsp.try_8x8basis(rem, weight, basis[0], 0);
         int nochange_score= best_score;
         int best_coeff=0;
         int best_change=0;
@@ -5105,7 +5081,7 @@
                 if(new_coeff >= 2048 || new_coeff < 0)
                     continue;
 
-                score= try_basis(rem, weight, 0, new_coeff - old_coeff);
+                score= s->dsp.try_8x8basis(rem, weight, basis[0], new_coeff - old_coeff);
                 if(score<best_score){
                     best_score= score;
                     best_coeff= 0;
@@ -5221,7 +5197,7 @@
                 unquant_change= new_coeff - old_coeff;
                 assert((score < 100*lambda && score > -100*lambda) || lambda==0);
                 
-                score+= try_basis(rem, weight, j, unquant_change);
+                score+= s->dsp.try_8x8basis(rem, weight, basis[j], unquant_change);
                 if(score<best_score){
                     best_score= score;
                     best_coeff= i;
@@ -5295,7 +5271,7 @@
                  }
             }
             
-            add_basis(rem, j, best_unquant_change);
+            s->dsp.add_8x8basis(rem, basis[j], best_unquant_change);
         }else{
             break;
         }