]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/msmpeg4.c
zero copy packet handling for DV1394 by Max Krasnyansky
[ffmpeg] / libavcodec / msmpeg4.c
index 2c4a31989a88d58dbece04532a563c7e4929c7b6..2c524a0675fa2a4fbb45880bb2bdc4414ab9f10c 100644 (file)
@@ -21,7 +21,7 @@
 #include "avcodec.h"
 #include "dsputil.h"
 #include "mpegvideo.h"
-
+//#define PRINT_MB
 
 /*
  * You can also call this codec : MPEG4 with a twist ! 
  */
 //#define DEBUG
 
-/* motion vector table */
-typedef struct MVTable {
-    int n;
-    const UINT16 *table_mv_code;
-    const UINT8 *table_mv_bits;
-    const UINT8 *table_mvx;
-    const UINT8 *table_mvy;
-    UINT16 *table_mv_index; /* encoding: convert mv to index in table_mv */
-    VLC vlc;                /* decoding: vlc */
-} MVTable;
+#define DC_VLC_BITS 9
+#define CBPY_VLC_BITS 6
+#define INTER_INTRA_VLC_BITS 3
+#define V1_INTRA_CBPC_VLC_BITS 6
+#define V1_INTER_CBPC_VLC_BITS 6
+#define V2_INTRA_CBPC_VLC_BITS 3
+#define V2_MB_TYPE_VLC_BITS 7
+#define MV_VLC_BITS 9
+#define V2_MV_VLC_BITS 9
+#define TEX_VLC_BITS 9
+#define MB_NON_INTRA_VLC_BITS 9
+#define MB_INTRA_VLC_BITS 9
+
+#define II_BITRATE 128*1024
+#define MBAC_BITRATE 50*1024
+
+#define DEFAULT_INTER_INDEX 3
 
 static UINT32 v2_dc_lum_table[512][2];
 static UINT32 v2_dc_chroma_table[512][2];
 
-static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n);
-static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
-                                int n, int coded);
+static inline void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n);
+static inline int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+                                       int n, int coded, const uint8_t *scantable);
 static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr);
 static int msmpeg4_decode_motion(MpegEncContext * s, 
                                  int *mx_ptr, int *my_ptr);
 static void msmpeg4v2_encode_motion(MpegEncContext * s, int val);
-static void init_h263_dc_for_msmpeg4();
-
+static void init_h263_dc_for_msmpeg4(void);
+static inline void msmpeg4_memsetw(short *tab, int val, int n);
+static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, int level, int intra);
+static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
+static int msmpeg4v34_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
+static int wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]);
 
 extern UINT32 inverse[256];
 
+
 #ifdef DEBUG
 int intra_count = 0;
 int frame_count = 0;
 #endif
-/* XXX: move it to mpegvideo.h */
-
-static int init_done = 0;
 
 #include "msmpeg4data.h"
 
+static UINT8 rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2];
+
 #ifdef STATS
 
 const char *st_names[ST_NB] = {
@@ -132,6 +143,48 @@ void print_stats(void)
 
 #endif
 
+static void common_init(MpegEncContext * s)
+{
+    static int inited=0;
+    
+    switch(s->msmpeg4_version){
+    case 1:
+    case 2:
+        s->y_dc_scale_table=
+        s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
+        break;
+    case 3:
+        if(s->workaround_bugs){
+            s->y_dc_scale_table= old_ff_y_dc_scale_table;
+            s->c_dc_scale_table= old_ff_c_dc_scale_table;
+        } else{
+            s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table;
+            s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table;
+        }
+        break;
+    case 4:
+    case 5:
+        s->y_dc_scale_table= wmv1_y_dc_scale_table;
+        s->c_dc_scale_table= wmv1_c_dc_scale_table;
+        break;
+    }
+
+    
+    if(s->msmpeg4_version>=4){
+        ff_init_scantable(s, &s->intra_scantable  , wmv1_scantable[1]);
+        ff_init_scantable(s, &s->intra_h_scantable, wmv1_scantable[2]);
+        ff_init_scantable(s, &s->intra_v_scantable, wmv1_scantable[3]);
+        ff_init_scantable(s, &s->inter_scantable  , wmv1_scantable[0]);
+    }
+    //Note the default tables are set in common_init in mpegvideo.c
+    
+    if(!inited){
+        inited=1;
+
+        init_h263_dc_for_msmpeg4();
+    }
+}
+
 /* build the table which associate a (x,y) motion vector to a vlc */
 static void init_mv_table(MVTable *tab)
 {
@@ -159,66 +212,206 @@ static void code012(PutBitContext *pb, int n)
     }
 }
 
