changeset 1001:95cbffdc98a9 libavcodec

dct_unquantize_h263_altivec by (Romain Dolbeau <dolbeaur at club-internet dot fr>)
author michaelni
date Sun, 12 Jan 2003 13:29:24 +0000
parents 3e1f39583bee
children e89b11e07ee7
files ppc/gmc_altivec.c ppc/mpegvideo_altivec.c ppc/mpegvideo_ppc.c
diffstat 3 files changed, 125 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ppc/gmc_altivec.c	Sun Jan 12 13:13:52 2003 +0000
+++ b/ppc/gmc_altivec.c	Sun Jan 12 13:29:24 2003 +0000
@@ -1,5 +1,5 @@
 /*
- * GMC (???)
+ * GMC (Global Motion Compensation)
  * AltiVec-enabled
  * Copyright (c) 2003 Romain Dolbeau <romain@dolbeau.org>
  *
--- a/ppc/mpegvideo_altivec.c	Sun Jan 12 13:13:52 2003 +0000
+++ b/ppc/mpegvideo_altivec.c	Sun Jan 12 13:29:24 2003 +0000
@@ -503,3 +503,124 @@
     return lastNonZero;
 }
 
+/*
+  AltiVec version of dct_unquantize_h263
+  this code assumes `block' is 16 bytes-aligned
+*/
+void dct_unquantize_h263_altivec(MpegEncContext *s, 
+                                 DCTELEM *block, int n, int qscale)
+{
+    int i, level, qmul, qadd;
+    int nCoeffs;
+    
+    assert(s->block_last_index[n]>=0);
+    
+    qadd = (qscale - 1) | 1;
+    qmul = qscale << 1;
+    
+    if (s->mb_intra) {
+        if (!s->h263_aic) {
+            if (n < 4) 
+                block[0] = block[0] * s->y_dc_scale;
+            else
+                block[0] = block[0] * s->c_dc_scale;
+        }else
+            qadd = 0;
+        i = 1;
+        nCoeffs= 63; //does not allways use zigzag table 
+    } else {
+        i = 0;
+        nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
+    }
+
+#if 0
+    for(;i<=nCoeffs;i++) {
+        level = block[i];
+        if (level) {
+            if (level < 0) {
+                level = level * qmul - qadd;
+            } else {
+                level = level * qmul + qadd;
+            }
+            block[i] = level;
+        }
+    }
+#else
+    {
+      register const vector short vczero = (const vector short)(0);
+      short __attribute__ ((aligned(16))) qmul8[] =
+          {
+            qmul, qmul, qmul, qmul,
+            qmul, qmul, qmul, qmul
+          };
+      short __attribute__ ((aligned(16))) qadd8[] =
+          {
+            qadd, qadd, qadd, qadd,
+            qadd, qadd, qadd, qadd
+          };
+      short __attribute__ ((aligned(16))) nqadd8[] =
+          {
+            -qadd, -qadd, -qadd, -qadd,
+            -qadd, -qadd, -qadd, -qadd
+          };
+      register vector short blockv, qmulv, qaddv, nqaddv, temp1;
+      register vector bool short blockv_null, blockv_neg;
+      register short backup_0 = block[0];
+      register int j = 0;
+      
+      qmulv = vec_ld(0, qmul8);
+      qaddv = vec_ld(0, qadd8);
+      nqaddv = vec_ld(0, nqadd8);
+
+      // first make sure block[j] is 16 bytes-aligned
+      for(j = 0; (j <= nCoeffs) && ((((unsigned long)block) + (j << 1)) & 0x0000000F) ; j++) {
+        level = block[j];
+        if (level) {
+          if (level < 0) {
+                level = level * qmul - qadd;
+            } else {
+                level = level * qmul + qadd;
+            }
+            block[j] = level;
+        }
+      }
+      
+      // vectorize all the 16 bytes-aligned blocks
+      // of 8 elements
+      for(; (j + 7) <= nCoeffs ; j+=8)
+      {
+        blockv = vec_ld(j << 1, block);
+        blockv_neg = vec_cmplt(blockv, vczero);
+        blockv_null = vec_cmpeq(blockv, vczero);
+        // choose between +qadd or -qadd as the third operand
+        temp1 = vec_sel(qaddv, nqaddv, blockv_neg);
+        // multiply & add (block{i,i+7} * qmul [+-] qadd)
+        temp1 = vec_mladd(blockv, qmulv, temp1);
+        // put 0 where block[{i,i+7} used to have 0
+        blockv = vec_sel(temp1, blockv, blockv_null);
+        vec_st(blockv, j << 1, block);
+      }
+
+      // if nCoeffs isn't a multiple of 8, finish the job
+      // using good old scalar units.
+      // (we could do it using a truncated vector,
+      // but I'm not sure it's worth the hassle)
+      for(; j <= nCoeffs ; j++) {
+        level = block[j];
+        if (level) {
+          if (level < 0) {
+                level = level * qmul - qadd;
+            } else {
+                level = level * qmul + qadd;
+            }
+            block[j] = level;
+        }
+      }
+      
+      if (i == 1)
+      { // cheat. this avoid special-casing the first iteration
+        block[0] = backup_0;
+      }
+    }
+#endif
+}
--- a/ppc/mpegvideo_ppc.c	Sun Jan 12 13:13:52 2003 +0000
+++ b/ppc/mpegvideo_ppc.c	Sun Jan 12 13:29:24 2003 +0000
@@ -27,6 +27,8 @@
 extern int dct_quantize_altivec(MpegEncContext *s,  
         DCTELEM *block, int n,
         int qscale, int *overflow);
+extern void dct_unquantize_h263_altivec(MpegEncContext *s,
+                                        DCTELEM *block, int n, int qscale);
 
 extern void idct_put_altivec(UINT8 *dest, int line_size, INT16 *block);
 extern void idct_add_altivec(UINT8 *dest, int line_size, INT16 *block);
@@ -66,6 +68,7 @@
                 (s->avctx->dct_algo == FF_DCT_ALTIVEC))
         {
             s->dct_quantize = dct_quantize_altivec;
+            s->dct_unquantize_h263 = dct_unquantize_h263_altivec;
         }
     } else
 #endif