]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/msmpeg4.c
moved the tables into header files (and applied the 'static' patch). Nick: why do...
[ffmpeg] / libavcodec / msmpeg4.c
index 66fc5255e488856fbb03ca67eafd5204982f0d99..839d8dbac4284424b2797a8030f430c043be8537 100644 (file)
@@ -1,27 +1,32 @@
 /*
  * MSMPEG4 backend for ffmpeg encoder and decoder
- * Copyright (c) 2001 Gerard Lantau.
+ * Copyright (c) 2001 Fabrice Bellard.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
+ * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
+ */
+
+/**
+ * @file msmpeg4.c
+ * MSMPEG4 backend for ffmpeg encoder and decoder.
  */
-#include <stdlib.h>
-#include <stdio.h>
-#include "common.h"
+
+#include "avcodec.h"
 #include "dsputil.h"
 #include "mpegvideo.h"
-#include "avcodec.h"
 
 /*
  * 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;
-
-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);
+#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_t v2_dc_lum_table[512][2];
+static uint32_t v2_dc_chroma_table[512][2];
+
+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);
+#ifdef CONFIG_ENCODERS
+static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, int level, int intra);
+#endif //CONFIG_ENCODERS
+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"
 
+#ifdef CONFIG_ENCODERS //strangely gcc includes this even if its not references
+static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2];
+#endif //CONFIG_ENCODERS
+
 #ifdef STATS
 
 const char *st_names[ST_NB] = {
@@ -132,12 +150,56 @@ 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->dsp.idct_permutation, &s->intra_scantable  , wmv1_scantable[1]);
+        ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, wmv1_scantable[2]);
+        ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, wmv1_scantable[3]);
+        ff_init_scantable(s->dsp.idct_permutation, &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();
+    }
+}
+
+#ifdef CONFIG_ENCODERS
+
 /* build the table which associate a (x,y) motion vector to a vlc */
 static void init_mv_table(MVTable *tab)
 {
     int i, x, y;
 
-    tab->table_mv_index = malloc(sizeof(UINT16) * 4096);
+    tab->table_mv_index = av_malloc(sizeof(uint16_t) * 4096);
     /* mark all entries as not used */
     for(i=0;i<4096;i++)
         tab->table_mv_index[i] = tab->n;
@@ -159,66 +221,206 @@ static void code012(PutBitContext *pb, int n)
     }
 }
 