+void ff_msmpeg4_encode_init(MpegEncContext *s)
+{
+    static int init_done=0;
+    int i;
+
+    common_init(s);
+    if(s->msmpeg4_version>=4){
+        s->min_qcoeff= -255;
+        s->max_qcoeff=  255;
+    }
+
+    if (!init_done) {
+        /* init various encoding tables */
+        init_done = 1;
+        init_mv_table(&mv_tables[0]);
+        init_mv_table(&mv_tables[1]);
+        for(i=0;i<NB_RL_TABLES;i++)
+            init_rl(&rl_table[i]);
+
+        for(i=0; i<NB_RL_TABLES; i++){
+            int level;
+            for(level=0; level<=MAX_LEVEL; level++){
+                int run;
+                for(run=0; run<=MAX_RUN; run++){
+                    int last;
+                    for(last=0; last<2; last++){
+                        rl_length[i][level][run][last]= get_size_of_code(s, &rl_table[  i], last, run, level, 0);
+                    }
+                }
+            }
+        }
+    }
+}
+
+static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, int level, int intra){
+    int size=0;
+    int code;
+    int run_diff= intra ? 0 : 1;
+    
+    code = get_rl_index(rl, last, run, level);
+    size+= rl->table_vlc[code][1];
+    if (code == rl->n) {
+        int level1, run1;
+
+        level1 = level - rl->max_level[last][run];
+        if (level1 < 1) 
+            goto esc2;
+        code = get_rl_index(rl, last, run, level1);
+        if (code == rl->n) {
+            esc2:
+            size++;
+            if (level > MAX_LEVEL)
+                goto esc3;
+            run1 = run - rl->max_run[last][level] - run_diff;
+            if (run1 < 0)
+                goto esc3;
+            code = get_rl_index(rl, last, run1, level);
+            if (code == rl->n) {
+            esc3:
+                /* third escape */
+                size+=1+1+6+8;
+            } else {
+                /* second escape */
+                size+= 1+1+ rl->table_vlc[code][1];
+            }
+        } else {
+            /* first escape */
+            size+= 1+1+ rl->table_vlc[code][1];
+        }
+    } else {
+        size++;
+    }
+    return size;
+}
+
+static void find_best_tables(MpegEncContext * s)
+{
+    int i;
+    int best       =-1, best_size       =9999999;
+    int chroma_best=-1, best_chroma_size=9999999;
+
+    for(i=0; i<3; i++){
+        int level;
+        int chroma_size=0;
+        int size=0;
+
+        if(i>0){// ;)
+            size++; 
+            chroma_size++;
+        }
+        for(level=0; level<=MAX_LEVEL; level++){
+            int run;
+            for(run=0; run<=MAX_RUN; run++){
+                int last;
+                const int last_size= size + chroma_size;
+                for(last=0; last<2; last++){
+                    int inter_count       = s->ac_stats[0][0][level][run][last] + s->ac_stats[0][1][level][run][last];
+                    int intra_luma_count  = s->ac_stats[1][0][level][run][last];
+                    int intra_chroma_count= s->ac_stats[1][1][level][run][last];
+                    
+                    if(s->pict_type==I_TYPE){
+                        size       += intra_luma_count  *rl_length[i  ][level][run][last];
+                        chroma_size+= intra_chroma_count*rl_length[i+3][level][run][last];
+                    }else{
+                        size+=        intra_luma_count  *rl_length[i  ][level][run][last]
+                                     +intra_chroma_count*rl_length[i+3][level][run][last]
+                                     +inter_count       *rl_length[i+3][level][run][last];
+                    }                   
+                }
+                if(last_size == size+chroma_size) break;
+            }
+        }
+        if(size<best_size){
+            best_size= size;
+            best= i;
+        }
+        if(chroma_size<best_chroma_size){
+            best_chroma_size= chroma_size;
+            chroma_best= i;
+        }
+    }
+
+//    printf("type:%d, best:%d, qp:%d, var:%d, mcvar:%d, size:%d //\n", 
+//           s->pict_type, best, s->qscale, s->mb_var_sum, s->mc_mb_var_sum, best_size);
+           
+    if(s->pict_type==P_TYPE) chroma_best= best;
+
+    memset(s->ac_stats, 0, sizeof(int)*(MAX_LEVEL+1)*(MAX_RUN+1)*2*2*2);
+
+    s->rl_table_index       =        best;
+    s->rl_chroma_table_index= chroma_best;
+    
+    if(s->pict_type != s->last_non_b_pict_type){
+        s->rl_table_index= 2;
+        if(s->pict_type==I_TYPE)
+            s->rl_chroma_table_index= 1;
+        else
+            s->rl_chroma_table_index= 2;
+    }
+
+}
+
 /* write MSMPEG4 compatible frame header */
 void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
 {
-    int i;
+    find_best_tables(s);
 
     align_put_bits(&s->pb);
-
     put_bits(&s->pb, 2, s->pict_type - 1);
 
     put_bits(&s->pb, 5, s->qscale);
-
-    s->rl_table_index = 2;
-    if(s->msmpeg4_version<=2)
-        s->rl_chroma_table_index = 2; /* only for I frame */
-    else
-        s->rl_chroma_table_index = 1; /* only for I frame */
+    if(s->msmpeg4_version<=2){
+        s->rl_table_index = 2;
+        s->rl_chroma_table_index = 2;
+    }
 
     s->dc_table_index = 1;
     s->mv_table_index = 1; /* only if P frame */
     s->use_skip_mb_code = 1; /* only if P frame */
-    
+    s->per_mb_rl_table = 0;
+    if(s->msmpeg4_version==4)
+        s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE && s->pict_type==P_TYPE);
+//printf("%d %d %d %d %d\n", s->pict_type, s->bit_rate, s->inter_intra_pred, s->width, s->height);
+
     if (s->pict_type == I_TYPE) {
-        put_bits(&s->pb, 5, 0x17); /* indicate only one "slice" */
+        s->slice_height= s->mb_height/1;
+        put_bits(&s->pb, 5, 0x16 + s->mb_height/s->slice_height);
+        
+        if(s->msmpeg4_version==4){
+            msmpeg4_encode_ext_header(s);
+            if(s->bit_rate>MBAC_BITRATE)
+                put_bits(&s->pb, 1, s->per_mb_rl_table);
+        }
 
         if(s->msmpeg4_version>2){
-            code012(&s->pb, s->rl_chroma_table_index);
-            code012(&s->pb, s->rl_table_index);
+            if(!s->per_mb_rl_table){
+                code012(&s->pb, s->rl_chroma_table_index);
+                code012(&s->pb, s->rl_table_index);
+            }
 
             put_bits(&s->pb, 1, s->dc_table_index);
         }
-        s->no_rounding = 1;
     } else {
         put_bits(&s->pb, 1, s->use_skip_mb_code);
         
-        s->rl_chroma_table_index = s->rl_table_index;
+        if(s->msmpeg4_version==4 && s->bit_rate>MBAC_BITRATE)
+            put_bits(&s->pb, 1, s->per_mb_rl_table);
+
         if(s->msmpeg4_version>2){
-            code012(&s->pb, s->rl_table_index);
+            if(!s->per_mb_rl_table)
+                code012(&s->pb, s->rl_table_index);
 
             put_bits(&s->pb, 1, s->dc_table_index);
 
             put_bits(&s->pb, 1, s->mv_table_index);
         }
-
-       if(s->flipflop_rounding){
-           s->no_rounding ^= 1;
-       }else{
-           s->no_rounding = 0;
-       }
     }
 
-    if (!init_done) {
-        /* init various encoding tables */
-        init_done = 1;
-        init_mv_table(&mv_tables[0]);
-        init_mv_table(&mv_tables[1]);
-        for(i=0;i<NB_RL_TABLES;i++)
-            init_rl(&rl_table[i]);
-
-        init_h263_dc_for_msmpeg4();
-    }
+    s->esc3_level_length= 0;
+    s->esc3_run_length= 0;
 
 #ifdef DEBUG
     intra_count = 0;
@@ -230,7 +423,7 @@ void msmpeg4_encode_ext_header(MpegEncContext * s)
 {
         put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29
 
-       put_bits(&s->pb, 11, MIN(s->bit_rate, 2047));
+        put_bits(&s->pb, 11, FFMIN(s->bit_rate/1024, 2047));
 
         if(s->msmpeg4_version<3)
             s->flipflop_rounding=0;
@@ -306,6 +499,19 @@ static void msmpeg4_encode_motion(MpegEncContext * s,
     }
 }
 
+static inline void handle_slices(MpegEncContext *s){
+    if (s->mb_x == 0) {
+        if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
+            if(s->msmpeg4_version < 4){
+                ff_mpeg4_clean_buffers(s);
+            }
+            s->first_slice_line = 1;
+        } else {
+            s->first_slice_line = 0; 
+        }
+    }
+}
+
 void msmpeg4_encode_mb(MpegEncContext * s, 
                        DCTELEM block[6][64],
                        int motion_x, int motion_y)
@@ -314,6 +520,8 @@ void msmpeg4_encode_mb(MpegEncContext * s,
     int pred_x, pred_y;
     UINT8 *coded_block;
 
+    handle_slices(s);
+    
     if (!s->mb_intra) {
        /* compute cbp */
         set_stat(ST_INTER_MB);
@@ -404,6 +612,10 @@ void msmpeg4_encode_mb(MpegEncContext * s,
             }
             set_stat(ST_INTRA_MB);
             put_bits(&s->pb, 1, 0);    /* no AC prediction yet */
+            if(s->inter_intra_pred){
+                s->h263_aic_dir=0;
+                put_bits(&s->pb, table_inter_intra[s->h263_aic_dir][1], table_inter_intra[s->h263_aic_dir][0]);
+            }
         }
     }
 
@@ -427,8 +639,8 @@ void ff_old_msmpeg4_dc_scale(MpegEncContext * s)
     }
 }
 
