rv34: Intra 16x16 handling
authorChristophe GISQUET <christophe.gisquet@gmail.com>
Mon, 2 Jan 2012 23:22:11 +0000 (00:22 +0100)
committerJanne Grunau <janne-libav@jannau.net>
Sun, 15 Jan 2012 23:41:51 +0000 (00:41 +0100)
Extract processing of intra 16x16 blocks from intra macroblock
processing.
Also implement a function performing inverse transform and block
reconstruction for DC-only blocks in 1 pass instead of 2.

libavcodec/rv34.c
libavcodec/rv34dsp.c
libavcodec/rv34dsp.h
libavcodec/x86/rv34dsp.asm
libavcodec/x86/rv34dsp_init.c

index 48f34b9..478c93a 100644 (file)
@@ -982,15 +982,6 @@ static void rv34_pred_4x4_block(RV34DecContext *r, uint8_t *dst, int stride, int
     r->h.pred4x4[itype](dst, prev, stride);
 }
 
-/** add_pixels_clamped for 4x4 block */
-static void rv34_add_4x4_block(uint8_t *dst, int stride, DCTELEM block[64], int off)
-{
-    int x, y;
-    for(y = 0; y < 4; y++)
-        for(x = 0; x < 4; x++)
-            dst[x + y*stride] = av_clip_uint8(dst[x + y*stride] + block[off + x+y*8]);
-}
-
 static inline int adjust_pred16(int itype, int up, int left)
 {
     if(!up && !left)
@@ -1007,15 +998,20 @@ static inline int adjust_pred16(int itype, int up, int left)
     return itype;
 }
 
