changeset 2847:712c84b9d8ce libavcodec

optimizations dc coeff rounding fix class=3 num of bits fix do interlaced check & idct only if CODEC_FLAG_INTERLACED_DCT
author michael
date Tue, 30 Aug 2005 20:03:19 +0000
parents 40765c51a7a9
children 78ad77267785
files dv.c
diffstat 1 files changed, 112 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/dv.c	Fri Aug 26 19:05:44 2005 +0000
+++ b/dv.c	Tue Aug 30 20:03:19 2005 +0000
@@ -34,9 +34,13 @@
 #include "simple_idct.h"
 #include "dvdata.h"
 
+//#undef NDEBUG
+//#include <assert.h>
+
 typedef struct DVVideoContext {
     const DVprofile* sys;
     AVFrame picture;
+    AVCodecContext *avctx;
     uint8_t *buf;
     
     uint8_t dv_zigzag[2][64];
@@ -54,7 +58,7 @@
 #define DV_VLC_MAP_LEV_SIZE 23
 #else
 #define DV_VLC_MAP_RUN_SIZE  64 
-#define DV_VLC_MAP_LEV_SIZE 512
+#define DV_VLC_MAP_LEV_SIZE 512 //FIXME sign was removed so this should be /2 but needs check
 #endif
 
 /* MultiThreading */
@@ -233,6 +237,7 @@
     if (dv_codec_profile(avctx))
 	avctx->pix_fmt = dv_codec_profile(avctx)->pix_fmt; 
     avctx->coded_frame = &s->picture;
+    s->avctx= avctx;
     
     return 0;
 }
@@ -332,10 +337,9 @@
 	if (pos >= 64)
 	    break;
         
-	if (level) {
-            pos1 = scan_table[pos];
-            block[pos1] = level << shift_table[pos1];
-        } 
+        assert(level);
+        pos1 = scan_table[pos];
+        block[pos1] = level << shift_table[pos1];
 
         UPDATE_CACHE(re, gb);
     }