-static int msmpeg4v1_pred_dc(MpegEncContext * s, int n, 
-                           INT32 **dc_val_ptr)
+static inline int msmpeg4v1_pred_dc(MpegEncContext * s, int n, 
+                                    INT32 **dc_val_ptr)
 {
     int i;
 
@@ -442,9 +654,22 @@ static int msmpeg4v1_pred_dc(MpegEncContext * s, int n,
     return s->last_dc[i]; 
 }
 
+static int get_dc(uint8_t *src, int stride, int scale)
+{
+    int y;
+    int sum=0;
+    for(y=0; y<8; y++){
+        int x;
+        for(x=0; x<8; x++){
+            sum+=src[x + y*stride];
+        }
+    }
+    return (sum + (scale>>1))/scale;
+}
+
 /* dir = 0: left, dir = 1: top prediction */
-static int msmpeg4_pred_dc(MpegEncContext * s, int n, 
-                           INT16 **dc_val_ptr, int *dir_ptr)
+static inline int msmpeg4_pred_dc(MpegEncContext * s, int n, 
+                             UINT16 **dc_val_ptr, int *dir_ptr)
 {
     int a, b, c, wrap, pred, scale;
     INT16 *dc_val;
@@ -465,6 +690,10 @@ static int msmpeg4_pred_dc(MpegEncContext * s, int n,
     a = dc_val[ - 1];
     b = dc_val[ - 1 - wrap];
     c = dc_val[ - wrap];
+    
+    if(s->first_slice_line && (n&2)==0 && s->msmpeg4_version<4){
+        b=c=1024;
+    }
 
     /* XXX: the following solution consumes divisions, but it does not
        necessitate to modify mpegvideo.c. The problem comes from the
@@ -506,12 +735,79 @@ static int msmpeg4_pred_dc(MpegEncContext * s, int n,
 #endif
     /* XXX: WARNING: they did not choose the same test as MPEG4. This
        is very important ! */
-    if (abs(a - b) <= abs(b - c)) {
-       pred = c;
-        *dir_ptr = 1;
-    } else {
-       pred = a;
-        *dir_ptr = 0;
+    if(s->msmpeg4_version>3){
+        if(s->inter_intra_pred){
+            uint8_t *dest;
+            int wrap;
+            
+            if(n==1){
+                pred=a;
+                *dir_ptr = 0;
+            }else if(n==2){
+                pred=c;
+                *dir_ptr = 1;
+            }else if(n==3){
+                if (abs(a - b) < abs(b - c)) {
+                    pred = c;
+                    *dir_ptr = 1;
+                } else {
+                    pred = a;
+                    *dir_ptr = 0;
+                }
+            }else{
+                if(n<4){
+                    wrap= s->linesize;
+                    dest= s->current_picture.data[0] + (((n>>1) + 2*s->mb_y) * 8*  wrap ) + ((n&1) + 2*s->mb_x) * 8;
+                }else{
+                    wrap= s->uvlinesize;
+                    dest= s->current_picture.data[n-3] + (s->mb_y * 8 * wrap) + s->mb_x * 8;
+                }
+                if(s->mb_x==0) a= (1024 + (scale>>1))/scale;
+                else           a= get_dc(dest-8, wrap, scale*8);
+                if(s->mb_y==0) c= (1024 + (scale>>1))/scale;
+                else           c= get_dc(dest-8*wrap, wrap, scale*8);
+                
+                if (s->h263_aic_dir==0) {
+                    pred= a;
+                    *dir_ptr = 0;
+                }else if (s->h263_aic_dir==1) {
+                    if(n==0){
+                        pred= c;
+                        *dir_ptr = 1;
+                    }else{
+                        pred= a;
+                        *dir_ptr = 0;
+                    }
+                }else if (s->h263_aic_dir==2) {
+                    if(n==0){
+                        pred= a;
+                        *dir_ptr = 0;
+                    }else{
+                        pred= c;
+                        *dir_ptr = 1;
+                    }
+                } else {
+                    pred= c;
+                    *dir_ptr = 1;
+                }
+            }
+        }else{
+            if (abs(a - b) < abs(b - c)) {
+                pred = c;
+                *dir_ptr = 1;
+            } else {
+                pred = a;
+                *dir_ptr = 0;
+            }
+        }
+    }else{
+        if (abs(a - b) <= abs(b - c)) {
+            pred = c;
+            *dir_ptr = 1;
+        } else {
+            pred = a;
+            *dir_ptr = 0;
+        }
     }
 
     /* update predictor */
@@ -533,7 +829,7 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr
         /* update predictor */
         *dc_val= level;
     }else{
-        INT16 *dc_val;
+        UINT16 *dc_val;
         pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
 
         /* update predictor */
@@ -593,12 +889,13 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr
 /* Encoding of a block. Very similar to MPEG4 except for a different
    escape coding (same as H263) and more vlc tables.
  */
-static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
+static inline void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
 {
     int level, run, last, i, j, last_index;
     int last_non_zero, sign, slevel;
     int code, run_diff, dc_pred_dir;
     const RLTable *rl;
+    const UINT8 *scantable;
 
     if (s->mb_intra) {
         set_stat(ST_DC);
@@ -610,6 +907,7 @@ static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
             rl = &rl_table[3 + s->rl_chroma_table_index];
         }
         run_diff = 0;
+        scantable= s->intra_scantable.permutated;
         set_stat(ST_INTRA_AC);
     } else {
         i = 0;
@@ -618,14 +916,22 @@ static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
             run_diff = 0;
         else
             run_diff = 1;
+        scantable= s->inter_scantable.permutated;
         set_stat(ST_INTER_AC);
     }
 
+    /* recalculate block_last_index for M$ wmv1 */
+    if(s->msmpeg4_version>=4 && s->block_last_index[n]>0){
+        for(last_index=63; last_index>=0; last_index--){
+            if(block[scantable[last_index]]) break;
+        }
+        s->block_last_index[n]= last_index;
+    }else
+        last_index = s->block_last_index[n];
     /* AC coefs */
-    last_index = s->block_last_index[n];
     last_non_zero = i - 1;
     for (; i <= last_index; i++) {
-       j = zigzag_direct[i];
+       j = scantable[i];
        level = block[j];
        if (level) {
            run = i - last_non_zero - 1;
@@ -636,6 +942,14 @@ static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
                sign = 1;
                level = -level;
            }
+
+            if(level<=MAX_LEVEL && run<=MAX_RUN){
+                s->ac_stats[s->mb_intra][n>3][level][run][last]++;
+            }
+#if 0
+else
+    s->ac_stats[s->mb_intra][n>3][40][63][0]++; //esc3 like
+#endif
             code = get_rl_index(rl, last, run, level);
             put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
             if (code == rl->n) {
@@ -659,8 +973,22 @@ static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
                         /* third escape */
                         put_bits(&s->pb, 1, 0);
                         put_bits(&s->pb, 1, last);
-                        put_bits(&s->pb, 6, run);
-                        put_bits(&s->pb, 8, slevel & 0xff);
+                        if(s->msmpeg4_version>=4){
+                            if(s->esc3_level_length==0){
+                                s->esc3_level_length=8;
+                                s->esc3_run_length= 6;
+                                if(s->qscale<8)
+                                    put_bits(&s->pb, 6, 3);
+                                else
+                                    put_bits(&s->pb, 8, 3);
+                            }
+                            put_bits(&s->pb, s->esc3_run_length, run);
+                            put_bits(&s->pb, 1, sign);
+                            put_bits(&s->pb, s->esc3_level_length, level);
+                        }else{
+                            put_bits(&s->pb, 6, run);
+                            put_bits(&s->pb, 8, slevel & 0xff);
+                        }
                     } else {
                         /* second escape */
                         put_bits(&s->pb, 1, 1);
@@ -684,7 +1012,7 @@ static void msmpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n)
 /****************************************/
 /* decoding stuff */
 
-static VLC mb_non_intra_vlc;
+static VLC mb_non_intra_vlc[4];
 static VLC mb_intra_vlc;
 static VLC dc_lum_vlc[2];
 static VLC dc_chroma_vlc[2];
@@ -696,15 +1024,12 @@ static VLC v2_mb_type_vlc;
 static VLC v2_mv_vlc;
 static VLC v1_intra_cbpc_vlc;
 static VLC v1_inter_cbpc_vlc;
+static VLC inter_intra_vlc;
 
 /* this table is practically identical to the one from h263 except that its inverted */
-static void init_h263_dc_for_msmpeg4()
+static void init_h263_dc_for_msmpeg4(void)
 {
-    static int inited=0;
-    
-    if(!inited){
         int level, uni_code, uni_len;
-        inited=1;
 
         for(level=-256; level<256; level++){
             int size, v, l;
@@ -754,74 +1079,102 @@ static void init_h263_dc_for_msmpeg4()
             v2_dc_chroma_table[level+256][1]= uni_len;
 
         }
-    }
 }
 
 /* init all vlc decoding tables */
-int msmpeg4_decode_init_vlc(MpegEncContext *s)
+int ff_msmpeg4_decode_init(MpegEncContext *s)
 {
+    static int done = 0;
     int i;
     MVTable *mv;
 
-    for(i=0;i<NB_RL_TABLES;i++) {
-        init_rl(&rl_table[i]);
-        init_vlc_rl(&rl_table[i]);
-    }
-    for(i=0;i<2;i++) {
-        mv = &mv_tables[i];
-        init_vlc(&mv->vlc, 9, mv->n + 1, 
-                 mv->table_mv_bits, 1, 1,
-                 mv->table_mv_code, 2, 2);
-    }
+    common_init(s);
+
+    if (!done) {
+        done = 1;
+
+        for(i=0;i<NB_RL_TABLES;i++) {
+            init_rl(&rl_table[i]);
+            init_vlc_rl(&rl_table[i]);
+        }
+        for(i=0;i<2;i++) {
+            mv = &mv_tables[i];
+            init_vlc(&mv->vlc, MV_VLC_BITS, mv->n + 1, 
+                     mv->table_mv_bits, 1, 1,
+                     mv->table_mv_code, 2, 2);
+        }
 
-    init_vlc(&dc_lum_vlc[0], 9, 120, 
-             &table0_dc_lum[0][1], 8, 4,
-             &table0_dc_lum[0][0], 8, 4);
-    init_vlc(&dc_chroma_vlc[0], 9, 120, 
-             &table0_dc_chroma[0][1], 8, 4,
-             &table0_dc_chroma[0][0], 8, 4);
-    init_vlc(&dc_lum_vlc[1], 9, 120, 
-             &table1_dc_lum[0][1], 8, 4,
-             &table1_dc_lum[0][0], 8, 4);
-    init_vlc(&dc_chroma_vlc[1], 9, 120, 
-             &table1_dc_chroma[0][1], 8, 4,
-             &table1_dc_chroma[0][0], 8, 4);
+        init_vlc(&dc_lum_vlc[0], DC_VLC_BITS, 120, 
+                 &table0_dc_lum[0][1], 8, 4,
+                 &table0_dc_lum[0][0], 8, 4);
+        init_vlc(&dc_chroma_vlc[0], DC_VLC_BITS, 120, 
+                 &table0_dc_chroma[0][1], 8, 4,
+                 &table0_dc_chroma[0][0], 8, 4);
+        init_vlc(&dc_lum_vlc[1], DC_VLC_BITS, 120, 
+                 &table1_dc_lum[0][1], 8, 4,
+                 &table1_dc_lum[0][0], 8, 4);
+        init_vlc(&dc_chroma_vlc[1], DC_VLC_BITS, 120, 
+                 &table1_dc_chroma[0][1], 8, 4,
+                 &table1_dc_chroma[0][0], 8, 4);
     
-    init_h263_dc_for_msmpeg4();
-    init_vlc(&v2_dc_lum_vlc, 9, 512, 
-             &v2_dc_lum_table[0][1], 8, 4,
-             &v2_dc_lum_table[0][0], 8, 4);
-    init_vlc(&v2_dc_chroma_vlc, 9, 512, 
-             &v2_dc_chroma_table[0][1], 8, 4,
-             &v2_dc_chroma_table[0][0], 8, 4);
+        init_vlc(&v2_dc_lum_vlc, DC_VLC_BITS, 512, 
+                 &v2_dc_lum_table[0][1], 8, 4,
+                 &v2_dc_lum_table[0][0], 8, 4);
+        init_vlc(&v2_dc_chroma_vlc, DC_VLC_BITS, 512, 
+                 &v2_dc_chroma_table[0][1], 8, 4,
+                 &v2_dc_chroma_table[0][0], 8, 4);
     
-    init_vlc(&cbpy_vlc, 6, 16,
-             &cbpy_tab[0][1], 2, 1,
-             &cbpy_tab[0][0], 2, 1);
-    init_vlc(&v2_intra_cbpc_vlc, 3, 4,
-             &v2_intra_cbpc[0][1], 2, 1,
-             &v2_intra_cbpc[0][0], 2, 1);
-    init_vlc(&v2_mb_type_vlc, 5, 8,
-             &v2_mb_type[0][1], 2, 1,
-             &v2_mb_type[0][0], 2, 1);
-    init_vlc(&v2_mv_vlc, 9, 33,
-             &mvtab[0][1], 2, 1,
-             &mvtab[0][0], 2, 1);
-
-    init_vlc(&mb_non_intra_vlc, 9, 128, 
-             &table_mb_non_intra[0][1], 8, 4,
-             &table_mb_non_intra[0][0], 8, 4);
-    init_vlc(&mb_intra_vlc, 9, 64, 
-             &table_mb_intra[0][1], 4, 2,
-             &table_mb_intra[0][0], 4, 2);
+        init_vlc(&cbpy_vlc, CBPY_VLC_BITS, 16,
+                 &cbpy_tab[0][1], 2, 1,
+                 &cbpy_tab[0][0], 2, 1);
+        init_vlc(&v2_intra_cbpc_vlc, V2_INTRA_CBPC_VLC_BITS, 4,
+                 &v2_intra_cbpc[0][1], 2, 1,
+                 &v2_intra_cbpc[0][0], 2, 1);
+        init_vlc(&v2_mb_type_vlc, V2_MB_TYPE_VLC_BITS, 8,
+                 &v2_mb_type[0][1], 2, 1,
+                 &v2_mb_type[0][0], 2, 1);
+        init_vlc(&v2_mv_vlc, V2_MV_VLC_BITS, 33,
+                 &mvtab[0][1], 2, 1,
+                 &mvtab[0][0], 2, 1);
+
+        for(i=0; i<4; i++){
+            init_vlc(&mb_non_intra_vlc[i], MB_NON_INTRA_VLC_BITS, 128, 
+                     &wmv2_inter_table[i][0][1], 8, 4,
+                     &wmv2_inter_table[i][0][0], 8, 4); //FIXME name?
+        }
         
-    init_vlc(&v1_intra_cbpc_vlc, 6, 8, 
-             intra_MCBPC_bits, 1, 1,
-             intra_MCBPC_code, 1, 1);
-    init_vlc(&v1_inter_cbpc_vlc, 6, 25, 
-             inter_MCBPC_bits, 1, 1,
-             inter_MCBPC_code, 1, 1);
-
+        init_vlc(&mb_intra_vlc, MB_INTRA_VLC_BITS, 64, 
+                 &table_mb_intra[0][1], 4, 2,
+                 &table_mb_intra[0][0], 4, 2);
+        
+        init_vlc(&v1_intra_cbpc_vlc, V1_INTRA_CBPC_VLC_BITS, 8, 
+                 intra_MCBPC_bits, 1, 1,
+                 intra_MCBPC_code, 1, 1);
+        init_vlc(&v1_inter_cbpc_vlc, V1_INTER_CBPC_VLC_BITS, 25, 
+                 inter_MCBPC_bits, 1, 1,
+                 inter_MCBPC_code, 1, 1);
+        
+        init_vlc(&inter_intra_vlc, INTER_INTRA_VLC_BITS, 4, 
+                 &table_inter_intra[0][1], 2, 1,
+                 &table_inter_intra[0][0], 2, 1);
+    }
+    
+    switch(s->msmpeg4_version){
+    case 1:
+    case 2:
+        s->decode_mb= msmpeg4v12_decode_mb;
+        break;
+    case 3:
+    case 4:
+        s->decode_mb= msmpeg4v34_decode_mb;
+        break;
+    case 5:
+        s->decode_mb= wmv2_decode_mb;
+        break;
+    }
+    
+    s->slice_height= s->mb_height; //to avoid 1/0 if the first frame isnt a keyframe
+    
     return 0;
 }
 
@@ -837,12 +1190,12 @@ static int decode012(GetBitContext *gb)
 
 int msmpeg4_decode_picture_header(MpegEncContext * s)
 {
-    int code, code2;
+    int code;
 
 #if 0
 {
 int i;
-for(i=0; i<s->gb.size*8; i++)
+for(i=0; i<s->gb.size_in_bits; i++)
     printf("%d", get_bits1(&s->gb));
 //    get_bits1(&s->gb);
 printf("END\n");
@@ -867,7 +1220,13 @@ return -1;
         fprintf(stderr, "invalid picture type\n");
         return -1;
     }
-
+#if 0
+{
+    static int had_i=0;
+    if(s->pict_type == I_TYPE) had_i=1;
+    if(!had_i) return -1;
+}
+#endif
     s->qscale = get_bits(&s->gb, 5);
 
     if (s->pict_type == I_TYPE) {
@@ -881,8 +1240,10 @@ return -1;
             s->slice_height = code;
         }else{
             /* 0x17: one slice, 0x18: two slices, ... */
-            if (code < 0x17)
+            if (code < 0x17){
+                fprintf(stderr, "error, slice code was %X\n", code);
                 return -1;
+            }
 
             s->slice_height = s->mb_height / (code - 0x16);
         }
@@ -902,28 +1263,29 @@ return -1;
             s->dc_table_index = get_bits1(&s->gb);
             break;
         case 4:
-            msmpeg4_decode_ext_header(s, 999 /* bufer size (useless here) */);
-            printf("%X\n", show_bits(&s->gb, 24));
-            code= get_bits(&s->gb, 2);
-            if(code==1){
-                code2= get_bits(&s->gb, 3);
-                if(code2==7) skip_bits(&s->gb, 1);
+            msmpeg4_decode_ext_header(s, (2+5+5+17+7)/8);
+
+            if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb);
+            else                           s->per_mb_rl_table= 0;
+            
+            if(!s->per_mb_rl_table){
+                s->rl_chroma_table_index = decode012(&s->gb);
+                s->rl_table_index = decode012(&s->gb);
             }
-            printf("%X\n", show_bits(&s->gb, 24));
-            s->rl_chroma_table_index = 2;
-            s->rl_table_index = 2;
 
-            s->dc_table_index = 0;
+            s->dc_table_index = get_bits1(&s->gb);
+            s->inter_intra_pred= 0;
             break;
         }
         s->no_rounding = 1;
-/*     printf(" %d %d %d %d     \n", 
+/*     printf("qscale:%d rlc:%d rl:%d dc:%d mbrl:%d slice:%d   \n", 
                s->qscale,
                s->rl_chroma_table_index,
                s->rl_table_index, 
-               s->dc_table_index);*/
+               s->dc_table_index,
+                s->per_mb_rl_table,
+                s->slice_height);*/
     } else {
-        
         switch(s->msmpeg4_version){
         case 1:
         case 2:
@@ -945,33 +1307,41 @@ return -1;
 
             s->mv_table_index = get_bits1(&s->gb);
             break;
+        case 4:
+            s->use_skip_mb_code = get_bits1(&s->gb);
+
+            if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb);
+            else                           s->per_mb_rl_table= 0;
+
+            if(!s->per_mb_rl_table){
+                s->rl_table_index = decode012(&s->gb);
+                s->rl_chroma_table_index = s->rl_table_index;
+            }
+
+            s->dc_table_index = get_bits1(&s->gb);
+
+            s->mv_table_index = get_bits1(&s->gb);
+            s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE);
+            break;
         }
-/*     printf(" %d %d %d %d %d     \n", 
+/*     printf("skip:%d rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d   \n", 
                s->use_skip_mb_code, 
                s->rl_table_index, 
                s->rl_chroma_table_index, 
                s->dc_table_index,
-               s->mv_table_index);*/
+               s->mv_table_index,
+                s->per_mb_rl_table,
+                s->qscale);*/
        if(s->flipflop_rounding){
            s->no_rounding ^= 1;
        }else{
            s->no_rounding = 0;
        }
-//     printf("%d", s->no_rounding);
-//return -1;
     }