-static void rv34_output_macroblock(RV34DecContext *r, int8_t *intra_types, int cbp, int is16)
+static void rv34_output_i16x16(RV34DecContext *r, int8_t *intra_types, int cbp)
 {
-    MpegEncContext *s = &r->s;
-    DSPContext *dsp = &s->dsp;
-    int i, j;
-    uint8_t *Y, *U, *V;
-    int itype;
-    int avail[6*8] = {0};
-    int idx;
+    LOCAL_ALIGNED_16(DCTELEM, block16, [64]);
+    MpegEncContext *s    = &r->s;
+    DSPContext     *dsp  = &s->dsp;
+    GetBitContext  *gb   = &s->gb;
+    int             q_dc = rv34_qscale_tab[ r->luma_dc_quant_i[s->qscale] ],
+                    q_ac = rv34_qscale_tab[s->qscale];
+    uint8_t        *dst  = s->dest[0];
+    DCTELEM        *ptr  = s->block[0];
+    int       avail[6*8] = {0};
+    int i, j, itype, has_ac;
+
+    memset(block16, 0, 64 * sizeof(*block16));
 
     // Set neighbour information.
     if(r->avail_cache[1])
@@ -1031,52 +1027,142 @@ static void rv34_output_macroblock(RV34DecContext *r, int8_t *intra_types, int c
     if(r->avail_cache[9])
         avail[24] = avail[32] = 1;
 
-    Y = s->dest[0];
-    U = s->dest[1];
-    V = s->dest[2];
-    if(!is16){
-        for(j = 0; j < 4; j++){
-            idx = 9 + j*8;
-            for(i = 0; i < 4; i++, cbp >>= 1, Y += 4, idx++){
-                rv34_pred_4x4_block(r, Y, s->linesize, ittrans[intra_types[i]], avail[idx-8], avail[idx-1], avail[idx+7], avail[idx-7]);
-                avail[idx] = 1;
-                if(cbp & 1)
-                    rv34_add_4x4_block(Y, s->linesize, s->block[(i>>1)+(j&2)], (i&1)*4+(j&1)*32);
+    has_ac = rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac);
+    if(has_ac)
+        r->rdsp.rv34_inv_transform_tab[1](block16);
+    else
+        r->rdsp.rv34_inv_transform_dc_tab[1](block16);
+
+    itype = ittrans16[intra_types[0]];
+    itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
+    r->h.pred16x16[itype](dst, s->linesize);
+
+    dsp->clear_block(ptr);
+    for(j = 0; j < 4; j++){
+        for(i = 0; i < 4; i++, cbp >>= 1){
+            int dc = block16[i + j*8];
+
+            if(cbp & 1){
+                has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
+            }else
+                has_ac = 0;
+
+            if(has_ac){
+                ptr[0] = dc;
+                r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr);
+                dsp->clear_block(ptr);
+            }else
+                r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc);
+        }
+
+        dst += 4*s->linesize;
+    }
+
+    itype = ittrans16[intra_types[0]];
+    if(itype == PLANE_PRED8x8) itype = DC_PRED8x8;
+    itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
+
+    q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
+    q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
+
+    for(j = 1; j < 3; j++){
+        dst = s->dest[j];
+        r->h.pred8x8[itype](dst, s->uvlinesize);
+        for(i = 0; i < 4; i++, cbp >>= 1){
+            uint8_t *pdst;
+            if(!(cbp & 1)) continue;
+            pdst   = dst + (i&1)*4 + (i&2)*2*s->uvlinesize;
+
+            has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac);
+            if(has_ac){
+                r->rdsp.rv34_idct_add(pdst, s->uvlinesize, ptr);
+                dsp->clear_block(ptr);
+            }else{
+                r->rdsp.rv34_idct_dc_add(pdst, s->uvlinesize, ptr[0]);
+                ptr[0] = 0;
             }
-            Y += s->linesize * 4 - 4*4;
-            intra_types += r->intra_types_stride;
         }
-        intra_types -= r->intra_types_stride * 4;
+    }
+}
+
+static void rv34_output_intra(RV34DecContext *r, int8_t *intra_types, int cbp)
+{
+    MpegEncContext *s   = &r->s;
+    DSPContext     *dsp = &s->dsp;
+    GetBitContext  *gb  = &s->gb;
+    DCTELEM        *ptr = s->block[0];
+    uint8_t        *dst = s->dest[0];
+    int      avail[6*8] = {0};
+    int i, j, k;
+    int idx, has_ac;
+    int q_ac, q_dc;
+
+    // Set neighbour information.
+    if(r->avail_cache[1])
+        avail[0] = 1;
+    if(r->avail_cache[2])
+        avail[1] = avail[2] = 1;
+    if(r->avail_cache[3])
+        avail[3] = avail[4] = 1;
+    if(r->avail_cache[4])
+        avail[5] = 1;
+    if(r->avail_cache[5])
+        avail[8] = avail[16] = 1;
+    if(r->avail_cache[9])
+        avail[24] = avail[32] = 1;
+
+    q_ac = rv34_qscale_tab[s->qscale];
+    for(j = 0; j < 4; j++){
+        idx = 9 + j*8;
+        for(i = 0; i < 4; i++, cbp >>= 1, dst += 4, idx++){
+            rv34_pred_4x4_block(r, dst, s->linesize, ittrans[intra_types[i]], avail[idx-8], avail[idx-1], avail[idx+7], avail[idx-7]);
+            avail[idx] = 1;
+            if(!(cbp & 1)) continue;
+
+            has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
+            if(has_ac){
+                r->rdsp.rv34_idct_add(dst, s->linesize, ptr);
+                dsp->clear_block(ptr);
+            }else{
+                r->rdsp.rv34_idct_dc_add(dst, s->linesize, ptr[0]);
+                ptr[0] = 0;
+            }
+        }
+        dst += s->linesize * 4 - 4*4;
+        intra_types += r->intra_types_stride;
+    }
+
+    intra_types -= r->intra_types_stride * 4;
+
+    q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
+    q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
+
+    for(k = 0; k < 2; k++){
+        dst = s->dest[1+k];
         fill_rectangle(r->avail_cache + 6, 2, 2, 4, 0, 4);
+
         for(j = 0; j < 2; j++){
-            idx = 6 + j*4;
-            for(i = 0; i < 2; i++, cbp >>= 1, idx++){
-                rv34_pred_4x4_block(r, U + i*4 + j*4*s->uvlinesize, s->uvlinesize, ittrans[intra_types[i*2+j*2*r->intra_types_stride]], r->avail_cache[idx-4], r->avail_cache[idx-1], !i && !j, r->avail_cache[idx-3]);
-                rv34_pred_4x4_block(r, V + i*4 + j*4*s->uvlinesize, s->uvlinesize, ittrans[intra_types[i*2+j*2*r->intra_types_stride]], r->avail_cache[idx-4], r->avail_cache[idx-1], !i && !j, r->avail_cache[idx-3]);
-                r->avail_cache[idx] = 1;
-                if(cbp & 0x01)
-                    rv34_add_4x4_block(U + i*4 + j*4*s->uvlinesize, s->uvlinesize, s->block[4], i*4+j*32);
-                if(cbp & 0x10)
-                    rv34_add_4x4_block(V + i*4 + j*4*s->uvlinesize, s->uvlinesize, s->block[5], i*4+j*32);
+            int* acache = r->avail_cache + 6 + j*4;
+            for(i = 0; i < 2; i++, cbp >>= 1, acache++){
+                int itype = ittrans[intra_types[i*2+j*2*r->intra_types_stride]];
+                rv34_pred_4x4_block(r, dst+4*i, s->uvlinesize, itype, acache[-4], acache[-1], !i && !j, acache[-3]);
+                acache[0] = 1;
+
+                if(!(cbp&1)) continue;
+
+                has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac);
+                if(has_ac){
+                    r->rdsp.rv34_idct_add(dst + 4*i, s->uvlinesize, ptr);
+                    dsp->clear_block(ptr);
+                }
+                else {
+                    r->rdsp.rv34_idct_dc_add(dst + 4*i, s->uvlinesize, ptr[0]);
+                    ptr[0] = 0;
+                }
             }
+
+            dst += 4*s->uvlinesize;
         }
-    }else{
-        itype = ittrans16[intra_types[0]];
-        itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
-        r->h.pred16x16[itype](Y, s->linesize);
-        dsp->add_pixels_clamped(s->block[0], Y,     s->linesize);
-        dsp->add_pixels_clamped(s->block[1], Y + 8, s->linesize);
-        Y += s->linesize * 8;
-        dsp->add_pixels_clamped(s->block[2], Y,     s->linesize);
-        dsp->add_pixels_clamped(s->block[3], Y + 8, s->linesize);
-
-        itype = ittrans16[intra_types[0]];
-        if(itype == PLANE_PRED8x8) itype = DC_PRED8x8;
-        itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
-        r->h.pred8x8[itype](U, s->uvlinesize);
-        dsp->add_pixels_clamped(s->block[4], U, s->uvlinesize);
-        r->h.pred8x8[itype](V, s->uvlinesize);
-        dsp->add_pixels_clamped(s->block[5], V, s->uvlinesize);
     }
 }
 