-/* write MSMPEG4 V3 compatible frame header */
-void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
+void ff_msmpeg4_encode_init(MpegEncContext *s)
 {
+    static int init_done=0;
     int i;
 
-    align_put_bits(&s->pb);
+    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)
+{
+    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->msmpeg4_version>2){
+            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!=2){
-            code012(&s->pb, 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){
+            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;
@@ -228,18 +430,20 @@ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
 
 void msmpeg4_encode_ext_header(MpegEncContext * s)
 {
-        s->flipflop_rounding=1;
-        s->bitrate= 910; // FIXME
-
-        put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29
+        put_bits(&s->pb, 5, s->avctx->frame_rate / s->avctx->frame_rate_base); //yes 29.97 -> 29
 
-       put_bits(&s->pb, 11, s->bitrate);
+        put_bits(&s->pb, 11, FFMIN(s->bit_rate/1024, 2047));
 
-       put_bits(&s->pb, 1, s->flipflop_rounding);
+        if(s->msmpeg4_version>=3)
+            put_bits(&s->pb, 1, s->flipflop_rounding);
+        else
+            assert(s->flipflop_rounding==0);
 }
 
+#endif //CONFIG_ENCODERS
+
 /* predict coded block */
-static inline int coded_block_pred(MpegEncContext * s, int n, UINT8 **coded_block_ptr)
+static inline int coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr)
 {
     int xy, wrap, pred, a, b, c;
 
@@ -265,6 +469,8 @@ static inline int coded_block_pred(MpegEncContext * s, int n, UINT8 **coded_bloc
     return pred;
 }
 
+#ifdef CONFIG_ENCODERS
+
 static void msmpeg4_encode_motion(MpegEncContext * s, 
                                   int mx, int my)
 {
@@ -304,14 +510,29 @@ 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)
 {
     int cbp, coded_cbp, i;
     int pred_x, pred_y;
-    UINT8 *coded_block;
+    uint8_t *coded_block;
 
+    handle_slices(s);
+    
     if (!s->mb_intra) {
        /* compute cbp */
         set_stat(ST_INTER_MB);
@@ -323,12 +544,16 @@ void msmpeg4_encode_mb(MpegEncContext * s,
        if (s->use_skip_mb_code && (cbp | motion_x | motion_y) == 0) {
            /* skip macroblock */
            put_bits(&s->pb, 1, 1);
+            s->last_bits++;
+           s->misc_bits++;
+            s->skip_count++;
+
            return;
        }
         if (s->use_skip_mb_code)
             put_bits(&s->pb, 1, 0);    /* mb coded */
         
-        if(s->msmpeg4_version==2){
+        if(s->msmpeg4_version<=2){
             put_bits(&s->pb, 
                      v2_mb_type[cbp&3][1], 
                      v2_mb_type[cbp&3][0]);
@@ -338,7 +563,9 @@ void msmpeg4_encode_mb(MpegEncContext * s,
             put_bits(&s->pb, 
                      cbpy_tab[coded_cbp>>2][1], 
                      cbpy_tab[coded_cbp>>2][0]);
-                        
+
+            s->misc_bits += get_bits_diff(s);
+
             h263_pred_motion(s, 0, &pred_x, &pred_y);
             msmpeg4v2_encode_motion(s, motion_x - pred_x);
             msmpeg4v2_encode_motion(s, motion_y - pred_y);
@@ -347,11 +574,20 @@ void msmpeg4_encode_mb(MpegEncContext * s,
                      table_mb_non_intra[cbp + 64][1], 
                      table_mb_non_intra[cbp + 64][0]);
 
+            s->misc_bits += get_bits_diff(s);
+
             /* motion vector */
             h263_pred_motion(s, 0, &pred_x, &pred_y);
             msmpeg4_encode_motion(s, motion_x - pred_x, 
                                   motion_y - pred_y);
         }
+
+        s->mv_bits += get_bits_diff(s);
+
+        for (i = 0; i < 6; i++) {
+            msmpeg4_encode_block(s, block[i], i);
+        }
+        s->p_tex_bits += get_bits_diff(s);
     } else {
        /* compute cbp */
        cbp = 0;
@@ -373,7 +609,7 @@ void msmpeg4_encode_mb(MpegEncContext * s,
             printf("cbp=%x %x\n", cbp, coded_cbp);
 #endif
 
-        if(s->msmpeg4_version==2){
+        if(s->msmpeg4_version<=2){
             if (s->pict_type == I_TYPE) {
                 put_bits(&s->pb, 
                          v2_intra_cbpc[cbp&3][1], v2_intra_cbpc[cbp&3][0]);
@@ -402,19 +638,27 @@ 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]);
+            }
         }
-    }
+        s->misc_bits += get_bits_diff(s);
 
-    for (i = 0; i < 6; i++) {
-        msmpeg4_encode_block(s, block[i], i);
+        for (i = 0; i < 6; i++) {
+            msmpeg4_encode_block(s, block[i], i);
+        }
+        s->i_tex_bits += get_bits_diff(s);
+        s->i_count++;
     }
 }
 
+#endif //CONFIG_ENCODERS
 
-/* strongly inspirated from MPEG4, but not exactly the same ! */
-void msmpeg4_dc_scale(MpegEncContext * s)
+/* old ffmpeg msmpeg4v3 mode */
+static void ff_old_msmpeg4_dc_scale(MpegEncContext * s)
 {
-    if (s->qscale < 5 || s->msmpeg4_version==2){
+    if (s->qscale < 5){
         s->y_dc_scale = 8;
         s->c_dc_scale = 8;
     }else if (s->qscale < 9){
@@ -426,12 +670,40 @@ void msmpeg4_dc_scale(MpegEncContext * s)
     }
 }
 
+static inline int msmpeg4v1_pred_dc(MpegEncContext * s, int n, 
+                                    int32_t **dc_val_ptr)
+{
+    int i;
+
+    if (n < 4) {
+        i= 0;
+    } else {
+        i= n-3;
+    }
+    
+    *dc_val_ptr= &s->last_dc[i];
+    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 FASTDIV((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_t **dc_val_ptr, int *dir_ptr)
 {
     int a, b, c, wrap, pred, scale;
-    INT16 *dc_val;
+    int16_t *dc_val;
 
     /* find prediction */
     if (n < 4) {
@@ -439,6 +711,7 @@ static int msmpeg4_pred_dc(MpegEncContext * s, int n,
     } else {
        scale = s->c_dc_scale;
     }
+    
     wrap = s->block_wrap[n];
     dc_val= s->dc_val[0] + s->block_index[n];
 
@@ -448,6 +721,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
@@ -482,19 +759,86 @@ static int msmpeg4_pred_dc(MpegEncContext * s, int n,
        b = (b + (8 >> 1)) / 8;
        c = (c + (8 >> 1)) / 8;
     } else {
-       a = (a + (scale >> 1)) / scale;
-       b = (b + (scale >> 1)) / scale;
-       c = (c + (scale >> 1)) / scale;
+       a = FASTDIV((a + (scale >> 1)), scale);
+       b = FASTDIV((b + (scale >> 1)), scale);
+       c = FASTDIV((c + (scale >> 1)), scale);
     }
 #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 */
@@ -508,21 +852,29 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr
 {
     int sign, code;
     int pred;
-    INT16 *dc_val;
 
-    pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+    if(s->msmpeg4_version==1){
+        int32_t *dc_val;
+        pred = msmpeg4v1_pred_dc(s, n, &dc_val);
+        
+        /* update predictor */
+        *dc_val= level;
+    }else{
+        uint16_t *dc_val;
+        pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
 
-    /* update predictor */
-    if (n < 4) {
-        *dc_val = level * s->y_dc_scale;
-    } else {
-        *dc_val = level * s->c_dc_scale;
+        /* update predictor */
+        if (n < 4) {
+            *dc_val = level * s->y_dc_scale;
+        } else {
+            *dc_val = level * s->c_dc_scale;
+        }
     }
 
     /* do the prediction */
     level -= pred;
 
-    if(s->msmpeg4_version==2){
+    if(s->msmpeg4_version<=2){
         if (n < 4) {
             put_bits(&s->pb, 
                      v2_dc_lum_table[level+256][1],
@@ -568,12 +920,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_t *scantable;
 
     if (s->mb_intra) {
         set_stat(ST_DC);
@@ -585,22 +938,31 @@ 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;
         rl = &rl_table[3 + s->rl_table_index];
-        if(s->msmpeg4_version==2)
+        if(s->msmpeg4_version<=2)
             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;
@@ -611,6 +973,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) {
@@ -634,8 +1004,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);
@@ -659,7 +1043,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];
@@ -669,15 +1053,14 @@ static VLC cbpy_vlc;
 static VLC v2_intra_cbpc_vlc;
 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;
@@ -727,66 +1110,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]);
+    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], 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_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, 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(&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);
     }
-    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);
+    
+    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;
     }
-
-    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_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);
+    s->slice_height= s->mb_height; //to avoid 1/0 if the first frame isnt a keyframe
     
-    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);
     return 0;
 }
 
@@ -804,79 +1223,160 @@ int msmpeg4_decode_picture_header(MpegEncContext * s)
 {
     int code;
 
+#if 0
+{
+int i;
+for(i=0; i<s->gb.size_in_bits; i++)
+    printf("%d", get_bits1(&s->gb));
+//    get_bits1(&s->gb);
+printf("END\n");
+return -1;
+}
+#endif
+
+    if(s->msmpeg4_version==1){
+        int start_code, num;
+        start_code = (get_bits(&s->gb, 16)<<16) | get_bits(&s->gb, 16);
+        if(start_code!=0x00000100){
+            fprintf(stderr, "invalid startcode\n");
+            return -1;
+        }
+
+        num= get_bits(&s->gb, 5); // frame number */
+    }
+
     s->pict_type = get_bits(&s->gb, 2) + 1;
     if (s->pict_type != I_TYPE &&
-        s->pict_type != P_TYPE)
+        s->pict_type != P_TYPE){
+        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->qscale==0){
+        fprintf(stderr, "invalid qscale\n");
+        return -1;
+    }
 
     if (s->pict_type == I_TYPE) {
         code = get_bits(&s->gb, 5); 
-        /* 0x17: one slice, 0x18: two slices */
-        if (code < 0x17)
-            return -1;
-        s->slice_height = s->mb_height / (code - 0x16);
-        if(s->msmpeg4_version==2){
+        if(s->msmpeg4_version==1){
+            if(code==0 || code>s->mb_height){
+                fprintf(stderr, "invalid slice height %d\n", code);
+                return -1;
+            }
+
+            s->slice_height = code;
+        }else{
+            /* 0x17: one slice, 0x18: two slices, ... */
+            if (code < 0x17){
+                fprintf(stderr, "error, slice code was %X\n", code);
+                return -1;
+            }
+
+            s->slice_height = s->mb_height / (code - 0x16);
+        }
+
+        switch(s->msmpeg4_version){
+        case 1:
+        case 2:
             s->rl_chroma_table_index = 2;
             s->rl_table_index = 2;
 
             s->dc_table_index = 0; //not used
-        }else{
+            break;
+        case 3:
             s->rl_chroma_table_index = decode012(&s->gb);
             s->rl_table_index = decode012(&s->gb);
 
             s->dc_table_index = get_bits1(&s->gb);
+            break;
+        case 4:
+            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);
+            }
+
+            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 {
-        s->use_skip_mb_code = get_bits1(&s->gb);
-        
-        if(s->msmpeg4_version==2){
+        switch(s->msmpeg4_version){
+        case 1:
+        case 2:
+            if(s->msmpeg4_version==1)
+                s->use_skip_mb_code = 1;
+            else
+                s->use_skip_mb_code = get_bits1(&s->gb);
             s->rl_table_index = 2;
             s->rl_chroma_table_index = s->rl_table_index;
-
             s->dc_table_index = 0; //not used
-
             s->mv_table_index = 0;
-        }else{
+            break;
+        case 3:
+            s->use_skip_mb_code = get_bits1(&s->gb);
             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);
+            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);
     }
-    
-#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++);
@@ -886,27 +1386,36 @@ return -1;
 
 int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size)
 {
+    int left= buf_size*8 - get_bits_count(&s->gb);
+    int length= s->msmpeg4_version>=3 ? 17 : 16;
     /* the alt_bitstream reader could read over the end so we need to check it */
-    if(get_bits_count(&s->gb) + 16 < buf_size*8)
+    if(left>=length && left<length+8)
     {
         int fps;
 
         fps= get_bits(&s->gb, 5);
-        s->bitrate= get_bits(&s->gb, 11);
-        s->flipflop_rounding= get_bits1(&s->gb);
+        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->bitrate, s->flipflop_rounding);
+//        printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bit_rate/1024, s->flipflop_rounding);
     }
-    else
+    else if(left<length+8)
     {
         s->flipflop_rounding= 0;
-        s->bitrate= 0;
+        printf("ext header missing, %d left\n", left);
+    }
+    else
+    {
+        fprintf(stderr, "I frame too long, ignoring ext header\n");
     }
 
     return 0;
 }
 
-static inline void memsetw(short *tab, int val, int n)
+static inline void msmpeg4_memsetw(short *tab, int val, int n)
 {
     int i;
     for(i=0;i<n;i++)
@@ -951,7 +1460,8 @@ 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;
 
@@ -959,14 +1469,16 @@ static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code)
         return pred;
     sign = get_bits1(&s->gb);
     shift = f_code - 1;
-    val = (code - 1) << shift;
-    if (shift > 0)
+    val = code;
+    if (shift) {
+        val = (val - 1) << shift;
         val |= get_bits(&s->gb, shift);
-    val++;
+        val++;
+    }
     if (sign)
         val = -val;
-    val += pred;
 
+    val += pred;
     if (val <= -64)
         val += 64;
     else if (val >= 64)
@@ -975,11 +1487,10 @@ static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code)
     return val;
 }
 
-
-int msmpeg4v2_decode_mb(MpegEncContext *s, 
-                      DCTELEM block[6][64])
+static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
 {
     int cbp, code, i;
+    
     if (s->pict_type == P_TYPE) {
         if (s->use_skip_mb_code) {
             if (get_bits1(&s->gb)) {
@@ -996,20 +1507,41 @@ int msmpeg4v2_decode_mb(MpegEncContext *s,
             }
         }
 
-        code = get_vlc(&s->gb, &v2_mb_type_vlc);
+        if(s->msmpeg4_version==2)
+            code = get_vlc2(&s->gb, v2_mb_type_vlc.table, V2_MB_TYPE_VLC_BITS, 1);
+        else
+            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;
+        }
+
         s->mb_intra = code >>2;
     
         cbp = code & 0x3;
     } else {
         s->mb_intra = 1;
-        cbp= get_vlc(&s->gb, &v2_intra_cbpc_vlc);
+        if(s->msmpeg4_version==2)
+            cbp= get_vlc2(&s->gb, v2_intra_cbpc_vlc.table, V2_INTRA_CBPC_VLC_BITS, 1);
+        else
+            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;
+        }
     }
 
     if (!s->mb_intra) {
-        int mx, my;
+        int mx, my, cbpy;
+        
+        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;
+        }
 
-        cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2;
-        if((cbp&3) != 3) cbp^= 0x3C;
+        cbp|= cbpy<<2;
+        if(s->msmpeg4_version==1 || (cbp&3) != 3) cbp^= 0x3C;
         
         h263_pred_motion(s, 0, &mx, &my);
         mx= msmpeg4v2_decode_motion(s, mx, 1);
@@ -1020,58 +1552,32 @@ int msmpeg4v2_decode_mb(MpegEncContext *s,
         s->mv[0][0][0] = mx;
         s->mv[0][0][1] = my;
     } else {
-        s->ac_pred = get_bits1(&s->gb);
-        cbp|= get_vlc(&s->gb, &cbpy_vlc)<<2;
+        if(s->msmpeg4_version==2){
+            s->ac_pred = get_bits1(&s->gb);
+            cbp|= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors
+        } else{
+            s->ac_pred = 0;
+            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,"\nIgnoring error while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
+             fprintf(stderr,"\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
              return -1;
        }
     }
     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;
-            memsetw(&s->dc_val[0][(1) + (2 * s->mb_y) * wrap], 
-                    1024, 2 * s->mb_width);
-            wrap = s->mb_width + 2;
-            memsetw(&s->dc_val[1][(1) + (s->mb_y) * wrap], 
-                    1024, s->mb_width);
-            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;
-            memsetw(s->ac_val[0][0] + (1 + (2 * s->mb_y) * wrap)*16,
-                    0, 2 * s->mb_width*16);
-            wrap = s->mb_width + 2;
-            memsetw(s->ac_val[1][0] + (1 + (s->mb_y) * wrap)*16,
-                    0, s->mb_width*16);
-            memsetw(s->ac_val[2][0] + (1 + (s->mb_y) * wrap)*16,
-                    0, s->mb_width*16);
+    uint8_t *coded_val;
+    uint32_t * const mb_type_ptr= &s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride ];
 
-            s->first_slice_line = 1;
-        } else {
-            s->first_slice_line = 0; 
-        }
-    }
-
-    if(s->msmpeg4_version==2) return msmpeg4v2_decode_mb(s, block); //FIXME merge if possible
-    
     if (s->pict_type == P_TYPE) {
         set_stat(ST_INTER_MB);
         if (s->use_skip_mb_code) {
@@ -1085,11 +1591,13 @@ int msmpeg4_decode_mb(MpegEncContext *s,
                 s->mv[0][0][0] = 0;
                 s->mv[0][0][1] = 0;
                 s->mb_skiped = 1;
+                *mb_type_ptr = MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16;
+
                 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;
@@ -1099,7 +1607,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 */
@@ -1117,6 +1625,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)
@@ -1125,28 +1638,40 @@ int msmpeg4_decode_mb(MpegEncContext *s,
         s->mv_type = MV_TYPE_16X16;
         s->mv[0][0][0] = mx;
         s->mv[0][0][1] = my;
+        *mb_type_ptr = MB_TYPE_L0 | MB_TYPE_16x16;
     } 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);
+        *mb_type_ptr = MB_TYPE_INTRA;
+        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,"\nIgnoring error while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
-           // return -1;
+           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) {
@@ -1156,33 +1681,46 @@ static int msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
        /* DC coef */
         set_stat(ST_DC);
         level = msmpeg4_decode_dc(s, n, &dc_pred_dir);
-        if (level < 0)
-            return -1;
-        block[0] = level;
+        
+        if (level < 0){
+            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+ 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+ 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)
@@ -1191,105 +1729,215 @@ 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 (get_bits1(&s->gb) == 0) {
-                if (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);
+                        const int run1= run - rl->max_run[last][abs_level] - run_diff;
+                        if(abs_level<=MAX_LEVEL && run<=MAX_RUN){
+                            if(abs_level <= rl->max_level[last][run]){
+                                fprintf(stderr, "illegal 3. esc, vlc encoding possible\n");
+                                return DECODING_AC_LOST;
+                            }
+                            if(abs_level <= rl->max_level[last][run]*2){
+                                fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n");
+                                return DECODING_AC_LOST;
+                            }
+                            if(run1>=0 && abs_level <= rl->max_level[last][run1]){
+                                fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n");
+                                return DECODING_AC_LOST;
+                            }
+                        }
+                    }
+#endif
                    //level = level * qmul + (level>0) * qadd - (level<=0) * qadd ;
                    if (level>0) level= level * qmul + qadd;
-                    else        level= level * qmul - qadd;
+                    else         level= level * qmul - qadd;
+#if 0 // waste of time too :(
+                    if(level>2048 || level<-2048){
+                        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;
-       j = scan_table[i];
-        block[j] = level;
-        i++;
-        if (last)
+        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;
+                }
+            }
+
+            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;
 }
 
 static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
 {
     int level, pred;
-    INT16 *dc_val;
 
-    if(s->msmpeg4_version==2){
+    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)
+        if (level < 0){
+            fprintf(stderr, "illegal dc vlc\n");
             return -1;
+        }
 
         if (level == DC_MAX) {
             level = get_bits(&s->gb, 8);
@@ -1301,14 +1949,24 @@ static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr)
         }
     }
 
-    pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
-    level += pred;
+    if(s->msmpeg4_version==1){
+        int32_t *dc_val;
+        pred = msmpeg4v1_pred_dc(s, n, &dc_val);
+        level += pred;
+        
+        /* update predictor */
+        *dc_val= level;
+    }else{
+        uint16_t *dc_val;
+        pred = msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
+        level += pred;
 
-    /* update predictor */
-    if (n < 4) {
-        *dc_val = level * s->y_dc_scale;
-    } else {
-        *dc_val = level * s->c_dc_scale;
+        /* update predictor */
+        if (n < 4) {
+            *dc_val = level * s->y_dc_scale;
+        } else {
+            *dc_val = level * s->c_dc_scale;
+        }
     }
 
     return level;
@@ -1322,10 +1980,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 {
@@ -1349,3 +2010,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"