-    
-#if 0
-if(s->msmpeg4_version==2)
-{
-int i;
-for(i=0; i<s->gb.size*8; i++)
-//    printf("%d", get_bits1(&s->gb));
-    get_bits1(&s->gb);
-printf("END\n");
-return -1;
-}
-#endif
+//printf("%d %d %d %d %d\n", s->pict_type, s->bit_rate, s->inter_intra_pred, s->width, s->height);
+
+    s->esc3_level_length= 0;
+    s->esc3_run_length= 0;
 
 #ifdef DEBUG
     printf("*****frame %d:\n", frame_count++);
@@ -989,13 +1359,13 @@ int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size)
         int fps;
 
         fps= get_bits(&s->gb, 5);
-        s->bit_rate= get_bits(&s->gb, 11);
+        s->bit_rate= get_bits(&s->gb, 11)*1024;
         if(s->msmpeg4_version>=3)
             s->flipflop_rounding= get_bits1(&s->gb);
         else
             s->flipflop_rounding= 0;
 
-//        printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bit_rate, s->flipflop_rounding);
+//        printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bit_rate/1024, s->flipflop_rounding);
     }
     else if(left<length+8)
     {
@@ -1055,7 +1425,7 @@ static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code)
 {
     int code, val, sign, shift;
 
-    code = get_vlc(&s->gb, &v2_mv_vlc);
+    code = get_vlc2(&s->gb, v2_mv_vlc.table, V2_MV_VLC_BITS, 2);
 //     printf("MV code %d at %d %d pred: %d\n", code, s->mb_x,s->mb_y, pred);
     if (code < 0)
         return 0xffff;
@@ -1080,11 +1450,12 @@ static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code)
     return val;
 }
 