@@ -1185,6 +1271,12 @@ static int rv34_decode_inter_macroblock(RV34DecContext *r, int8_t *intra_types)
     if(cbp == -1)
         return -1;
 
+    if (IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos])){
+        if(r->is16) rv34_output_i16x16(r, intra_types, cbp);
+        else        rv34_output_intra(r, intra_types, cbp);
+        return 0;
+    }
+
     if(r->is16){
         int luma_dc_quant = r->block_type == RV34_MB_P_MIX16x16
                           ? r->luma_dc_quant_p[s->qscale]
@@ -1243,10 +1335,7 @@ static int rv34_decode_inter_macroblock(RV34DecContext *r, int8_t *intra_types)
         else
             r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
     }
-    if (IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos]))
-        rv34_output_macroblock(r, intra_types, cbp2, r->is16);
-    else
-        rv34_apply_differences(r, cbp2);
+    rv34_apply_differences(r, cbp2);
 
     return 0;
 }
@@ -1254,12 +1343,7 @@ static int rv34_decode_inter_macroblock(RV34DecContext *r, int8_t *intra_types)
 static int rv34_decode_intra_macroblock(RV34DecContext *r, int8_t *intra_types)
 {
     MpegEncContext *s = &r->s;
-    GetBitContext *gb = &s->gb;
-    int cbp, cbp2;
-    int q_dc, q_ac, has_ac;
-    int i, blknum, blkoff;
-    LOCAL_ALIGNED_16(DCTELEM, block16, [64]);
-    int dist;
+    int cbp, dist;
     int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
 
     // Calculate which neighbours are available. Maybe it's worth optimizing too.
@@ -1278,74 +1362,21 @@ static int rv34_decode_intra_macroblock(RV34DecContext *r, int8_t *intra_types)
         r->avail_cache[1] = s->current_picture_ptr->f.mb_type[mb_pos - s->mb_stride - 1];
 
     s->qscale = r->si.quant;
-    cbp = cbp2 = rv34_decode_intra_mb_header(r, intra_types);
+    cbp = rv34_decode_intra_mb_header(r, intra_types);
     r->cbp_luma  [mb_pos] = cbp;
     r->cbp_chroma[mb_pos] = cbp >> 16;
     r->deblock_coefs[mb_pos] = 0xFFFF;
-     s->current_picture_ptr->f.qscale_table[mb_pos] = s->qscale;
+    s->current_picture_ptr->f.qscale_table[mb_pos] = s->qscale;
 
     if(cbp == -1)
         return -1;
 
     if(r->is16){
-        int luma_dc_quant = r->block_type == RV34_MB_P_MIX16x16
-                          ? r->luma_dc_quant_p[s->qscale]
-                          : r->luma_dc_quant_i[s->qscale];
-        q_dc = rv34_qscale_tab[luma_dc_quant];
-        q_ac = rv34_qscale_tab[s->qscale];
-        s->dsp.clear_block(block16);
-        if (rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac))
-            r->rdsp.rv34_inv_transform_tab[1](block16);
-        else
-            r->rdsp.rv34_inv_transform_dc_tab[1](block16);
-
-        q_ac = rv34_qscale_tab[s->qscale];
-        for(i = 0; i < 16; i++, cbp >>= 1){
-            DCTELEM *ptr;
-            blknum = ((i & 2) >> 1) + ((i & 8) >> 2);
-            blkoff = ((i & 1) << 2) + ((i & 4) << 3);
-            ptr    = s->block[blknum] + blkoff;
-            if(cbp & 1)
-                has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
-            else
-                has_ac = 0;
-            ptr[0] = block16[(i & 3) | ((i & 0xC) << 1)];
-            if(has_ac)
-                r->rdsp.rv34_inv_transform_tab[0](ptr);
-            else
-                r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
-        }
-    }else{
-        q_ac = rv34_qscale_tab[s->qscale];
-        for(i = 0; i < 16; i++, cbp >>= 1){
-            DCTELEM *ptr;
-            if(!(cbp & 1)) continue;
-            blknum = ((i & 2) >> 1) + ((i & 8) >> 2);
-            blkoff = ((i & 1) << 2) + ((i & 4) << 3);
-            ptr    = s->block[blknum] + blkoff;
-            has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
-            if(has_ac)
-                r->rdsp.rv34_inv_transform_tab[0](ptr);
-            else
-                r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
-        }
-    }
-
-    q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
-    q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
-    for(; i < 24; i++, cbp >>= 1){
-        DCTELEM *ptr;
-        if(!(cbp & 1)) continue;
-        blknum = ((i & 4) >> 2) + 4;
-        blkoff = ((i & 1) << 2) + ((i & 2) << 4);
-        ptr    = s->block[blknum] + blkoff;
-        if (rv34_decode_block(ptr, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac))
-            r->rdsp.rv34_inv_transform_tab[0](ptr);
-        else
-            r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
+        rv34_output_i16x16(r, intra_types, cbp);
+        return 0;
     }