@@ -346,9 +350,9 @@
 static inline void bit_copy(PutBitContext *pb, GetBitContext *gb)
 {
     int bits_left = get_bits_left(gb);
-    while (bits_left >= 16) {
-        put_bits(pb, 16, get_bits(gb, 16));
-        bits_left -= 16;
+    while (bits_left >= MIN_CACHE_BITS) {
+        put_bits(pb, MIN_CACHE_BITS, get_bits(gb, MIN_CACHE_BITS));
+        bits_left -= MIN_CACHE_BITS;
     }
     if (bits_left > 0) {
         put_bits(pb, bits_left, get_bits(gb, bits_left));
@@ -371,9 +375,12 @@
     GetBitContext gb;
     BlockInfo mb_data[5 * 6], *mb, *mb1;
     DCTELEM sblock[5*6][64] __align8;
-    uint8_t mb_bit_buffer[80 + 4]; /* allow some slack */
-    uint8_t vs_bit_buffer[5 * 80 + 4]; /* allow some slack */
+    uint8_t mb_bit_buffer[80 + 4] __align8; /* allow some slack */
+    uint8_t vs_bit_buffer[5 * 80 + 4] __align8; /* allow some slack */
 	    
+    assert((((int)mb_bit_buffer)&7)==0);
+    assert((((int)vs_bit_buffer)&7)==0);
+    
     memset(sblock, 0, sizeof(sblock));
 
     /* pass 1 : read DC and AC coefficients in blocks */
@@ -525,14 +532,9 @@
 
 #ifdef DV_CODEC_TINY_TARGET
 /* Converts run and level (where level != 0) pair into vlc, returning bit size */
-static always_inline int dv_rl2vlc(int run, int l, uint32_t* vlc)
+static always_inline int dv_rl2vlc(int run, int level, int sign, uint32_t* vlc)
 {
-    int sign = l >> 8;
-    int level = (l ^ sign) - sign;
     int size;
-    
-    sign = (sign & 1);
-
     if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) {
         *vlc = dv_vlc_map[run][level].vlc | sign;
 	size = dv_vlc_map[run][level].size;
@@ -555,9 +557,8 @@
     return size;
 }
 
-static always_inline int dv_rl2vlc_size(int run, int l)
+static always_inline int dv_rl2vlc_size(int run, int level)
 {
-    int level = (l ^ (l >> 8)) - (l >> 8);
     int size;
     
     if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) {
@@ -572,41 +573,43 @@
     return size;
 }
 #else
-static always_inline int dv_rl2vlc(int run, int l, uint32_t* vlc)
+static always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t* vlc)
 {
-    *vlc = dv_vlc_map[run][((uint16_t)l)&0x1ff].vlc;
-    return dv_vlc_map[run][((uint16_t)l)&0x1ff].size;
+    *vlc = dv_vlc_map[run][l].vlc | sign;
+    return dv_vlc_map[run][l].size;
 }
 
 static always_inline int dv_rl2vlc_size(int run, int l)
 {
-    return dv_vlc_map[run][((uint16_t)l)&0x1ff].size;
+    return dv_vlc_map[run][l].size;
 }
 #endif
 
 typedef struct EncBlockInfo {
     int area_q[4];
     int bit_size[4];
-    int prev_run[4];
+    int prev[5];
     int cur_ac;
     int cno;
     int dct_mode;
-    DCTELEM *mb;
+    DCTELEM mb[64];
+    uint8_t next[64];
+    uint8_t sign[64];
     uint8_t partial_bit_count;
     uint32_t partial_bit_buffer; /* we can't use uint16_t here */
 } EncBlockInfo;
 
-static always_inline void dv_encode_ac(EncBlockInfo* bi, PutBitContext* pb_pool, 
-                                       int pb_size)
+static always_inline PutBitContext* dv_encode_ac(EncBlockInfo* bi, PutBitContext* pb_pool, 
+                                       PutBitContext* pb_end)
 {
-    int run;
+    int prev;
     int bits_left;
     PutBitContext* pb = pb_pool;
     int size = bi->partial_bit_count;
     uint32_t vlc = bi->partial_bit_buffer;
-    
+
     bi->partial_bit_count = bi->partial_bit_buffer = 0;
-vlc_loop:
+    for(;;){
        /* Find suitable storage space */
        for (; size > (bits_left = put_bits_left(pb)); pb++) {
           if (bits_left) {
@@ -614,69 +617,84 @@
 	      put_bits(pb, bits_left, vlc >> size);
 	      vlc = vlc & ((1<<size)-1);
 	  }
-	  if (pb_size == 1) {
+	  if (pb + 1 >= pb_end) {
 	      bi->partial_bit_count = size;
 	      bi->partial_bit_buffer = vlc;
-	      return;
+	      return pb;
 	  }
-	  --pb_size;
        }
        
        /* Store VLC */
        put_bits(pb, size, vlc);
        
+       if(bi->cur_ac>=64)
+           break;
+       
        /* Construct the next VLC */
-       run = 0;
-       for (; bi->cur_ac < 64; bi->cur_ac++, run++) {
-           if (bi->mb[bi->cur_ac]) {
-	       size = dv_rl2vlc(run, bi->mb[bi->cur_ac], &vlc);
-	       bi->cur_ac++;
-	       goto vlc_loop;
-	   }
+       prev= bi->cur_ac;
+       bi->cur_ac = bi->next[prev];
+       if(bi->cur_ac < 64){
+           size = dv_rl2vlc(bi->cur_ac - prev - 1, bi->mb[bi->cur_ac], bi->sign[bi->cur_ac], &vlc);
+       } else {
+           size = 4; vlc = 6; /* End Of Block stamp */
        }
-   
-       if (bi->cur_ac == 64) {
-           size = 4; vlc = 6; /* End Of Block stamp */
-	   bi->cur_ac++;
-	   goto vlc_loop;
-       }
+    }
+    return pb;
 }
 
 static always_inline void dv_set_class_number(DCTELEM* blk, EncBlockInfo* bi, 
                                               const uint8_t* zigzag_scan, int bias)
 {
     int i, area;
-    int run;
-    int classes[] = {12, 24, 36, 0xffff};
+    static const int classes[] = {12, 24, 36, 0xffff};
+    int max=12;
+    int prev=0;
 
-    run = 0;
     bi->mb[0] = blk[0]; 
-    bi->cno = 0;
+    
     for (area = 0; area < 4; area++) {
-       bi->prev_run[area] = run;
-       bi->bit_size[area] = 0;
+       bi->prev[area] = prev;
+       bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)
        for (i=mb_area_start[area]; i<mb_area_start[area+1]; i++) {
-          bi->mb[i] = (blk[zigzag_scan[i]] / 16);
-          while ((bi->mb[i] ^ (bi->mb[i] >> 8)) > classes[bi->cno])
-              bi->cno++;
+          int level = blk[zigzag_scan[i]];
        
-          if (bi->mb[i]) {
-              bi->bit_size[area] += dv_rl2vlc_size(run, bi->mb[i]);
-	      run = 0;
-          } else
-              ++run;
+          if (level+15 > 30U) {
+              bi->sign[i] = (level>>31)&1;
+              bi->mb[i] = level= ABS(level)>>4;
+              if(level>max) max= level;
+              bi->bit_size[area] += dv_rl2vlc_size(i - prev  - 1, level);
+              bi->next[prev]= i;
+              prev= i;
+          }
        }
     }
-    bi->bit_size[3] += 4; /* EOB marker */
+    bi->next[prev]= i;
+    for(bi->cno = 0; max > classes[bi->cno]; bi->cno++);
+
     bi->cno += bias;
     
-    if (bi->cno >= 3) { /* FIXME: we have to recreate bit_size[], prev_run[] */
+    if (bi->cno >= 3) {
         bi->cno = 3;
-	for (i=1; i<64; i++)
-	   bi->mb[i] /= 2;
+        prev=0;
+        i= bi->next[prev];
+        for (area = 0; area < 4; area++) {
+            bi->prev[area] = prev;
+            bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)
+            for (; i<mb_area_start[area+1]; i= bi->next[i]) {
+                bi->mb[i] >>=1;
+            
+                if (bi->mb[i]) {
+                    bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, bi->mb[i]);
+                    bi->next[prev]= i;
+                    prev= i;
+                }
+            }
+        }
+        bi->next[prev]= i;
     }
 }
 
+//FIXME replace this by dsputil
 #define SC(x, y) ((s[x] - s[y]) ^ ((s[x] - s[y]) >> 7))
 static always_inline int dv_guess_dct_mode(DCTELEM *blk) {
     DCTELEM *s;
@@ -705,9 +723,9 @@
 static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos)
 {
     int size[5];
-    int i, j, k, a, run;
+    int i, j, k, a, prev;
     EncBlockInfo* b;
-    
+
     do {
        b = blks;
        for (i=0; i<5; i++) {
@@ -719,17 +737,19 @@
           for (j=0; j<6; j++, b++) {
 	     for (a=0; a<4; a++) {
 	        if (b->area_q[a] != dv_quant_shifts[qnos[i] + dv_quant_offset[b->cno]][a]) {
-		    b->bit_size[a] = (a==3)?4:0;
+		    b->bit_size[a] = 1; // 4 areas 4 bits for EOB :)
 		    b->area_q[a]++;
-		    run = b->prev_run[a];
-		    for (k=mb_area_start[a]; k<mb_area_start[a+1]; k++) {
-		       b->mb[k] /= 2;
+                    prev= b->prev[a];
+                    for (k= b->next[prev] ; k<mb_area_start[a+1]; k= b->next[k]) {
+		       b->mb[k] >>= 1;
 		       if (b->mb[k]) {
-                           b->bit_size[a] += dv_rl2vlc_size(run, b->mb[k]);
-	                   run = 0;
-                       } else
-                           ++run;
+                           b->bit_size[a] += dv_rl2vlc_size(k - prev - 1, b->mb[k]);
+	                   prev= k;
+                       } else {
+                           b->next[prev] = b->next[k];
+                       }
 		    }
+                    b->prev[a+1]= prev;
 		}
 		size[i] += b->bit_size[a];
 	     }
@@ -755,13 +775,14 @@
     uint8_t*  ptr;
     int       do_edge_wrap;
     DCTELEM   block[64] __align8;
-    DCTELEM   sblock[5*6][64] __align8;
     EncBlockInfo  enc_blks[5*6];
     PutBitContext pbs[5*6];
     PutBitContext* pb; 
     EncBlockInfo* enc_blk;
     int       vs_bit_size = 0;
     int       qnos[5];
+    
+    assert((((int)block) & 7) == 0);
    
     enc_blk = &enc_blks[0];
     pb = &pbs[0];
@@ -808,21 +829,22 @@
 	        s->get_pixels(block, data, linesize);
 	    }
 	  
-            enc_blk->dct_mode = dv_guess_dct_mode(block);
-	    enc_blk->mb = &sblock[mb_index*6+j][0];
+            if(s->avctx->flags & CODEC_FLAG_INTERLACED_DCT)
+                enc_blk->dct_mode = dv_guess_dct_mode(block);
+            else
+                enc_blk->dct_mode = 0;
 	    enc_blk->area_q[0] = enc_blk->area_q[1] = enc_blk->area_q[2] = enc_blk->area_q[3] = 0;
 	    enc_blk->partial_bit_count = 0;
 	    enc_blk->partial_bit_buffer = 0;
-	    enc_blk->cur_ac = 1;
+	    enc_blk->cur_ac = 0;
 	    
 	    s->fdct[enc_blk->dct_mode](block);
 	    
 	    dv_set_class_number(block, enc_blk, 
-	                        enc_blk->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct,
-				j/4*(j%2));
+	                        enc_blk->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct, j/4);
            
             init_put_bits(pb, ptr, block_sizes[j]/8);
-	    put_bits(pb, 9, (uint16_t)(((enc_blk->mb[0] >> 3) - 1024) >> 2));
+	    put_bits(pb, 9, (uint16_t)(((enc_blk->mb[0] >> 3) - 1024 + 2) >> 2));
 	    put_bits(pb, 1, enc_blk->dct_mode);
 	    put_bits(pb, 2, enc_blk->cno);
 	    
@@ -843,18 +865,22 @@
 
     /* First pass over individual cells only */
     for (j=0; j<5*6; j++)
-       dv_encode_ac(&enc_blks[j], &pbs[j], 1);
+       dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j+1]);
 
     /* Second pass over each MB space */
-    for (j=0; j<5*6; j++) {
-       if (enc_blks[j].cur_ac < 65 || enc_blks[j].partial_bit_count)
-           dv_encode_ac(&enc_blks[j], &pbs[(j/6)*6], 6);
+    for (j=0; j<5*6; j+=6) {
+        pb= &pbs[j];
+        for (i=0; i<6; i++) {
+            if (enc_blks[i+j].partial_bit_count)
+                pb=dv_encode_ac(&enc_blks[i+j], pb, &pbs[j+6]);
+        }
     }
 
     /* Third and final pass over the whole vides segment space */
+    pb= &pbs[0];
     for (j=0; j<5*6; j++) {
-       if (enc_blks[j].cur_ac < 65 || enc_blks[j].partial_bit_count)
-           dv_encode_ac(&enc_blks[j], &pbs[0], 6*5);
+       if (enc_blks[j].partial_bit_count)
+           pb=dv_encode_ac(&enc_blks[j], pb, &pbs[6*5]);
     }
 
     for (j=0; j<5*6; j++)