-
-static int msmpeg4v12_decode_mb(MpegEncContext *s, 
-                      DCTELEM block[6][64])
+static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
 {
     int cbp, code, i;
+    
+    s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0;
+    
     if (s->pict_type == P_TYPE) {
         if (s->use_skip_mb_code) {
             if (get_bits1(&s->gb)) {
@@ -1102,9 +1473,9 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s,
         }
 
         if(s->msmpeg4_version==2)
-            code = get_vlc(&s->gb, &v2_mb_type_vlc);
+            code = get_vlc2(&s->gb, v2_mb_type_vlc.table, V2_MB_TYPE_VLC_BITS, 1);
         else
-            code = get_vlc(&s->gb, &v1_inter_cbpc_vlc);
+            code = get_vlc2(&s->gb, v1_inter_cbpc_vlc.table, V1_INTER_CBPC_VLC_BITS, 3);
         if(code<0 || code>7){
             fprintf(stderr, "cbpc %d invalid at %d %d\n", code, s->mb_x, s->mb_y);
             return -1;
@@ -1116,9 +1487,9 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s,
     } else {
         s->mb_intra = 1;
         if(s->msmpeg4_version==2)
-            cbp= get_vlc(&s->gb, &v2_intra_cbpc_vlc);
+            cbp= get_vlc2(&s->gb, v2_intra_cbpc_vlc.table, V2_INTRA_CBPC_VLC_BITS, 1);
         else
-            cbp= get_vlc(&s->gb, &v1_intra_cbpc_vlc);
+            cbp= get_vlc2(&s->gb, v1_intra_cbpc_vlc.table, V1_INTRA_CBPC_VLC_BITS, 1);
         if(cbp<0 || cbp>3){
             fprintf(stderr, "cbpc %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);
             return -1;
@@ -1128,7 +1499,7 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s,
     if (!s->mb_intra) {
         int mx, my, cbpy;
         
-        cbpy= get_vlc(&s->gb, &cbpy_vlc);
+        cbpy= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1);
         if(cbpy<0){
             fprintf(stderr, "cbpy %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);
             return -1;
@@ -1148,16 +1519,16 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s,
     } else {
         if(s->msmpeg4_version==2){
             s->ac_pred = get_bits1(&s->gb);
-            cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2; //FIXME check errors
+            cbp|= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors
         } else{
             s->ac_pred = 0;
-            cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2; //FIXME check errors
+            cbp|= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors
             if(s->pict_type==P_TYPE) cbp^=0x3C;
         }
     }
 
     for (i = 0; i < 6; i++) {
-        if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0)
+        if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0)
        {
              fprintf(stderr,"\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
              return -1;
@@ -1166,43 +1537,19 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s,
     return 0;
 }
 
-int msmpeg4_decode_mb(MpegEncContext *s, 
-                      DCTELEM block[6][64])
+static int msmpeg4v34_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
 {
     int cbp, code, i;
     UINT8 *coded_val;
 
-    /* special slice handling */
-    if (s->mb_x == 0) {
-        if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
-            int wrap;
-            /* reset DC pred (set previous line to 1024) */
-            wrap = 2 * s->mb_width + 2;
-           msmpeg4_memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap],
-                           1024, 2 * s->mb_width);
-           wrap = s->mb_width + 2;
-           msmpeg4_memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap],
-                           1024, s->mb_width);
-           msmpeg4_memsetw(&s->dc_val[2][(1) + (s->mb_y) * wrap],
-                           1024, s->mb_width);
-
-           /* reset AC pred (set previous line to 0) */
-           wrap = s->mb_width * 2 + 2;
-           msmpeg4_memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16,
-                           0, 2 * s->mb_width*16);
-           wrap = s->mb_width + 2;
-           msmpeg4_memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16,
-                           0, s->mb_width*16);
-           msmpeg4_memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16,
-                           0, s->mb_width*16);
-
-            s->first_slice_line = 1;
-        } else {
-            s->first_slice_line = 0; 
-        }
-    }
+#ifdef PRINT_MB
+if(s->mb_x==0){
+    printf("\n");
+    if(s->mb_y==0) printf("\n");
+}
+#endif
 