-    rv34_output_macroblock(r, intra_types, cbp2, r->is16);
 
+    rv34_output_intra(r, intra_types, cbp);
     return 0;
 }
 
index 1767be4..91c455a 100644 (file)
@@ -32,7 +32,7 @@
  * @{
  */
 
-static av_always_inline void rv34_row_transform(int temp[16], DCTELEM *block)
+static av_always_inline void rv34_row_transform(int temp[16], const DCTELEM *block)
 {
     int i;
 
@@ -72,6 +72,32 @@ static void rv34_inv_transform_c(DCTELEM *block){
     }
 }
 
+/**
+ * Real Video 3.0/4.0 inverse transform + sample reconstruction
+ * Code is almost the same as in SVQ3, only scaling is different.
+ */
+static void rv34_idct_add_c(uint8_t *dst, int stride, const DCTELEM *block){
+    int      temp[16];
+    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+    int      i;
+
+    rv34_row_transform(temp, block);
+
+    for(i = 0; i < 4; i++){
+        const int z0 = 13*(temp[4*0+i] +    temp[4*2+i]) + 0x200;
+        const int z1 = 13*(temp[4*0+i] -    temp[4*2+i]) + 0x200;
+        const int z2 =  7* temp[4*1+i] - 17*temp[4*3+i];
+        const int z3 = 17* temp[4*1+i] +  7*temp[4*3+i];
+
+        dst[0] = cm[ dst[0] + ( (z0 + z3) >> 10 ) ];
+        dst[1] = cm[ dst[1] + ( (z1 + z2) >> 10 ) ];
+        dst[2] = cm[ dst[2] + ( (z1 - z2) >> 10 ) ];
+        dst[3] = cm[ dst[3] + ( (z0 - z3) >> 10 ) ];
+
+        dst  += stride;
+    }
+}
+
 /**
  * RealVideo 3.0/4.0 inverse transform for DC block
  *
@@ -97,6 +123,22 @@ static void rv34_inv_transform_noround_c(DCTELEM *block){
     }
 }
 
+static void rv34_idct_dc_add_c(uint8_t *dst, int stride, int dc)
+{
+    const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+    int i, j;
+
+    cm += (13*13*dc + 0x200) >> 10;
+
+    for (i = 0; i < 4; i++)
+    {
+        for (j = 0; j < 4; j++)
+            dst[j] = cm[ dst[j] ];
+
+        dst += stride;
+    }
+}
+
 static void rv34_inv_transform_dc_c(DCTELEM *block)
 {
     DCTELEM dc = (13 * 13 * block[0] + 0x200) >> 10;
@@ -126,6 +168,9 @@ av_cold void ff_rv34dsp_init(RV34DSPContext *c, DSPContext* dsp) {
     c->rv34_inv_transform_dc_tab[0]  = rv34_inv_transform_dc_c;
     c->rv34_inv_transform_dc_tab[1]  = rv34_inv_transform_dc_noround_c;
 
+    c->rv34_idct_add    = rv34_idct_add_c;
+    c->rv34_idct_dc_add = rv34_idct_dc_add_c;
+
     if (HAVE_NEON)
         ff_rv34dsp_init_neon(c, dsp);
     if (HAVE_MMX)
index 6f53a09..2e9e58e 100644 (file)
@@ -36,6 +36,11 @@ typedef void (*rv40_weight_func)(uint8_t *dst/*align width (8 or 16)*/,
 
 typedef void (*rv34_inv_transform_func)(DCTELEM *block);
 
+typedef void (*rv34_idct_add_func)(uint8_t *dst, int stride,
+                                   const DCTELEM *block);
+typedef void (*rv34_idct_dc_add_func)(uint8_t *dst, int stride,
+                                      int   dc);
+
 typedef void (*rv40_weak_loop_filter_func)(uint8_t *src, int stride,
                                            int filter_p1, int filter_q1,
                                            int alpha, int beta,
@@ -57,6 +62,8 @@ typedef struct RV34DSPContext {
     rv40_weight_func rv40_weight_pixels_tab[2];
     rv34_inv_transform_func rv34_inv_transform_tab[2];
     void (*rv34_inv_transform_dc_tab[2])(DCTELEM *block);
+    rv34_idct_add_func rv34_idct_add;
+    rv34_idct_dc_add_func rv34_idct_dc_add;
     rv40_weak_loop_filter_func rv40_weak_loop_filter[2];
     rv40_strong_loop_filter_func rv40_strong_loop_filter[2];
     rv40_loop_filter_strength_func rv40_loop_filter_strength[2];
index 58f1af0..c8eeebb 100644 (file)
@@ -35,21 +35,84 @@ SECTION .text
     sar    %1, 10
 %endmacro
 
-%macro rv34_idct_dequant4x4_dc 1
-cglobal rv34_idct_dequant4x4_%1_mmx2, 1, 2, 0
+%macro rv34_idct 1
+cglobal rv34_idct_%1_mmx2, 1, 2, 0
     movsx   r1, word [r0]
     IDCT_DC r1
-    movd    mm0, r1
-    pshufw  mm0, mm0, 0
-    movq    [r0+ 0], mm0
-    movq    [r0+16], mm0
-    movq    [r0+32], mm0
-    movq    [r0+48], mm0
+    movd    m0, r1
+    pshufw  m0, m0, 0
+    movq    [r0+ 0], m0
+    movq    [r0+16], m0
+    movq    [r0+32], m0
+    movq    [r0+48], m0
     REP_RET
 %endmacro
 
 INIT_MMX
 %define IDCT_DC IDCT_DC_ROUND
-rv34_idct_dequant4x4_dc dc
+rv34_idct dc
 %define IDCT_DC IDCT_DC_NOROUND
-rv34_idct_dequant4x4_dc dc_noround
+rv34_idct dc_noround
+
+; ff_rv34_idct_dc_add_mmx(uint8_t *dst, int stride, int dc);
+cglobal rv34_idct_dc_add_mmx, 3, 3
+    ; calculate DC
+    IDCT_DC_ROUND r2
+    pxor       m1, m1
+    movd       m0, r2
+    psubw      m1, m0
+    packuswb   m0, m0
+    packuswb   m1, m1
+    punpcklbw  m0, m0
+    punpcklbw  m1, m1
+    punpcklwd  m0, m0
+    punpcklwd  m1, m1
+
+    ; add DC
+    lea        r2, [r0+r1*2]
+    movh       m2, [r0]
+    movh       m3, [r0+r1]
+    movh       m4, [r2]
+    movh       m5, [r2+r1]
+    paddusb    m2, m0
+    paddusb    m3, m0
+    paddusb    m4, m0
+    paddusb    m5, m0
+    psubusb    m2, m1
+    psubusb    m3, m1
+    psubusb    m4, m1
+    psubusb    m5, m1
+    movh       [r0], m2
+    movh       [r0+r1], m3
+    movh       [r2], m4
+    movh       [r2+r1], m5
+    RET
+
+; ff_rv34_idct_dc_add_sse4(uint8_t *dst, int stride, int dc);
+INIT_XMM
+cglobal rv34_idct_dc_add_sse4, 3, 3, 6
+    ; load data
+    IDCT_DC_ROUND r2
+    pxor       m1, m1
+
+    ; calculate DC
+    movd       m0, r2
+    lea        r2, [r0+r1*2]
+    movd       m2, [r0]
+    movd       m3, [r0+r1]
+    pshuflw    m0, m0, 0
+    movd       m4, [r2]
+    movd       m5, [r2+r1]
+    punpcklqdq m0, m0
+    punpckldq  m2, m3
+    punpckldq  m4, m5
+    punpcklbw  m2, m1
+    punpcklbw  m4, m1
+    paddw      m2, m0
+    paddw      m4, m0
+    packuswb   m2, m4
+    movd      [r0], m2
+    pextrd [r0+r1], m2, 1
+    pextrd    [r2], m2, 2
+    pextrd [r2+r1], m2, 3
+    RET
index 4317e9b..c10ae4e 100644 (file)
 #include "libavcodec/dsputil.h"
 #include "libavcodec/rv34dsp.h"
 
-void ff_rv34_idct_dequant4x4_dc_mmx2(DCTELEM *block);
-void ff_rv34_idct_dequant4x4_dc_noround_mmx2(DCTELEM *block);
+void ff_rv34_idct_dc_mmx2(DCTELEM *block);
+void ff_rv34_idct_dc_noround_mmx2(DCTELEM *block);
+void ff_rv34_idct_dc_add_mmx(uint8_t *dst, int stride, int dc);
+void ff_rv34_idct_dc_add_sse4(uint8_t *dst, int stride, int dc);
 
 av_cold void ff_rv34dsp_init_x86(RV34DSPContext* c, DSPContext *dsp)
 {
 #if HAVE_YASM
     int mm_flags = av_get_cpu_flags();
 
+    if (mm_flags & AV_CPU_FLAG_MMX)
+        c->rv34_idct_dc_add = ff_rv34_idct_dc_add_mmx;
     if (mm_flags & AV_CPU_FLAG_MMX2) {
-        c->rv34_inv_transform_dc_tab[0] = ff_rv34_idct_dequant4x4_dc_mmx2;
-        c->rv34_inv_transform_dc_tab[1] = ff_rv34_idct_dequant4x4_dc_noround_mmx2;
+        c->rv34_inv_transform_dc_tab[0] = ff_rv34_idct_dc_mmx2;
+        c->rv34_inv_transform_dc_tab[1] = ff_rv34_idct_dc_noround_mmx2;
     }
+    if (mm_flags & AV_CPU_FLAG_SSE4)
+        c->rv34_idct_dc_add = ff_rv34_idct_dc_add_sse4;
 #endif
 }