-    if(s->msmpeg4_version<=2) return msmpeg4v12_decode_mb(s, block); //FIXME export function & call from outside perhaps
+    s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0;
     
     if (s->pict_type == P_TYPE) {
         set_stat(ST_INTER_MB);
@@ -1217,11 +1564,14 @@ int msmpeg4_decode_mb(MpegEncContext *s,
                 s->mv[0][0][0] = 0;
                 s->mv[0][0][1] = 0;
                 s->mb_skiped = 1;
+#ifdef PRINT_MB
+printf("S ");
+#endif
                 return 0;
             }
         }
         
-        code = get_vlc(&s->gb, &mb_non_intra_vlc);
+        code = get_vlc2(&s->gb, mb_non_intra_vlc[DEFAULT_INTER_INDEX].table, MB_NON_INTRA_VLC_BITS, 3);
         if (code < 0)
             return -1;
        //s->mb_intra = (code & 0x40) ? 0 : 1;
@@ -1231,7 +1581,7 @@ int msmpeg4_decode_mb(MpegEncContext *s,
     } else {
         set_stat(ST_INTRA_MB);
         s->mb_intra = 1;
-        code = get_vlc(&s->gb, &mb_intra_vlc);
+        code = get_vlc2(&s->gb, mb_intra_vlc.table, MB_INTRA_VLC_BITS, 2);
         if (code < 0)
             return -1;
         /* predict coded block pattern */
@@ -1249,6 +1599,11 @@ int msmpeg4_decode_mb(MpegEncContext *s,
 
     if (!s->mb_intra) {
         int mx, my;
+//printf("P at %d %d\n", s->mb_x, s->mb_y);
+        if(s->per_mb_rl_table && cbp){
+            s->rl_table_index = decode012(&s->gb);
+            s->rl_chroma_table_index = s->rl_table_index;
+        }
         set_stat(ST_MV);
         h263_pred_motion(s, 0, &mx, &my);
         if (msmpeg4_decode_motion(s, &mx, &my) < 0)
@@ -1257,29 +1612,44 @@ int msmpeg4_decode_mb(MpegEncContext *s,
         s->mv_type = MV_TYPE_16X16;
         s->mv[0][0][0] = mx;
         s->mv[0][0][1] = my;
+#ifdef PRINT_MB
+printf("P ");
+#endif
     } else {
+//printf("I at %d %d %d %06X\n", s->mb_x, s->mb_y, ((cbp&3)? 1 : 0) +((cbp&0x3C)? 2 : 0), show_bits(&s->gb, 24));
         set_stat(ST_INTRA_MB);
         s->ac_pred = get_bits1(&s->gb);
+#ifdef PRINT_MB
+printf("%c", s->ac_pred ? 'A' : 'I');
+#endif
+        if(s->inter_intra_pred){
+            s->h263_aic_dir= get_vlc2(&s->gb, inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1);
+//            printf("%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y);
+        }
+        if(s->per_mb_rl_table && cbp){
+            s->rl_table_index = decode012(&s->gb);
+            s->rl_chroma_table_index = s->rl_table_index;
+        }
     }
 
     for (i = 0; i < 6; i++) {
-        if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1) < 0)
+        if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0)
        {
            fprintf(stderr,"\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
            return -1;
        }
     }
-
+    
     return 0;
 }
-
-static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
-                              int n, int coded)
+//#define ERROR_DETAILS
+static inline int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
+                              int n, int coded, const uint8_t *scan_table)
 {
-    int code, level, i, j, last, run, run_diff;
+    int level, i, last, run, run_diff;
     int dc_pred_dir;
     RLTable *rl;
-    const UINT8 *scan_table;
+    RL_VLC_ELEM *rl_vlc;
     int qmul, qadd;
 
     if (s->mb_intra) {
@@ -1289,43 +1659,53 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
        /* DC coef */
         set_stat(ST_DC);
         level = msmpeg4_decode_dc(s, n, &dc_pred_dir);
+#ifdef PRINT_MB
+{
+    static int c;
+    if(n==0) c=0;
+    if(n==4) printf("%X", c);
+    c+= c +dc_pred_dir;
+}
+#endif
         if (level < 0){
-            fprintf(stderr, "dc overflow-\n");
-            return -1;
+            fprintf(stderr, "dc overflow- block: %d qscale: %d//\n", n, s->qscale);
+            if(s->inter_intra_pred) level=0;
+            else                    return -1;
         }
         if (n < 4) {
             rl = &rl_table[s->rl_table_index];
             if(level > 256*s->y_dc_scale){
-                fprintf(stderr, "dc overflow+\n");
-                return -1;
+                fprintf(stderr, "dc overflow+ L qscale: %d//\n", s->qscale);
+                if(!s->inter_intra_pred) return -1;
             }
         } else {
             rl = &rl_table[3 + s->rl_chroma_table_index];
             if(level > 256*s->c_dc_scale){
-                fprintf(stderr, "dc overflow+\n");
-                return -1;
+                fprintf(stderr, "dc overflow+ C qscale: %d//\n", s->qscale);
+                if(!s->inter_intra_pred) return -1;
             }
         }
         block[0] = level;
 
         run_diff = 0;
-       i = 1;
+        i = 0;
         if (!coded) {
             goto not_coded;
         }
         if (s->ac_pred) {
             if (dc_pred_dir == 0) 
-                scan_table = ff_alternate_vertical_scan; /* left */
+                scan_table = s->intra_v_scantable.permutated; /* left */
             else
-                scan_table = ff_alternate_horizontal_scan; /* top */
+                scan_table = s->intra_h_scantable.permutated; /* top */
         } else {
-            scan_table = zigzag_direct;
+            scan_table = s->intra_scantable.permutated;
         }
         set_stat(ST_INTRA_AC);
+        rl_vlc= rl->rl_vlc[0];
     } else {
         qmul = s->qscale << 1;
         qadd = (s->qscale - 1) | 1;
-       i = 0;
+        i = -1;
         rl = &rl_table[3 + s->rl_table_index];
 
         if(s->msmpeg4_version==2)
@@ -1334,26 +1714,71 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
             run_diff = 1;
 
         if (!coded) {
-            s->block_last_index[n] = i - 1;
+            s->block_last_index[n] = i;
             return 0;
         }
-        scan_table = zigzag_direct;
+        if(!scan_table)
+            scan_table = s->inter_scantable.permutated;
         set_stat(ST_INTER_AC);
+        rl_vlc= rl->rl_vlc[s->qscale];
     }
-
+  {
+    OPEN_READER(re, &s->gb);
     for(;;) {
-        code = get_vlc(&s->gb, &rl->vlc);
-        if (code < 0)
-            return -1;
-        if (code == rl->n) {
+        UPDATE_CACHE(re, &s->gb);
+        GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2);
+        if (level==0) {
+            int cache;
+            cache= GET_CACHE(re, &s->gb);
             /* escape */
-            if (s->msmpeg4_version==1 || get_bits1(&s->gb) == 0) {
-                if (s->msmpeg4_version==1 || get_bits1(&s->gb) == 0) {
+            if (s->msmpeg4_version==1 || (cache&0x80000000)==0) {
+                if (s->msmpeg4_version==1 || (cache&0x40000000)==0) {
                     /* third escape */
-                    last = get_bits1(&s->gb);
-                    run = get_bits(&s->gb, 6);
-                    level = get_bits(&s->gb, 8);
-                    level = (level << 24) >> 24; /* sign extend */
+                    if(s->msmpeg4_version!=1) LAST_SKIP_BITS(re, &s->gb, 2);
+                    UPDATE_CACHE(re, &s->gb);
+                    if(s->msmpeg4_version<=3){
+                        last=  SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1);
+                        run=   SHOW_UBITS(re, &s->gb, 6); SKIP_CACHE(re, &s->gb, 6);
+                        level= SHOW_SBITS(re, &s->gb, 8); LAST_SKIP_CACHE(re, &s->gb, 8);
+                        SKIP_COUNTER(re, &s->gb, 1+6+8);
+                    }else{                        
+                        int sign;
+                        last=  SHOW_UBITS(re, &s->gb, 1); SKIP_BITS(re, &s->gb, 1);
+                        if(!s->esc3_level_length){
+                            int ll;
+                            //printf("ESC-3 %X at %d %d\n", show_bits(&s->gb, 24), s->mb_x, s->mb_y);
+                            if(s->qscale<8){
+                                ll= SHOW_UBITS(re, &s->gb, 3); SKIP_BITS(re, &s->gb, 3);
+                                if(ll==0){
+                                    if(SHOW_UBITS(re, &s->gb, 1)) printf("cool a new vlc code ,contact the ffmpeg developers and upload the file\n");
+                                    SKIP_BITS(re, &s->gb, 1);
+                                    ll=8;
+                                }
+                            }else{
+                                ll=2;
+                                while(ll<8 && SHOW_UBITS(re, &s->gb, 1)==0){
+                                    ll++;
+                                    SKIP_BITS(re, &s->gb, 1);
+                                }
+                                if(ll<8) SKIP_BITS(re, &s->gb, 1);
+                            }
+
+                            s->esc3_level_length= ll;
+                            s->esc3_run_length= SHOW_UBITS(re, &s->gb, 2) + 3; SKIP_BITS(re, &s->gb, 2);
+//printf("level length:%d, run length: %d\n", ll, s->esc3_run_length);
+                            UPDATE_CACHE(re, &s->gb);
+                        }
+                        run=   SHOW_UBITS(re, &s->gb, s->esc3_run_length); 
+                        SKIP_BITS(re, &s->gb, s->esc3_run_length);
+                        
+                        sign=  SHOW_UBITS(re, &s->gb, 1); 
+                        SKIP_BITS(re, &s->gb, 1);
+                        
+                        level= SHOW_UBITS(re, &s->gb, s->esc3_level_length); 
+                        SKIP_BITS(re, &s->gb, s->esc3_level_length);
+                        if(sign) level= -level;
+                    }
+//printf("level: %d, run: %d at %d %d\n", level, run, s->mb_x, s->mb_y);
 #if 0 // waste of time / this will detect very few errors
                     {
                         const int abs_level= ABS(level);
@@ -1367,7 +1792,7 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
                                 fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n");
                                 return DECODING_AC_LOST;
                             }
-                            if(abs_level <= rl->max_level[last][run1] && 0){
+                            if(run1>=0 && abs_level <= rl->max_level[last][run1]){
                                 fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n");
                                 return DECODING_AC_LOST;
                             }
@@ -1382,59 +1807,96 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
                         fprintf(stderr, "|level| overflow in 3. esc\n");
                         return DECODING_AC_LOST;
                     }
+#endif
+                    i+= run + 1;
+                    if(last) i+=192;
+#ifdef ERROR_DETAILS
+                if(run==66)
+                    fprintf(stderr, "illegal vlc code in ESC3 level=%d\n", level);
+                else if((i>62 && i<192) || i>192+63)
+                    fprintf(stderr, "run overflow in ESC3 i=%d run=%d level=%d\n", i, run, level);
 #endif
                 } else {
                     /* second escape */
-                    code = get_vlc(&s->gb, &rl->vlc);
-                    if (code < 0 || code >= rl->n)
-                        return -1;
-                    run = rl->table_run[code];
-                    level = rl->table_level[code];
-                    last = code >= rl->last;
-                    run += rl->max_run[last][level] + run_diff;
-                    level= level * qmul + qadd;
-                    if (get_bits1(&s->gb))
-                        level = -level;
+#if MIN_CACHE_BITS < 23
+                    LAST_SKIP_BITS(re, &s->gb, 2);
+                    UPDATE_CACHE(re, &s->gb);
+#else
+                    SKIP_BITS(re, &s->gb, 2);
+#endif
+                    GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2);
+                    i+= run + rl->max_run[run>>7][level/qmul] + run_diff; //FIXME opt indexing
+                    level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1);
+                    LAST_SKIP_BITS(re, &s->gb, 1);
+#ifdef ERROR_DETAILS
+                if(run==66)
+                    fprintf(stderr, "illegal vlc code in ESC2 level=%d\n", level);
+                else if((i>62 && i<192) || i>192+63)
+                    fprintf(stderr, "run overflow in ESC2 i=%d run=%d level=%d\n", i, run, level);
+#endif
                 }
             } else {
                 /* first escape */
-                code = get_vlc(&s->gb, &rl->vlc);
-                if (code < 0 || code >= rl->n)
-                    return -1;
-                run = rl->table_run[code];
-                level = rl->table_level[code];
-                last = code >= rl->last;
-                level += rl->max_level[last][run];
-                level= level * qmul + qadd;
-                if (get_bits1(&s->gb))
-                    level = -level;
+#if MIN_CACHE_BITS < 22
+                LAST_SKIP_BITS(re, &s->gb, 1);
+                UPDATE_CACHE(re, &s->gb);
+#else
+                SKIP_BITS(re, &s->gb, 1);
+#endif
+                GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2);
+                i+= run;
+                level = level + rl->max_level[run>>7][(run-1)&63] * qmul;//FIXME opt indexing
+                level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1);
+                LAST_SKIP_BITS(re, &s->gb, 1);
+#ifdef ERROR_DETAILS
+                if(run==66)
+                    fprintf(stderr, "illegal vlc code in ESC1 level=%d\n", level);
+                else if((i>62 && i<192) || i>192+63)
+                    fprintf(stderr, "run overflow in ESC1 i=%d run=%d level=%d\n", i, run, level);
+#endif
             }
         } else {
-            run = rl->table_run[code];
-            level = rl->table_level[code] * qmul + qadd;
-            last = code >= rl->last;
-            if (get_bits1(&s->gb))
-                level = -level;
+            i+= run;
+            level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1);
+            LAST_SKIP_BITS(re, &s->gb, 1);
+#ifdef ERROR_DETAILS
+                if(run==66)
+                    fprintf(stderr, "illegal vlc code level=%d\n", level);
+                else if((i>62 && i<192) || i>192+63)
+                    fprintf(stderr, "run overflow i=%d run=%d level=%d\n", i, run, level);
+#endif
         }
-        i += run;
-        if (i >= 64)
-            return -1;
+        if (i > 62){
+            i-= 192;
+            if(i&(~63)){
+                const int left= s->gb.size_in_bits - get_bits_count(&s->gb);
+                if(((i+192 == 64 && level/qmul==-1) || s->error_resilience<=1) && left>=0){
+                    fprintf(stderr, "ignoring overflow at %d %d\n", s->mb_x, s->mb_y);
+                    break;
+                }else{
+                    fprintf(stderr, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y);
+                    return -1;
+                }
+            }
 
-       j = scan_table[i];
-        block[j] = level;
-        i++;
-        if (last)
+            block[scan_table[i]] = level;
             break;
+        }
+
+        block[scan_table[i]] = level;
     }
+    CLOSE_READER(re, &s->gb);
+  }
  not_coded:
     if (s->mb_intra) {
         mpeg4_pred_ac(s, block, n, dc_pred_dir);
         if (s->ac_pred) {
-            i = 64; /* XXX: not optimal */
+            i = 63; /* XXX: not optimal */
         }
     }
-    s->block_last_index[n] = i - 1;
-
+    if(s->msmpeg4_version>=4 && i>0) i=63; //FIXME/XXX optimize
+    s->block_last_index[n] = i;
+    
     return 0;
 }
 
@@ -1444,18 +1906,18 @@ static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
 
     if(s->msmpeg4_version<=2){
         if (n < 4) {
-            level = get_vlc(&s->gb, &v2_dc_lum_vlc);
+            level = get_vlc2(&s->gb, v2_dc_lum_vlc.table, DC_VLC_BITS, 3);
         } else {
-            level = get_vlc(&s->gb, &v2_dc_chroma_vlc);
+            level = get_vlc2(&s->gb, v2_dc_chroma_vlc.table, DC_VLC_BITS, 3);
         }
         if (level < 0) 
             return -1;
         level-=256;
     }else{  //FIXME optimize use unified tables & index
         if (n < 4) {
-            level = get_vlc(&s->gb, &dc_lum_vlc[s->dc_table_index]);
+            level = get_vlc2(&s->gb, dc_lum_vlc[s->dc_table_index].table, DC_VLC_BITS, 3);
         } else {
-            level = get_vlc(&s->gb, &dc_chroma_vlc[s->dc_table_index]);
+            level = get_vlc2(&s->gb, dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3);
         }
         if (level < 0){
             fprintf(stderr, "illegal dc vlc\n");
@@ -1480,7 +1942,7 @@ static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
         /* update predictor */
         *dc_val= level;
     }else{
-        INT16 *dc_val;
+        UINT16 *dc_val;
         pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
         level += pred;
 
@@ -1503,10 +1965,13 @@ static int msmpeg4_decode_motion(MpegEncContext * s,
 
     mv = &mv_tables[s->mv_table_index];
 
-    code = get_vlc(&s->gb, &mv->vlc);
-    if (code < 0)
+    code = get_vlc2(&s->gb, mv->vlc.table, MV_VLC_BITS, 2);
+    if (code < 0){
+        fprintf(stderr, "illegal MV code at %d %d\n", s->mb_x, s->mb_y);
         return -1;
+    }
     if (code == mv->n) {
+//printf("MV ESC %X at %d %d\n", show_bits(&s->gb, 24), s->mb_x, s->mb_y);
         mx = get_bits(&s->gb, 6);
         my = get_bits(&s->gb, 6);
     } else {
@@ -1530,3 +1995,9 @@ static int msmpeg4_decode_motion(MpegEncContext * s,
     *my_ptr = my;
     return 0;
 }
+
+/* cleanest way to support it
+ * there is too much shared between versions so that we cant have 1 file per version & 1 common
+ * as allmost everything would be in the common file 
+ */
+#include "wmv2.c"