changeset 745:25d7fb7c89be libavcodec

better/cleaner error resilience (done in a 2nd pass after decoding) h263/mpeg4 out of order slice decoding
author michaelni
date Sun, 13 Oct 2002 13:16:04 +0000
parents 2f7da29ede37
children fccad7166d5a
files Makefile avcodec.h error_resilience.c h263.c h263dec.c mpeg4data.h mpegvideo.c mpegvideo.h msmpeg4.c rv10.c utils.c
diffstat 11 files changed, 1709 insertions(+), 685 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Oct 11 23:01:16 2002 +0000
+++ b/Makefile	Sun Oct 13 13:16:04 2002 +0000
@@ -15,7 +15,7 @@
       mpegaudio.o ac3enc.o mjpeg.o resample.o dsputil.o \
       motion_est.o imgconvert.o imgresample.o msmpeg4.o \
       mpeg12.o h263dec.o svq1.o rv10.o mpegaudiodec.o pcm.o simple_idct.o \
-      ratecontrol.o adpcm.o eval.o dv.o
+      ratecontrol.o adpcm.o eval.o dv.o error_resilience.o
 ASM_OBJS=
 
 # currently using liba52 for ac3 decoding
--- a/avcodec.h	Fri Oct 11 23:01:16 2002 +0000
+++ b/avcodec.h	Sun Oct 13 13:16:04 2002 +0000
@@ -5,8 +5,8 @@
 
 #define LIBAVCODEC_VERSION_INT 0x000406
 #define LIBAVCODEC_VERSION     "0.4.6"
-#define LIBAVCODEC_BUILD       4630
-#define LIBAVCODEC_BUILD_STR   "4630"
+#define LIBAVCODEC_BUILD       4631
+#define LIBAVCODEC_BUILD_STR   "4631"
 
 enum CodecID {
     CODEC_ID_NONE, 
@@ -414,12 +414,19 @@
     unsigned int codec_tag;  /* codec tag, only used if unknown codec */
     
     /**
-     * workaround bugs in encoders which cannot be detected automatically
+     * workaround bugs in encoders which sometimes cannot be detected automatically
      * encoding: unused
      * decoding: set by user
      */
     int workaround_bugs;
-    
+#define FF_BUG_AUTODETECT       1  //autodetection
+#define FF_BUG_OLD_MSMPEG4      2
+#define FF_BUG_XVID_ILACE       4
+#define FF_BUG_UMP4             8
+#define FF_BUG_NO_PADDING       16
+#define FF_BUG_AC_VLC           32
+//#define FF_BUG_FAKE_SCALABILITY 16 //autodetection should work 100%
+        
     /**
      * encoding: set by user
      * decoding: unused
@@ -715,6 +722,15 @@
      */
     int *slice_offset;
 
+    /**
+     * error concealment flags
+     * encoding: unused
+     * decoding: set by user
+     */
+    int error_concealment;
+#define FF_EC_GUESS_MVS   1
+#define FF_EC_DEBLOCK     2
+
     //FIXME this should be reordered after kabis API is finished ...
     //TODO kill kabi
     /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/error_resilience.c	Sun Oct 13 13:16:04 2002 +0000
@@ -0,0 +1,885 @@
+/*
+ * Error resilience / concealment
+ *
+ * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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
+ */
+
+#include "avcodec.h"
+#include "dsputil.h"
+#include "mpegvideo.h"
+
+/**
+ * replaces the current MB with a flat dc only version.
+ */
+static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
+{
+    int dc, dcu, dcv, y, i;
+    for(i=0; i<4; i++){
+        dc= s->dc_val[0][mb_x*2+1 + (i&1) + (mb_y*2+1 + (i>>1))*(s->mb_width*2+2)];
+        if(dc<0) dc=0;
+        else if(dc>2040) dc=2040;
+        for(y=0; y<8; y++){
+            int x;
+            for(x=0; x<8; x++){
+                dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
+            }
+        }
+    }
+    dcu = s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
+    dcv = s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
+    if     (dcu<0   ) dcu=0;
+    else if(dcu>2040) dcu=2040;
+    if     (dcv<0   ) dcv=0;
+    else if(dcv>2040) dcv=2040;
+    for(y=0; y<8; y++){
+        int x;
+        for(x=0; x<8; x++){
+            dest_cb[x + y*(s->uvlinesize)]= dcu/8;
+            dest_cr[x + y*(s->uvlinesize)]= dcv/8;
+        }
+    }
+}
+
+static void filter181(INT16 *data, int width, int height, int stride){
+    int x,y;
+
+    /* horizontal filter */
+    for(y=1; y<height-1; y++){
+        int prev_dc= data[0 + y*stride];
+
+        for(x=1; x<width-1; x++){
+            int dc;
+            
+            dc= - prev_dc 
+                + data[x     + y*stride]*8
+                - data[x + 1 + y*stride];
+            dc= (dc*10923 + 32768)>>16;
+            prev_dc= data[x + y*stride];
+            data[x + y*stride]= dc;
+        }
+    }
+    
+    /* vertical filter */
+    for(x=1; x<width-1; x++){
+        int prev_dc= data[x];
+
+        for(y=1; y<height-1; y++){
+            int dc;
+            
+            dc= - prev_dc 
+                + data[x +  y   *stride]*8
+                - data[x + (y+1)*stride];
+            dc= (dc*10923 + 32768)>>16;
+            prev_dc= data[x + y*stride];
+            data[x + y*stride]= dc;
+        }
+    }
+}
+
+/**
+ * guess the dc of blocks which dont have a undamaged dc
+ * @param w	width in 8 pixel blocks
+ * @param h	height in 8 pixel blocks
+ */
+static void guess_dc(MpegEncContext *s, INT16 *dc, int w, int h, int stride, int is_luma){
+    int b_x, b_y;
+
+    for(b_y=0; b_y<h; b_y++){
+        for(b_x=0; b_x<w; b_x++){
+            int color[4]={1024,1024,1024,1024};
+            int distance[4]={9999,9999,9999,9999};
+            int mb_index, error, j;
+            INT64 guess, weight_sum;
+            
+            mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_width;
+            
+            error= s->error_status_table[mb_index];
+            
+            if(!(s->mb_type[mb_index]&MB_TYPE_INTRA)) continue; //inter
+            if(!(error&DC_ERROR)) continue;           //dc-ok
+            
+            /* right block */
+            for(j=b_x+1; j<w; j++){
+                int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_width;
+                int error_j= s->error_status_table[mb_index_j];
+                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
+                if(intra_j==0 || !(error_j&DC_ERROR)){
+                    color[0]= dc[j + b_y*stride];
+                    distance[0]= j-b_x;
+                    break;
+                }
+            }
+            
+            /* left block */
+            for(j=b_x-1; j>=0; j--){
+                int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_width;
+                int error_j= s->error_status_table[mb_index_j];
+                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
+                if(intra_j==0 || !(error_j&DC_ERROR)){
+                    color[1]= dc[j + b_y*stride];
+                    distance[1]= b_x-j;
+                    break;
+                }
+            }
+
+            /* bottom block */
+            for(j=b_y+1; j<h; j++){
+                int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_width;
+                int error_j= s->error_status_table[mb_index_j];
+                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
+                if(intra_j==0 || !(error_j&DC_ERROR)){
+                    color[2]= dc[b_x + j*stride];
+                    distance[2]= j-b_y;
+                    break;
+                }
+            }
+
+            /* top block */
+            for(j=b_y-1; j>=0; j--){
+                int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_width;
+                int error_j= s->error_status_table[mb_index_j];
+                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
+                if(intra_j==0 || !(error_j&DC_ERROR)){
+                    color[3]= dc[b_x + j*stride];
+                    distance[3]= b_y-j;
+                    break;
+                }
+            }
+            
+            weight_sum=0;
+            guess=0;
+            for(j=0; j<4; j++){
+                INT64 weight= 256*256*256*16/distance[j];
+                guess+= weight*(INT64)color[j];
+                weight_sum+= weight;
+            }
+            guess= (guess + weight_sum/2) / weight_sum;
+
+            dc[b_x + b_y*stride]= guess;
+        }
+    }
+}
+
+/**
+ * simple horizontal deblocking filter used for error resilience
+ * @param w	width in 8 pixel blocks
+ * @param h	height in 8 pixel blocks
+ */
+static void h_block_filter(MpegEncContext *s, UINT8 *dst, int w, int h, int stride, int is_luma){
+    int b_x, b_y;
+    UINT8 *cm = cropTbl + MAX_NEG_CROP;
+
+    for(b_y=0; b_y<h; b_y++){
+        for(b_x=0; b_x<w-1; b_x++){
+            int y;
+            int left_status = s->error_status_table[( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_width];
+            int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_width];
+            int left_intra=   s->mb_type      [( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
+            int right_intra=  s->mb_type      [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
+            int left_damage =  left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+            int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+            int offset= b_x*8 + b_y*stride*8;
+            INT16 *left_mv=  s->motion_val[s->block_wrap[0]*((b_y<<(1-is_luma)) + 1) + ( b_x   <<(1-is_luma))];
+            INT16 *right_mv= s->motion_val[s->block_wrap[0]*((b_y<<(1-is_luma)) + 1) + ((b_x+1)<<(1-is_luma))];
+            
+            if(!(left_damage||right_damage)) continue; // both undamaged
+            
+            if(   (!left_intra) && (!right_intra) 
+               && ABS(left_mv[0]-right_mv[0]) + ABS(left_mv[1]+right_mv[1]) < 2) continue;
+            
+            for(y=0; y<8; y++){
+                int a,b,c,d;
+                
+                a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
+                b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
+                c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
+                
+                d= ABS(b) - ((ABS(a) + ABS(c) + 1)>>1);
+                d= MAX(d, 0);
+                if(b<0) d= -d;
+                
+                if(d==0) continue;
+
+                if(!(left_damage && right_damage))
+                    d= d*16/9;
+                
+                if(left_damage){
+                    dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
+                    dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
+                    dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
+                    dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
+                }
+                if(right_damage){
+                    dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
+                    dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
+                    dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
+                    dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
+                }
+            }
+        }
+    }
+}
+
+/**
+ * simple vertical deblocking filter used for error resilience
+ * @param w	width in 8 pixel blocks
+ * @param h	height in 8 pixel blocks
+ */
+static void v_block_filter(MpegEncContext *s, UINT8 *dst, int w, int h, int stride, int is_luma){
+    int b_x, b_y;
+    UINT8 *cm = cropTbl + MAX_NEG_CROP;
+
+    for(b_y=0; b_y<h-1; b_y++){
+        for(b_x=0; b_x<w; b_x++){
+            int x;
+            int top_status   = s->error_status_table[(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_width];
+            int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_width];
+            int top_intra=     s->mb_type      [(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_width]&MB_TYPE_INTRA;
+            int bottom_intra=  s->mb_type      [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
+            int top_damage =      top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+            int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
+            int offset= b_x*8 + b_y*stride*8;
+            INT16 *top_mv=    s->motion_val[s->block_wrap[0]*(( b_y   <<(1-is_luma)) + 1) + (b_x<<(1-is_luma))];
+            INT16 *bottom_mv= s->motion_val[s->block_wrap[0]*(((b_y+1)<<(1-is_luma)) + 1) + (b_x<<(1-is_luma))];
+            
+            if(!(top_damage||bottom_damage)) continue; // both undamaged
+            
+            if(   (!top_intra) && (!bottom_intra) 
+               && ABS(top_mv[0]-bottom_mv[0]) + ABS(top_mv[1]+bottom_mv[1]) < 2) continue;
+            
+            for(x=0; x<8; x++){
+                int a,b,c,d;
+                
+                a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
+                b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
+                c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
+                
+                d= ABS(b) - ((ABS(a) + ABS(c)+1)>>1);
+                d= MAX(d, 0);
+                if(b<0) d= -d;
+                
+                if(d==0) continue;
+
+                if(!(top_damage && bottom_damage))
+                    d= d*16/9;
+                
+                if(top_damage){
+                    dst[offset + x +  7*stride] = cm[dst[offset + x +  7*stride] + ((d*7)>>4)];
+                    dst[offset + x +  6*stride] = cm[dst[offset + x +  6*stride] + ((d*5)>>4)];
+                    dst[offset + x +  5*stride] = cm[dst[offset + x +  5*stride] + ((d*3)>>4)];
+                    dst[offset + x +  4*stride] = cm[dst[offset + x +  4*stride] + ((d*1)>>4)];
+                }
+                if(bottom_damage){
+                    dst[offset + x +  8*stride] = cm[dst[offset + x +  8*stride] - ((d*7)>>4)];
+                    dst[offset + x +  9*stride] = cm[dst[offset + x +  9*stride] - ((d*5)>>4)];
+                    dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
+                    dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
+                }
+            }
+        }
+    }
+}
+
+static void guess_mv(MpegEncContext *s){
+    UINT8 fixed[s->mb_num];
+#define MV_FROZEN    3
+#define MV_CHANGED   2
+#define MV_UNCHANGED 1
+    const int mb_width = s->mb_width;
+    const int mb_height= s->mb_height;
+    int i, depth, num_avail;
+   
+    num_avail=0;
+    for(i=0; i<s->mb_num; i++){
+        int f=0;
+        int error= s->error_status_table[i];
+
+        if(s->mb_type[i]&MB_TYPE_INTRA) f=MV_FROZEN; //intra //FIXME check
+        if(!(error&MV_ERROR)) f=MV_FROZEN;           //inter with undamaged MV
+        
+        fixed[i]= f;
+        if(f==MV_FROZEN)
+            num_avail++;
+    }
+    
+    if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
+        int mb_x, mb_y;
+        i= -1;
+        for(mb_y=0; mb_y<s->mb_height; mb_y++){
+            for(mb_x=0; mb_x<s->mb_width; mb_x++){
+                i++;
+                
+                if(s->mb_type[i]&MB_TYPE_INTRA) continue;
+                if(!(s->error_status_table[i]&MV_ERROR)) continue;
+
+                s->mv_dir = MV_DIR_FORWARD;
+                s->mb_intra=0;
+                s->mv_type = MV_TYPE_16X16;
+                s->mb_skiped=0;
+
+                clear_blocks(s->block[0]);
+
+                s->mb_x= mb_x;
+                s->mb_y= mb_y;
+                s->mv[0][0][0]= 0;
+                s->mv[0][0][1]= 0;
+                MPV_decode_mb(s, s->block);
+            }
+        }
+        return;
+    }
+    
+    for(depth=0;; depth++){
+        int changed, pass, none_left;
+
+        none_left=1;
+        changed=1;
+        for(pass=0; (changed || pass<2) && pass<10; pass++){
+            int i,mb_x, mb_y;
+int score_sum=0;
+ 
+            changed=0;
+            i= -1;
+            for(mb_y=0; mb_y<s->mb_height; mb_y++){
+                for(mb_x=0; mb_x<s->mb_width; mb_x++){
+                    int mv_predictor[8][2]={{0}};
+                    int pred_count=0;
+                    int j;
+                    int best_score=256*256*256*64;
+                    int best_pred=0;
+                    const int mot_stride= mb_width*2+2;
+                    const int mot_index= mb_x*2 + 1 + (mb_y*2+1)*mot_stride;
+                    int prev_x= s->motion_val[mot_index][0];
+                    int prev_y= s->motion_val[mot_index][1];
+
+                    i++;
+                    if((mb_x^mb_y^pass)&1) continue;
+                    
+                    if(fixed[i]==MV_FROZEN) continue;
+                    
+                    j=0;
+                    if(mb_x>0           && fixed[i-1       ]==MV_FROZEN) j=1;
+                    if(mb_x+1<mb_width  && fixed[i+1       ]==MV_FROZEN) j=1;
+                    if(mb_y>0           && fixed[i-mb_width]==MV_FROZEN) j=1;
+                    if(mb_y+1<mb_height && fixed[i+mb_width]==MV_FROZEN) j=1;
+                    if(j==0) continue;
+
+                    j=0;
+                    if(mb_x>0           && fixed[i-1       ]==MV_CHANGED) j=1;
+                    if(mb_x+1<mb_width  && fixed[i+1       ]==MV_CHANGED) j=1;
+                    if(mb_y>0           && fixed[i-mb_width]==MV_CHANGED) j=1;
+                    if(mb_y+1<mb_height && fixed[i+mb_width]==MV_CHANGED) j=1;
+                    if(j==0 && pass>1) continue;
+                    
+                    none_left=0;
+                    
+                    if(mb_x>0 && fixed[i-1]){
+                        mv_predictor[pred_count][0]= s->motion_val[mot_index - 2][0];
+                        mv_predictor[pred_count][1]= s->motion_val[mot_index - 2][1];
+                        pred_count++;
+                    }
+                    if(mb_x+1<mb_width && fixed[i+1]){
+                        mv_predictor[pred_count][0]= s->motion_val[mot_index + 2][0];
+                        mv_predictor[pred_count][1]= s->motion_val[mot_index + 2][1];
+                        pred_count++;
+                    }
+                    if(mb_y>0 && fixed[i-mb_width]){
+                        mv_predictor[pred_count][0]= s->motion_val[mot_index - mot_stride*2][0];
+                        mv_predictor[pred_count][1]= s->motion_val[mot_index - mot_stride*2][1];
+                        pred_count++;
+                    }
+                    if(mb_y+1<mb_height && fixed[i+mb_width]){
+                        mv_predictor[pred_count][0]= s->motion_val[mot_index + mot_stride*2][0];
+                        mv_predictor[pred_count][1]= s->motion_val[mot_index + mot_stride*2][1];
+                        pred_count++;
+                    }
+                    if(pred_count==0) continue;
+                    
+                    if(pred_count>1){
+                        int sum_x=0, sum_y=0;
+                        int max_x, max_y, min_x, min_y;
+
+                        for(j=0; j<pred_count; j++){
+                            sum_x+= mv_predictor[j][0];
+                            sum_y+= mv_predictor[j][1];
+                        }
+                    
+                        /* mean */
+                        mv_predictor[pred_count][0] = sum_x/j;
+                        mv_predictor[pred_count][1] = sum_y/j;
+                    
+                        /* median */
+                        if(pred_count>=3){
+                            min_y= min_x= 99999;
+                            max_y= max_x=-99999;
+                        }else{
+                            min_x=min_y=max_x=max_y=0;
+                        }
+                        for(j=0; j<pred_count; j++){
+                            max_x= MAX(max_x, mv_predictor[j][0]);
+                            max_y= MAX(max_y, mv_predictor[j][1]);
+                            min_x= MIN(min_x, mv_predictor[j][0]);
+                            min_y= MIN(min_y, mv_predictor[j][1]);
+                        }
+                        mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
+                        mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
+                        
+                        if(pred_count==4){
+                            mv_predictor[pred_count+1][0] /= 2;
+                            mv_predictor[pred_count+1][1] /= 2;
+                        }
+                        pred_count+=2;
+                    }
+                    
+                    /* zero MV */
+                    pred_count++;
+
+                    /* last MV */
+                    mv_predictor[pred_count][0]= s->motion_val[mot_index][0];
+                    mv_predictor[pred_count][1]= s->motion_val[mot_index][1];
+                    pred_count++;                    
+                    
+                    s->mv_dir = MV_DIR_FORWARD;
+                    s->mb_intra=0;
+                    s->mv_type = MV_TYPE_16X16;
+                    s->mb_skiped=0;
+
+                    clear_blocks(s->block[0]);
+
+                    s->mb_x= mb_x;
+                    s->mb_y= mb_y;
+                    for(j=0; j<pred_count; j++){
+                        int score=0;
+                        UINT8 *src= s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
+
+                        s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
+                        s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
+                        MPV_decode_mb(s, s->block);
+                        
+                        if(mb_x>0 && fixed[i-1]){
+                            int k;
+                            for(k=0; k<16; k++)
+                                score += ABS(src[k*s->linesize-1 ]-src[k*s->linesize   ]);
+                        }
+                        if(mb_x+1<mb_width && fixed[i+1]){
+                            int k;
+                            for(k=0; k<16; k++)
+                                score += ABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
+                        }
+                        if(mb_y>0 && fixed[i-mb_width]){
+                            int k;
+                            for(k=0; k<16; k++)
+                                score += ABS(src[k-s->linesize   ]-src[k               ]);
+                        }
+                        if(mb_y+1<mb_height && fixed[i+mb_width]){
+                            int k;
+                            for(k=0; k<16; k++)
+                                score += ABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
+                        }
+                        
+                        if(score <= best_score){ // <= will favor the last MV
+                            best_score= score;
+                            best_pred= j;
+                        }
+                    }
+score_sum+= best_score;
+//FIXME no need to set s->motion_val[mot_index][0] explicit
+                    s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[best_pred][0];
+                    s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[best_pred][1];
+
+                    MPV_decode_mb(s, s->block);
+
+                    
+                    if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
+                        fixed[i]=MV_CHANGED;
+                        changed++;
+                    }else
+                        fixed[i]=MV_UNCHANGED;
+                }
+            }
+
+//            printf(".%d/%d", changed, score_sum); fflush(stdout);
+        }
+        
+        if(none_left) 
+            return;
+            
+        for(i=0; i<s->mb_num; i++){
+            if(fixed[i])
+                fixed[i]=MV_FROZEN;
+        }
+//        printf(":"); fflush(stdout);
+    }
+}
+    
+static int is_intra_more_likely(MpegEncContext *s){
+    int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
+
+    undamaged_count=0;
+    for(i=0; i<s->mb_num; i++){
+        int error= s->error_status_table[i];
+        if(!((error&DC_ERROR) && (error&MV_ERROR)))
+            undamaged_count++;
+    }
+    
+    if(undamaged_count < 5) return 0; //allmost all MBs damaged -> use temporal prediction
+    
+    skip_amount= MAX(undamaged_count/50, 1); //check only upto 50 MBs 
+    is_intra_likely=0;
+
+    j=0;
+    i=-1;
+    for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
+        for(mb_x= 0; mb_x<s->mb_width; mb_x++){
+            int error;
+
+            i++;
+            error= s->error_status_table[i];
+            if((error&DC_ERROR) && (error&MV_ERROR))
+                continue; //skip damaged
+        
+            j++;    
+            if((j%skip_amount) != 0) continue; //skip a few to speed things up
+    
+            if(s->pict_type==I_TYPE){
+                UINT8 *mb_ptr     = s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
+                UINT8 *last_mb_ptr= s->last_picture   [0] + mb_x*16 + mb_y*16*s->linesize;
+    
+                is_intra_likely += pix_abs16x16(last_mb_ptr, mb_ptr                    , s->linesize);
+                is_intra_likely -= pix_abs16x16(last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize);
+            }else{
+                if(s->mbintra_table[i]) //HACK (this is allways inited but we should use mb_type[])
+                   is_intra_likely++;
+                else
+                   is_intra_likely--;
+            }
+        }
+    }
+//printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
+    return is_intra_likely > 0;    
+}
+
+void ff_error_resilience(MpegEncContext *s){
+    int i, mb_x, mb_y, error, error_type;
+    int distance;
+    int threshold_part[4]= {100,100,100};
+    int threshold= 50;
+    int is_intra_likely;
+    
+#if 1
+    /* handle overlapping slices */
+    for(error_type=1; error_type<=3; error_type++){
+        int end_ok=0;
+
+        for(i=s->mb_num-1; i>=0; i--){
+            int error= s->error_status_table[i];
+        
+            if(error&(1<<error_type))
+                end_ok=1;
+            if(error&(8<<error_type))
+                end_ok=1;
+
+            if(!end_ok)
+                s->error_status_table[i]|= 1<<error_type;
+
+            if(error&VP_START)
+                end_ok=0;
+        }
+    }
+#endif
+#if 1
+    /* handle slices with partitions of different length */
+    if(s->partitioned_frame){
+        int end_ok=0;
+
+        for(i=s->mb_num-1; i>=0; i--){
+            int error= s->error_status_table[i];
+        
+            if(error&AC_END)
+                end_ok=0;
+            if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
+                end_ok=1;
+
+            if(!end_ok)
+                s->error_status_table[i]|= AC_ERROR;
+
+            if(error&VP_START)
+                end_ok=0;
+        }
+    }
+#endif
+    /* handle missing slices */
+    if(s->error_resilience>=4){
+        int end_ok=1;
+                
+        for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
+            int error1= s->error_status_table[i  ];
+            int error2= s->error_status_table[i+1];
+        
+            if(error1&VP_START)
+                end_ok=1;
+             
+            if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
+               && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END) 
+               && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninited
+                end_ok=0;
+            }
+        
+            if(!end_ok)
+                s->error_status_table[i]|= DC_ERROR|AC_ERROR|MV_ERROR;
+        }
+    }
+    
+#if 1
+    /* backward mark errors */
+    distance=9999999;
+    for(error_type=1; error_type<=3; error_type++){
+        for(i=s->mb_num-1; i>=0; i--){
+            int error= s->error_status_table[i];
+            
+            if(!s->mbskip_table[i]) //FIXME partition specific
+                distance++;            
+            if(error&(1<<error_type))
+                distance= 0;
+
+            if(s->partitioned_frame){
+                if(distance < threshold_part[error_type-1])
+                    s->error_status_table[i]|= 1<<error_type;
+            }else{
+                if(distance < threshold)
+                    s->error_status_table[i]|= 1<<error_type;
+            }
+
+            if(error&VP_START)
+                distance= 9999999;
+        }
+    }
+#endif
+
+    /* forward mark errors */
+    error=0;
+    for(i=0; i<s->mb_num; i++){
+        int old_error= s->error_status_table[i];
+        
+        if(old_error&VP_START)
+            error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
+        else{
+            error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
+            s->error_status_table[i]|= error;
+        }
+    }
+#if 1
+    /* handle not partitioned case */
+    if(!s->partitioned_frame){
+        for(i=0; i<s->mb_num; i++){
+            error= s->error_status_table[i];
+            if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
+                error|= AC_ERROR|DC_ERROR|MV_ERROR;
+            s->error_status_table[i]= error;
+        }
+    }
+#endif
+    is_intra_likely= is_intra_more_likely(s);
+
+    /* set unknown mb-type to most likely */
+    for(i=0; i<s->mb_num; i++){
+        int intra;
+        error= s->error_status_table[i];
+        if((error&DC_ERROR) && (error&MV_ERROR))
+            intra= is_intra_likely;
+        else
+            intra= s->mbintra_table[i];
+
+        if(intra)
+            s->mb_type[i]|= MB_TYPE_INTRA;
+        else
+            s->mb_type[i]&= ~MB_TYPE_INTRA;
+    }
+    
+    /* handle inter blocks with damaged AC */
+    i= -1;
+    for(mb_y=0; mb_y<s->mb_height; mb_y++){
+        for(mb_x=0; mb_x<s->mb_width; mb_x++){
+            i++;
+            error= s->error_status_table[i];
+
+            if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
+            if(error&MV_ERROR) continue;              //inter with damaged MV
+            if(!(error&AC_ERROR)) continue;           //undamaged inter
+            
+            s->mv_dir = MV_DIR_FORWARD;
+            s->mb_intra=0;
+            s->mb_skiped=0;
+            if(s->mb_type[i]&MB_TYPE_INTER4V){
+                int mb_index= mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0];
+                int j;
+                s->mv_type = MV_TYPE_8X8;
+                for(j=0; j<4; j++){
+                    s->mv[0][j][0] = s->motion_val[ mb_index + (j&1) + (j>>1)*s->block_wrap[0] ][0];
+                    s->mv[0][j][1] = s->motion_val[ mb_index + (j&1) + (j>>1)*s->block_wrap[0] ][1];
+                }
+            }else{
+                s->mv_type = MV_TYPE_16X16;
+                s->mv[0][0][0] = s->motion_val[ mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0] ][0];
+                s->mv[0][0][1] = s->motion_val[ mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0] ][1];
+            }
+        
+            clear_blocks(s->block[0]);
+
+            s->mb_x= mb_x;
+            s->mb_y= mb_y;
+            MPV_decode_mb(s, s->block);
+        }
+    }
+
+    /* guess MVs */
+    if(s->pict_type==B_TYPE){
+        i= -1;
+        for(mb_y=0; mb_y<s->mb_height; mb_y++){
+            for(mb_x=0; mb_x<s->mb_width; mb_x++){
+                int xy= mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0];
+                i++;
+                error= s->error_status_table[i];
+
+                if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
+                if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
+                if(!(error&AC_ERROR)) continue;           //undamaged inter
+            
+                s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
+                s->mb_intra=0;
+                s->mv_type = MV_TYPE_16X16;
+                s->mb_skiped=0;
+                
+                if(s->pp_time){
+                    int time_pp= s->pp_time;
+                    int time_pb= s->pb_time;
+            
+                    s->mv[0][0][0] = s->motion_val[xy][0]*time_pb/time_pp;
+                    s->mv[0][0][1] = s->motion_val[xy][1]*time_pb/time_pp;
+                    s->mv[1][0][0] = s->motion_val[xy][0]*(time_pb - time_pp)/time_pp;
+                    s->mv[1][0][1] = s->motion_val[xy][1]*(time_pb - time_pp)/time_pp;
+                }else{
+                    s->mv[0][0][0]= 0;
+                    s->mv[0][0][1]= 0;
+                    s->mv[1][0][0]= 0;
+                    s->mv[1][0][1]= 0;
+                }
+                                
+                clear_blocks(s->block[0]);
+                s->mb_x= mb_x;
+                s->mb_y= mb_y;
+                MPV_decode_mb(s, s->block);
+            }
+        }
+    }else
+        guess_mv(s);
+
+    /* fill DC for inter blocks */
+    i= -1;
+    for(mb_y=0; mb_y<s->mb_height; mb_y++){
+        for(mb_x=0; mb_x<s->mb_width; mb_x++){
+            int dc, dcu, dcv, y, n;
+            INT16 *dc_ptr;
+            UINT8 *dest_y, *dest_cb, *dest_cr;
+           
+            i++;
+            error= s->error_status_table[i];
+
+            if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
+//            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
+            
+            dest_y = s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
+            dest_cb= s->current_picture[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
+            dest_cr= s->current_picture[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
+           
+            dc_ptr= &s->dc_val[0][mb_x*2+1 + (mb_y*2+1)*(s->mb_width*2+2)];
+            for(n=0; n<4; n++){
+                dc=0;
+                for(y=0; y<8; y++){
+                    int x;
+                    for(x=0; x<8; x++){
+                       dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
+                    }
+                }
+                dc_ptr[(n&1) + (n>>1)*(s->mb_width*2+2)]= (dc+4)>>3;
+            }
+
+            dcu=dcv=0;
+            for(y=0; y<8; y++){
+                int x;
+                for(x=0; x<8; x++){
+                    dcu+=dest_cb[x + y*(s->uvlinesize)];
+                    dcv+=dest_cr[x + y*(s->uvlinesize)];
+                }
+            }
+            s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)]= (dcu+4)>>3;
+            s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)]= (dcv+4)>>3;   
+        }
+    }
+#if 1
+    /* guess DC for damaged blocks */
+    guess_dc(s, s->dc_val[0] + s->mb_width*2+3, s->mb_width*2, s->mb_height*2, s->mb_width*2+2, 1);
+    guess_dc(s, s->dc_val[1] + s->mb_width  +3, s->mb_width  , s->mb_height  , s->mb_width  +2, 0);
+    guess_dc(s, s->dc_val[2] + s->mb_width  +3, s->mb_width  , s->mb_height  , s->mb_width  +2, 0);
+#endif   
+    /* filter luma DC */
+    filter181(s->dc_val[0] + s->mb_width*2+3, s->mb_width*2, s->mb_height*2, s->mb_width*2+2);
+    
+#if 1
+    /* render DC only intra */
+    i= -1;
+    for(mb_y=0; mb_y<s->mb_height; mb_y++){
+        for(mb_x=0; mb_x<s->mb_width; mb_x++){
+            UINT8 *dest_y, *dest_cb, *dest_cr;
+           
+            i++;
+            error= s->error_status_table[i];
+
+            if(!(s->mb_type[i]&MB_TYPE_INTRA)) continue; //inter
+            if(!(error&AC_ERROR)) continue;              //undamaged
+            
+            dest_y = s->current_picture[0] + mb_x*16 + mb_y*16*s->linesize;
+            dest_cb= s->current_picture[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
+            dest_cr= s->current_picture[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
+            
+            put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
+        }
+    }
+#endif
+    
+    if(s->avctx->error_concealment&FF_EC_DEBLOCK){
+        /* filter horizontal block boundaries */
+        h_block_filter(s, s->current_picture[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
+        h_block_filter(s, s->current_picture[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
+        h_block_filter(s, s->current_picture[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
+
+        /* filter vertical block boundaries */
+        v_block_filter(s, s->current_picture[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
+        v_block_filter(s, s->current_picture[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
+        v_block_filter(s, s->current_picture[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
+    }
+
+    /* clean a few tables */
+    for(i=0; i<s->mb_num; i++){
+        int error= s->error_status_table[i];
+        
+        if(s->pict_type!=B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
+            s->mbskip_table[i]=0;
+        }
+        s->mbintra_table[i]=1;
+    }    
+}
--- a/h263.c	Fri Oct 11 23:01:16 2002 +0000
+++ b/h263.c	Sun Oct 13 13:16:04 2002 +0000
@@ -70,6 +70,8 @@
 static void mpeg4_inv_pred_ac(MpegEncContext * s, INT16 *block, int n,
                               int dir);
 static void mpeg4_decode_sprite_trajectory(MpegEncContext * s);
+static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr);
+
 
 extern UINT32 inverse[256];
 
@@ -332,6 +334,9 @@
     return score0 > score1 ? 1 : 0;    
 }
 
+/**
+ * modify qscale so that encoding is acually possible in h263 (limit difference to -2..2)
+ */
 void ff_clean_h263_qscales(MpegEncContext *s){
     int i;
     
@@ -345,6 +350,9 @@
     }
 }
 
+/**
+ * modify mb_type & qscale so that encoding is acually possible in mpeg4
+ */
 void ff_clean_mpeg4_qscales(MpegEncContext *s){
     int i;
     
@@ -1031,7 +1039,7 @@
 
     A = s->motion_val[xy - 1];
     /* special case for first (slice) line */
-    if ((s->mb_y == 0 || s->first_slice_line) && block<3) {
+    if (s->first_slice_line && block<3) {
         // we cant just change some MVs to simulate that as we need them for the B frames (and ME)
         // and if we ever support non rectangular objects than we need to do a few ifs here anyway :(
         if(block==0){ //most common case
@@ -1452,7 +1460,9 @@
 }
 
 /***************************************************/
-
+/**
+ * add mpeg4 stuffing bits (01...1)
+ */
 void ff_mpeg4_stuffing(PutBitContext * pbc)
 {
     int length;
@@ -1545,7 +1555,9 @@
     }else{ /* vo_ver_id == 2 */
         put_bits(&s->pb, 2, s->vol_sprite_usage=0);		/* sprite enable */
     }
-    put_bits(&s->pb, 1, 0);		/* not 8 bit */
+    
+    s->quant_precision=5;
+    put_bits(&s->pb, 1, 0);		/* not 8 bit == false */
     put_bits(&s->pb, 1, s->mpeg_quant);	/* quant type= (0=h263 style)*/
     if(s->mpeg_quant) put_bits(&s->pb, 2, 0); /* no custom matrixes */
 
@@ -1589,6 +1601,8 @@
             mpeg4_encode_vol_header(s);
     }
     
+    s->partitioned_frame= s->data_partitioning && s->pict_type!=B_TYPE;
+
 //printf("num:%d rate:%d base:%d\n", s->picture_number, s->frame_rate, FRAME_RATE_BASE);
     
     put_bits(&s->pb, 16, 0);	        /* vop header */
@@ -1633,6 +1647,9 @@
      s->v_edge_pos= s->height;
 }
 
+/**
+ * change qscale by given dquant and update qscale dependant variables.
+ */
 static void change_qscale(MpegEncContext * s, int dquant)
 {
     s->qscale += dquant;
@@ -1646,7 +1663,7 @@
     s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
 }
 
-inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr)
+static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr)
 {
     int a, b, c, wrap, pred, scale;
     UINT16 *dc_val;
@@ -1668,6 +1685,16 @@
     b = dc_val[ - 1 - wrap];
     c = dc_val[ - wrap];
 
+    /* outside slice handling (we cant do that by memset as we need the dc for error resilience) */
+    if(s->first_slice_line && n!=3){
+        if(n!=2) b=c= 1024;
+        if(n!=1 && s->mb_x == s->resync_mb_x) b=a= 1024;
+    }
+    if(s->mb_x == s->resync_mb_x && s->mb_y == s->resync_mb_y+1){
+        if(n==0 || n==4 || n==5)
+            b=1024;
+    }
+
     if (abs(a - b) < abs(b - c)) {
 	pred = c;
         *dir_ptr = 1; /* top */
@@ -2083,33 +2110,58 @@
                  &mb_type_b_tab[0][1], 2, 1,
                  &mb_type_b_tab[0][0], 2, 1);
     }
-
-    s->progressive_sequence=1; // set to most likely for the case of incomplete headers
 }
 
-int h263_decode_gob_header(MpegEncContext *s)
+/**
+ * Get the GOB height based on picture height.
+ */
+int ff_h263_get_gob_height(MpegEncContext *s){
+    if (s->height <= 400)
+        return 1;
+    else if (s->height <= 800)
+        return  2;
+    else
+        return 4;
+}
+
+/**
+ * decodes the group of blocks header.
+ * @return <0 if an error occured
+ */
+static int h263_decode_gob_header(MpegEncContext *s)
 {
     unsigned int val, gfid;
+    int left;
     
     /* Check for GOB Start Code */
     val = show_bits(&s->gb, 16);
-    if (val == 0) {
+    if(val)
+        return -1;
+
         /* We have a GBSC probably with GSTUFF */
-        skip_bits(&s->gb, 16); /* Drop the zeros */
-        while (get_bits1(&s->gb) == 0); /* Seek the '1' bit */
+    skip_bits(&s->gb, 16); /* Drop the zeros */
+    left= s->gb.size*8 - get_bits_count(&s->gb);
+    //MN: we must check the bits left or we might end in a infinite loop (or segfault)
+    for(;left>13; left--){
+        if(get_bits1(&s->gb)) break; /* Seek the '1' bit */
+    }
+    if(left<=13) 
+        return -1;
+
 #ifdef DEBUG
-        fprintf(stderr,"\nGOB Start Code at MB %d\n", (s->mb_y * s->mb_width) + s->mb_x);
+    fprintf(stderr,"\nGOB Start Code at MB %d\n", (s->mb_y * s->mb_width) + s->mb_x);
 #endif
-        s->gob_number = get_bits(&s->gb, 5); /* GN */
-        gfid = get_bits(&s->gb, 2); /* GFID */
-        s->qscale = get_bits(&s->gb, 5); /* GQUANT */
+    s->gob_number = get_bits(&s->gb, 5); /* GN */
+    gfid = get_bits(&s->gb, 2); /* GFID */
+    s->qscale = get_bits(&s->gb, 5); /* GQUANT */
+    if(s->qscale==0) 
+        return -1;
+    s->mb_x= 0;
+    s->mb_y= s->gob_index* s->gob_number;
 #ifdef DEBUG
-        fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", s->gob_number, gfid, s->qscale);
+    fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", s->gob_number, gfid, s->qscale);
 #endif
-        return 1;
-    }
     return 0;
-            
 }
 
 static inline void memsetw(short *tab, int val, int n)
@@ -2137,7 +2189,7 @@
         s->i_tex_bits+= tex_pb_len;
     }else{
         put_bits(&s->pb, 17, MOTION_MARKER);
-        s->misc_bits+=17 + pb2_len;;
+        s->misc_bits+=17 + pb2_len;
         s->mv_bits+= bits - s->last_bits;
         s->p_tex_bits+= tex_pb_len;
     }
@@ -2150,104 +2202,131 @@
     s->last_bits= get_bit_count(&s->pb);
 }
 
+int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s){
+    switch(s->pict_type){
+        case I_TYPE:
+            return 16;
+        case P_TYPE:
+        case S_TYPE:
+            return s->f_code+15;
+        case B_TYPE:
+            return MAX(MAX(s->f_code, s->b_code)+15, 17);
+        default:
+            return -1;
+    }
+}
+
 void ff_mpeg4_encode_video_packet_header(MpegEncContext *s)
 {
     int mb_num_bits= av_log2(s->mb_num - 1) + 1;
 
     ff_mpeg4_stuffing(&s->pb);
-    if(s->pict_type==I_TYPE)
-        put_bits(&s->pb, 16, 0);
-    else if(s->pict_type==B_TYPE)
-        put_bits(&s->pb, MAX(MAX(s->f_code, s->b_code)+15, 17), 0);
-    else /* S/P_TYPE */
-        put_bits(&s->pb, s->f_code+15, 0);
+    put_bits(&s->pb, ff_mpeg4_get_video_packet_prefix_length(s), 0);
     put_bits(&s->pb, 1, 1);
     
     put_bits(&s->pb, mb_num_bits, s->mb_x + s->mb_y*s->mb_width);
-    put_bits(&s->pb, 5, s->qscale);
+    put_bits(&s->pb, s->quant_precision, s->qscale);
     put_bits(&s->pb, 1, 0); /* no HEC */
 }
 
 /**
- * decodes the next video packet and sets s->next_qscale 
- * returns mb_num of the next packet or <0 if something went wrong
+ * check if the next stuff is a resync marker or the end.
+ * @return 0 if not
  */
-static int decode_video_packet_header(MpegEncContext *s, GetBitContext *gb)
+static inline int mpeg4_is_resync(MpegEncContext *s){
+    const int bits_count= get_bits_count(&s->gb);
+    
+    if(s->workaround_bugs&FF_BUG_NO_PADDING){
+        return 0;
+    }
+
+    if(bits_count + 8 >= s->gb.size*8){
+        int v= show_bits(&s->gb, 8);
+        v|= 0x7F >> (7-(bits_count&7));
+                
+        if(v==0x7F)
+            return 1;
+    }else{
+        if(show_bits(&s->gb, 16) == ff_mpeg4_resync_prefix[bits_count&7]){
+            int len;
+            GetBitContext gb= s->gb;
+        
+            skip_bits(&s->gb, 1);
+            align_get_bits(&s->gb);
+        
+            for(len=0; len<32; len++){
+                if(get_bits1(&s->gb)) break;
+            }
+
+            s->gb= gb;
+
+            if(len>=ff_mpeg4_get_video_packet_prefix_length(s))
+                return 1;
+        }
+    }
+    return 0;
+}
+
+/**
+ * decodes the next video packet.
+ * @return <0 if something went wrong
+ */
+static int mpeg4_decode_video_packet_header(MpegEncContext *s)
 {
-    int bits;
     int mb_num_bits= av_log2(s->mb_num - 1) + 1;
-    int header_extension=0, mb_num;
-//printf("%X\n", show_bits(&gb, 24));
-//printf("parse_video_packet_header\n");
-//    if(show_aligned_bits(gb, 1, 16) != 0) return -1;
+    int header_extension=0, mb_num, len;
     
     /* is there enough space left for a video packet + header */
-    if( get_bits_count(gb) > gb->size*8-20) return -1;
-
-//printf("resync at %d %d\n", s->mb_x, s->mb_y);
-//    skip_bits(gb, 1);
-//    align_get_bits(gb);
-    if(get_bits(gb, 16)!=0){
-        printf("internal error while decoding video packet header\n");
+    if( get_bits_count(&s->gb) > s->gb.size*8-20) return -1;
+
+    for(len=0; len<32; len++){
+        if(get_bits1(&s->gb)) break;
     }
 
-//printf("%X\n", show_bits(gb, 24));
-    bits=0;
-    while(!get_bits1(gb) && bits<30) bits++;
-    if((s->pict_type == P_TYPE || s->pict_type == S_TYPE) && bits != s->f_code-1){
-        printf("marker does not match f_code (is: %d should be: %d pos: %d end %d x: %d y: %d)\n", 
-               bits+1, s->f_code, get_bits_count(gb), gb->size*8, s->mb_x, s->mb_y);
-        return -1;
-    }else if(s->pict_type == I_TYPE && bits != 0){
-        printf("marker too long\n");
-        return -1;
-    }else if(s->pict_type == B_TYPE && bits != MAX(MAX(s->f_code, s->b_code)-1, 1)){
-        printf("marker does not match f/b_code\n");
+    if(len!=ff_mpeg4_get_video_packet_prefix_length(s)){
+        printf("marker does not match f_code\n");
         return -1;
     }
-//printf("%X\n", show_bits(gb, 24));
-
+    
     if(s->shape != RECT_SHAPE){
-        header_extension= get_bits1(gb);
+        header_extension= get_bits1(&s->gb);
         //FIXME more stuff here
     }
 
-    mb_num= get_bits(gb, mb_num_bits);
-    if(mb_num < s->mb_x + s->mb_y*s->mb_width || mb_num>=s->mb_num){
-        fprintf(stderr, "illegal mb_num in video packet (%d %d) \n", mb_num, s->mb_x + s->mb_y*s->mb_width);
+    mb_num= get_bits(&s->gb, mb_num_bits);
+    if(mb_num>=s->mb_num){
+        fprintf(stderr, "illegal mb_num in video packet (%d %d) \n", mb_num, s->mb_num);
         return -1;
     }
+    s->mb_x= mb_num % s->mb_width;
+    s->mb_y= mb_num / s->mb_width;
 
     if(s->shape != BIN_ONLY_SHAPE){
-        s->next_resync_qscale= get_bits(gb, 5);
-        if(s->next_resync_qscale==0)
-            s->next_resync_qscale= s->qscale;
-        if(s->next_resync_qscale==0){
-            fprintf(stderr, "qscale==0\n");
-            return -1;
-        }
+        int qscale= get_bits(&s->gb, s->quant_precision); 
+        if(qscale)
+            s->qscale= qscale;
     }
 
     if(s->shape == RECT_SHAPE){
-        header_extension= get_bits1(gb);
+        header_extension= get_bits1(&s->gb);
     }
     if(header_extension){
         int time_increment;
         int time_incr=0;
 
-        while (get_bits1(gb) != 0) 
+        while (get_bits1(&s->gb) != 0) 
             time_incr++;
 
-        check_marker(gb, "before time_increment in video packed header");
-        time_increment= get_bits(gb, s->time_increment_bits);
-        check_marker(gb, "before vop_coding_type in video packed header");
+        check_marker(&s->gb, "before time_increment in video packed header");
+        time_increment= get_bits(&s->gb, s->time_increment_bits);
+        check_marker(&s->gb, "before vop_coding_type in video packed header");
         
-        skip_bits(gb, 2); /* vop coding type */
+        skip_bits(&s->gb, 2); /* vop coding type */
         //FIXME not rect stuff here
 
         if(s->shape != BIN_ONLY_SHAPE){
-            skip_bits(gb, 3); /* intra dc vlc threshold */
-
+            skip_bits(&s->gb, 3); /* intra dc vlc threshold */
+//FIXME dont just ignore everything
             if(s->pict_type == S_TYPE && s->vol_sprite_usage==GMC_SPRITE && s->num_sprite_warping_points){
                 mpeg4_decode_sprite_trajectory(s);
                 fprintf(stderr, "untested\n");
@@ -2256,13 +2335,13 @@
             //FIXME reduced res stuff here
             
             if (s->pict_type != I_TYPE) {
-                int f_code = get_bits(gb, 3);	/* fcode_for */
+                int f_code = get_bits(&s->gb, 3);	/* fcode_for */
                 if(f_code==0){
                     printf("Error, video packet header damaged (f_code=0)\n");
                 }
             }
             if (s->pict_type == B_TYPE) {
-                int b_code = get_bits(gb, 3);
+                int b_code = get_bits(&s->gb, 3);
                 if(b_code==0){
                     printf("Error, video packet header damaged (b_code=0)\n");
                 }
@@ -2273,7 +2352,7 @@
     
 //printf("parse ok %d %d %d %d\n", mb_num, s->mb_x + s->mb_y*s->mb_width, get_bits_count(gb), get_bits_count(&s->gb));
 
-    return mb_num;
+    return 0;
 }
 
 void ff_mpeg4_clean_buffers(MpegEncContext *s)
@@ -2285,10 +2364,12 @@
     c_wrap= s->block_wrap[4];
     c_xy= s->mb_y*c_wrap + s->mb_x;
 
+#if 0
     /* clean DC */
     memsetw(s->dc_val[0] + l_xy, 1024, l_wrap*2+1);
     memsetw(s->dc_val[1] + c_xy, 1024, c_wrap+1);
     memsetw(s->dc_val[2] + c_xy, 1024, c_wrap+1);
+#endif
 
     /* clean AC */
     memset(s->ac_val[0] + l_xy, 0, (l_wrap*2+1)*16*sizeof(INT16));
@@ -2305,84 +2386,70 @@
     s->last_mv[1][0][1]= 0;
 }
 
-/* searches for the next resync marker clears ac,dc,mc, and sets s->next_resync_gb, s->mb_num_left */
-int ff_mpeg4_resync(MpegEncContext *s)
-{
-    GetBitContext gb;
+/**
+ * decodes the group of blocks / video packet header.
+ * @return <0 if no resync found
+ */
+int ff_h263_resync(MpegEncContext *s){
+    int left, ret;
     
-    /* search & parse next resync marker */
+    if(s->codec_id==CODEC_ID_MPEG4)
+        skip_bits1(&s->gb);
     
-    gb= s->next_resync_gb;
-    align_get_bits(&gb);
-//printf("mpeg4_resync %d next:%d \n", get_bits_count(&gb), get_bits_count(&s->next_resync_gb));
-    for(;;) {
-        int v= show_bits(&gb, 24);
-        if( get_bits_count(&gb) >= gb.size*8-24 || v == 1 /* start-code */){
-            s->mb_num_left= s->mb_num - s->mb_x - s->mb_y*s->mb_width;
-//printf("mpeg4_resync end\n");
-            s->gb= s->next_resync_gb; //continue at the next resync marker
-            return -1;
-        }else if(v>>8 == 0){
-            int next;
-            s->next_resync_pos= get_bits_count(&gb);
-            
-            next= decode_video_packet_header(s, &gb);
-            if(next >= 0){
-                s->mb_num_left= next - s->mb_x - s->mb_y*s->mb_width;
-                break;
-            }
-
-            align_get_bits(&gb);
-        }
-        skip_bits(&gb, 8);
+    align_get_bits(&s->gb);
+
+    if(show_bits(&s->gb, 16)==0){
+        if(s->codec_id==CODEC_ID_MPEG4)
+            ret= mpeg4_decode_video_packet_header(s);
+        else
+            ret= h263_decode_gob_header(s);
+        if(ret>=0)
+            return 0;
     }
-    s->next_resync_gb=gb;
+    //ok, its not where its supposed to be ...
+    s->gb= s->last_resync_gb;
+    align_get_bits(&s->gb);
+    left= s->gb.size*8 - get_bits_count(&s->gb);
     
-    return 0;
-}
-
-static inline void init_block_index(MpegEncContext *s)
-{
-    s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1 + s->mb_x*2;
-    s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1)     + s->mb_x*2;
-    s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1 + s->mb_x*2;
-    s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2)     + s->mb_x*2;
-    s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1)                    + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
-    s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
-}
-
-static inline void update_block_index(MpegEncContext *s)
-{
-    s->block_index[0]+=2;
-    s->block_index[1]+=2;
-    s->block_index[2]+=2;
-    s->block_index[3]+=2;
-    s->block_index[4]++;
-    s->block_index[5]++;
+    for(;left>16+1+5+5; left-=8){ 
+        if(show_bits(&s->gb, 16)==0){
+            GetBitContext bak= s->gb;
+
+            if(s->codec_id==CODEC_ID_MPEG4)
+                ret= mpeg4_decode_video_packet_header(s);
+            else
+                ret= h263_decode_gob_header(s);
+            if(ret>=0)
+                return 0;
+
+            s->gb= bak;
+        }
+        skip_bits(&s->gb, 8);
+    }
+    
+    return -1;
 }
 
 /**
- * decodes the first & second partition
- * returns error type or 0 if no error
+ * decodes first partition.
+ * @return number of MBs decoded or <0 if an error occured
  */
-int ff_mpeg4_decode_partitions(MpegEncContext *s)
-{
+static int mpeg4_decode_partition_a(MpegEncContext *s){
+    int mb_num;
     static const INT8 quant_tab[4] = { -1, -2, 1, 2 };
-    int mb_num;
     
     /* decode first partition */
     mb_num=0;
     s->first_slice_line=1;
-    s->mb_x= s->resync_mb_x;
-    for(s->mb_y= s->resync_mb_y; mb_num < s->mb_num_left; s->mb_y++){
-        init_block_index(s);
-        for(; mb_num < s->mb_num_left && s->mb_x<s->mb_width; s->mb_x++){
+    for(; s->mb_y<s->mb_height; s->mb_y++){
+        ff_init_block_index(s);
+        for(; s->mb_x<s->mb_width; s->mb_x++){
             const int xy= s->mb_x + s->mb_y*s->mb_width;
             int cbpc;
             int dir=0;
             
             mb_num++;
-            update_block_index(s);
+            ff_update_block_index(s);
             if(s->mb_x == s->resync_mb_x && s->mb_y == s->resync_mb_y+1)
                 s->first_slice_line=0;
             
@@ -2391,11 +2458,16 @@
             if(s->pict_type==I_TYPE){
                 int i;
 
+                if(show_bits(&s->gb, 19)==DC_MARKER){
+                    return mb_num-1;
+                }
+
                 PRINT_MB_TYPE("I");
                 cbpc = get_vlc2(&s->gb, intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 1);
                 if (cbpc < 0){
+
                     fprintf(stderr, "cbpc corrupted at %d %d\n", s->mb_x, s->mb_y);
-                    return DECODING_DESYNC;
+                    return -1;
                 }
                 s->cbp_table[xy]= cbpc & 3;
                 s->mb_type[xy]= MB_TYPE_INTRA;
@@ -2412,18 +2484,25 @@
                     int dc= mpeg4_decode_dc(s, i, &dc_pred_dir); 
                     if(dc < 0){
                         fprintf(stderr, "DC corrupted at %d %d\n", s->mb_x, s->mb_y);
-                        return DECODING_DESYNC;
+                        return -1;
                     }
                     dir<<=1;
                     if(dc_pred_dir) dir|=1;
                 }
                 s->pred_dir_table[xy]= dir;
+                
+                s->error_status_table[xy]= AC_ERROR;
             }else{ /* P/S_TYPE */
-                int mx, my, pred_x, pred_y;
+                int mx, my, pred_x, pred_y, bits;
                 INT16 * const mot_val= s->motion_val[s->block_index[0]];
                 const int stride= s->block_wrap[0]*2;
 
-                if(get_bits1(&s->gb)){
+                bits= show_bits(&s->gb, 17);
+                if(bits==MOTION_MARKER){
+                    return mb_num-1;
+                }
+                skip_bits1(&s->gb);
+                if(bits&0x10000){
                     /* skip mb */
                     s->mb_type[xy]= MB_TYPE_SKIPED;
                     if(s->pict_type==S_TYPE && s->vol_sprite_usage==GMC_SPRITE){
@@ -2450,12 +2529,13 @@
                     if(s->mbintra_table[xy])
                         ff_clean_intra_table_entries(s);
 
+                    s->error_status_table[xy]= AC_ERROR;
                     continue;
                 }
                 cbpc = get_vlc2(&s->gb, inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2);
                 if (cbpc < 0){
                     fprintf(stderr, "cbpc corrupted at %d %d\n", s->mb_x, s->mb_y);
-                    return DECODING_DESYNC;
+                    return -1;
                 }
                 if (cbpc > 20)
                     cbpc+=3;
@@ -2473,6 +2553,7 @@
                     mot_val[0+stride]= mot_val[2+stride]= 0;
                     mot_val[1       ]= mot_val[3       ]=
                     mot_val[1+stride]= mot_val[3+stride]= 0;
+                    s->error_status_table[xy]= DC_ERROR|AC_ERROR;
                 }else{
                     if(s->mbintra_table[xy])
                         ff_clean_intra_table_entries(s);
@@ -2498,7 +2579,7 @@
                             }
                         }
                         if (mx >= 0xffff)
-                            return DECODING_DESYNC;
+                            return -1;
             
                         if(!s->mcsel)
                            my = h263_decode_motion(s, pred_y, s->f_code);
@@ -2511,7 +2592,7 @@
                             }
                         }
                         if (my >= 0xffff)
-                            return DECODING_DESYNC;
+                            return -1;
                         mot_val[0       ]= mot_val[2       ] =
                         mot_val[0+stride]= mot_val[2+stride]= mx;
                         mot_val[1       ]= mot_val[3       ]=
@@ -2524,45 +2605,51 @@
                             INT16 *mot_val= h263_pred_motion(s, i, &pred_x, &pred_y);
                             mx = h263_decode_motion(s, pred_x, s->f_code);
                             if (mx >= 0xffff)
-                                return DECODING_DESYNC;
+                                return -1;
                 
                             my = h263_decode_motion(s, pred_y, s->f_code);
                             if (my >= 0xffff)
-                                return DECODING_DESYNC;
+                                return -1;
                             mot_val[0] = mx;
                             mot_val[1] = my;
                         }
                     }
+                    s->error_status_table[xy]= AC_ERROR;
                 }
             }
         }
         s->mb_x= 0;
     }
 
-    if     (s->pict_type==I_TYPE && get_bits(&s->gb, 19)!=DC_MARKER    ) s->decoding_error= DECODING_DESYNC;
-    else if(s->pict_type!=I_TYPE && get_bits(&s->gb, 17)!=MOTION_MARKER) s->decoding_error= DECODING_DESYNC;
-    if(s->decoding_error== DECODING_DESYNC){
-        fprintf(stderr, "marker missing after first partition at %d %d\n", s->mb_x, s->mb_y);
-        return DECODING_DESYNC;
-    }
-
-    /* decode second partition */
-    mb_num=0;
+    return mb_num;
+}
+
+/**
+ * decode second partition.
+ * @return <0 if an error occured
+ */
+static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count){
+    int mb_num=0;
+    static const INT8 quant_tab[4] = { -1, -2, 1, 2 };
+
     s->mb_x= s->resync_mb_x;
-    for(s->mb_y= s->resync_mb_y; mb_num < s->mb_num_left; s->mb_y++){
-        init_block_index(s);
-        for(; mb_num < s->mb_num_left && s->mb_x<s->mb_width; s->mb_x++){
+    s->first_slice_line=1;
+    for(s->mb_y= s->resync_mb_y; mb_num < mb_count; s->mb_y++){
+        ff_init_block_index(s);
+        for(; mb_num < mb_count && s->mb_x<s->mb_width; s->mb_x++){
             const int xy= s->mb_x + s->mb_y*s->mb_width;
 
             mb_num++;
-            update_block_index(s);
+            ff_update_block_index(s);
+            if(s->mb_x == s->resync_mb_x && s->mb_y == s->resync_mb_y+1)
+                s->first_slice_line=0;
             
             if(s->pict_type==I_TYPE){
                 int ac_pred= get_bits1(&s->gb);
                 int cbpy = get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1);
                 if(cbpy<0){
                     fprintf(stderr, "cbpy corrupted at %d %d\n", s->mb_x, s->mb_y);
-                    return DECODING_AC_LOST;
+                    return -1;
                 }
                 
                 s->cbp_table[xy]|= cbpy<<2;
@@ -2575,7 +2662,7 @@
 
                     if(cbpy<0){
                         fprintf(stderr, "I cbpy corrupted at %d %d\n", s->mb_x, s->mb_y);
-                        return DECODING_ACDC_LOST;
+                        return -1;
                     }
                     
                     if(s->cbp_table[xy] & 8) {
@@ -2588,7 +2675,7 @@
                         int dc= mpeg4_decode_dc(s, i, &dc_pred_dir); 
                         if(dc < 0){
                             fprintf(stderr, "DC corrupted at %d %d\n", s->mb_x, s->mb_y);
-                            return DECODING_ACDC_LOST;
+                            return -1;
                         }
                         dir<<=1;
                         if(dc_pred_dir) dir|=1;
@@ -2596,6 +2683,7 @@
                     s->cbp_table[xy]&= 3; //remove dquant
                     s->cbp_table[xy]|= cbpy<<2;
                     s->pred_dir_table[xy]= dir | (ac_pred<<7);
+                    s->error_status_table[xy]&= ~DC_ERROR;
                 }else if(s->mb_type[xy]&MB_TYPE_SKIPED){
                     s->qscale_table[xy]= s->qscale;
                     s->cbp_table[xy]= 0;
@@ -2604,7 +2692,7 @@
 
                     if(cbpy<0){
                         fprintf(stderr, "P cbpy corrupted at %d %d\n", s->mb_x, s->mb_y);
-                        return DECODING_ACDC_LOST;
+                        return -1;
                     }
                     
                     if(s->cbp_table[xy] & 8) {
@@ -2617,51 +2705,72 @@
                 }
             }
         }
+        if(mb_num >= mb_count) return 0;
         s->mb_x= 0;
     }
+    return 0;
+}
+
+/**
+ * decodes the first & second partition
+ * @return <0 if error (and sets error type in the error_status_table)
+ */
+int ff_mpeg4_decode_partitions(MpegEncContext *s)
+{
+    int mb_num;
     
+    mb_num= mpeg4_decode_partition_a(s);    
+    if(mb_num<0)
+        return -1;
+    
+    if(s->resync_mb_x + s->resync_mb_y*s->mb_width + mb_num > s->mb_num){
+        fprintf(stderr, "slice below monitor ...\n");
+        return -1;
+    }
+
+    s->mb_num_left= mb_num;
+        
+    if(s->pict_type==I_TYPE){
+        if(get_bits(&s->gb, 19)!=DC_MARKER){
+            fprintf(stderr, "marker missing after first I partition at %d %d\n", s->mb_x, s->mb_y);
+            return -1;
+        }else
+            s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= MV_END|DC_END;
+    }else{
+        if(get_bits(&s->gb, 17)!=MOTION_MARKER){
+            fprintf(stderr, "marker missing after first P partition at %d %d\n", s->mb_x, s->mb_y);
+            return -1;
+        }else
+            s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= MV_END;
+    }
+    
+    if( mpeg4_decode_partition_b(s, mb_num) < 0){
+        return -1;
+    }
+    
+    s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= DC_END;
 
     return 0;        
 }
 
-static int mpeg4_decode_partitioned_mb(MpegEncContext *s,
-                   DCTELEM block[6][64])
+/**
+ * decode partition C of one MB.
+ * @return <0 if an error occured
+ */
+static int mpeg4_decode_partitioned_mb(MpegEncContext *s, DCTELEM block[6][64])
 {
     int cbp, mb_type;
     const int xy= s->mb_x + s->mb_y*s->mb_width;
 
-    if(s->mb_x==s->resync_mb_x && s->mb_y==s->resync_mb_y){ //Note resync_mb_{x,y}==0 at the start
-        int i;
-        int block_index_backup[6];
-        int qscale= s->qscale;
-        
-        for(i=0; i<6; i++) block_index_backup[i]= s->block_index[i];
-        
-        s->decoding_error= ff_mpeg4_decode_partitions(s);
-        
-        for(i=0; i<6; i++) s->block_index[i]= block_index_backup[i];
-        s->first_slice_line=1;
-        s->mb_x= s->resync_mb_x;
-        s->mb_y= s->resync_mb_y;
-        s->qscale= qscale;
-        s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
-        s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
-
-        if(s->decoding_error==DECODING_DESYNC) return -1;
-    }
-    
     mb_type= s->mb_type[xy];
-    if(s->decoding_error)
-        cbp=0;
-    else 
-        cbp = s->cbp_table[xy];
-
-    if(s->decoding_error!=DECODING_ACDC_LOST && s->qscale_table[xy] != s->qscale){
+    cbp = s->cbp_table[xy];
+
+    if(s->qscale_table[xy] != s->qscale){
         s->qscale= s->qscale_table[xy];
         s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
         s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
     }
-
+    
     if (s->pict_type == P_TYPE || s->pict_type==S_TYPE) {
         int i;
         for(i=0; i<4; i++){
@@ -2683,21 +2792,14 @@
                 s->mcsel=0;
                 s->mb_skiped = 1;
             }
-            return 0;
-        }else if(s->mb_intra && s->decoding_error!=DECODING_ACDC_LOST){
+        }else if(s->mb_intra){
             s->ac_pred = s->pred_dir_table[xy]>>7;
 
             /* decode each block */
             for (i = 0; i < 6; i++) {
-                int ret= mpeg4_decode_block(s, block[i], i, cbp&32, 1);
-                if(ret==DECODING_AC_LOST){
-                    fprintf(stderr, "texture corrupted at %d %d (trying to continue with mc/dc only)\n", s->mb_x, s->mb_y);
-                    s->decoding_error=DECODING_AC_LOST;
-                    cbp=0;
-                }else if(ret==DECODING_ACDC_LOST){
-                    fprintf(stderr, "dc corrupted at %d %d (trying to continue with mc only)\n", s->mb_x, s->mb_y);
-                    s->decoding_error=DECODING_ACDC_LOST;
-                    break;
+                if(mpeg4_decode_block(s, block[i], i, cbp&32, 1) < 0){
+                    fprintf(stderr, "texture corrupted at %d %d\n", s->mb_x, s->mb_y);
+                    return -1;
                 }
                 cbp+=cbp;
             }
@@ -2710,17 +2812,13 @@
             } else {
                 s->mv_type = MV_TYPE_16X16;
             }
-            if(s->decoding_error==0 && cbp){
-                /* decode each block */
-                for (i = 0; i < 6; i++) {
-                    int ret= mpeg4_decode_block(s, block[i], i, cbp&32, 0);
-                    if(ret==DECODING_AC_LOST){
-                        fprintf(stderr, "texture corrupted at %d %d (trying to continue with mc/dc only)\n", s->mb_x, s->mb_y);
-                        s->decoding_error=DECODING_AC_LOST;
-                        break;
-                    }
-                    cbp+=cbp;
+            /* decode each block */
+            for (i = 0; i < 6; i++) {
+                if(mpeg4_decode_block(s, block[i], i, cbp&32, 0) < 0){
+                    fprintf(stderr, "texture corrupted at %d %d (trying to continue with mc/dc only)\n", s->mb_x, s->mb_y);
+                    return -1;
                 }
+                cbp+=cbp;
             }
         }
     } else { /* I-Frame */
@@ -2730,71 +2828,43 @@
         
         /* decode each block */
         for (i = 0; i < 6; i++) {
-            int ret= mpeg4_decode_block(s, block[i], i, cbp&32, 1);
-            if(ret==DECODING_AC_LOST){
+            if(mpeg4_decode_block(s, block[i], i, cbp&32, 1) < 0){
                 fprintf(stderr, "texture corrupted at %d %d (trying to continue with dc only)\n", s->mb_x, s->mb_y);
-                s->decoding_error=DECODING_AC_LOST;
-                cbp=0;
-            }else if(ret==DECODING_ACDC_LOST){
-                fprintf(stderr, "dc corrupted at %d %d\n", s->mb_x, s->mb_y);
                 return -1;
             }
             cbp+=cbp;
         }
     }
 
-    return 0;
-}
-#if 0
-static inline void decode_interlaced_info(MpegEncContext *s, int cbp, int mb_type){
-    s->mv_type= 0;            
-    if(!s->progressive_sequence){
-        if(cbp || s->mb_intra)
-            s->interlaced_dct= get_bits1(&s->gb);
-        
-        if(!s->mb_intra){
-            if(   s->pict_type==P_TYPE //FIXME check that 4MV is forbidden
-               || (s->pict_type==S_TYPE && s->vol_sprite_usage==GMC_SPRITE && !s->mcsel)
-               || (s->pict_type==B_TYPE && mb_type!=0) ){
-
-                if(get_bits1(&s->gb)){
-                    s->mv_type= MV_TYPE_FIELD;
-
-                    if(   s->pict_type==P_TYPE
-                       || (s->pict_type==B_TYPE && mb_type!=2)){
-                        s->field_select[0][0]= get_bits1(&s->gb);
-                        s->field_select[0][1]= get_bits1(&s->gb);
-                    }
-                    if(s->pict_type==B_TYPE && mb_type!=3){
-                        s->field_select[1][0]= get_bits1(&s->gb);
-                        s->field_select[1][1]= get_bits1(&s->gb);
-                    }
-                }else
-                    s->mv_type= 0;            
-            }
-        }   
+    s->error_status_table[xy]&= ~AC_ERROR;
+
+    /* per-MB end of slice check */
+
+    if(--s->mb_num_left <= 0){
+//printf("%06X %d\n", show_bits(&s->gb, 24), s->gb.size*8 - get_bits_count(&s->gb));
+        if(mpeg4_is_resync(s))
+            return SLICE_END;
+        else
+            return SLICE_NOEND;     
+    }else{
+        if(s->cbp_table[xy+1] && mpeg4_is_resync(s))
+            return SLICE_END;
+        else
+            return SLICE_OK;
     }
 }
-#endif
-
-int h263_decode_mb(MpegEncContext *s,
-                   DCTELEM block[6][64])
+
+int ff_h263_decode_mb(MpegEncContext *s,
+                      DCTELEM block[6][64])
 {
     int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant;
     INT16 *mot_val;
     static INT8 quant_tab[4] = { -1, -2, 1, 2 };
 
+    s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0;
+
     if(s->mb_x==0) PRINT_MB_TYPE("\n");
 
-    if(s->resync_marker){
-        if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){
-            s->first_slice_line=0; 
-        }
-    }
-
-    if(s->data_partitioning && s->pict_type!=B_TYPE)
-        return mpeg4_decode_partitioned_mb(s, block);
-
     if (s->pict_type == P_TYPE || s->pict_type==S_TYPE) {
         if (get_bits1(&s->gb)) {
             /* skip mb */
@@ -2828,7 +2898,7 @@
                 s->mv[0][0][1] = 0;
                 s->mb_skiped = 1;
             }
-            return 0;
+            goto end;
         }
         cbpc = get_vlc2(&s->gb, inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2);
         //fprintf(stderr, "\tCBPC: %d", cbpc);
@@ -2851,7 +2921,7 @@
         if (dquant) {
             change_qscale(s, quant_tab[get_bits(&s->gb, 2)]);
         }
-        if((!s->progressive_sequence) && (cbp || s->workaround_bugs==2))
+        if((!s->progressive_sequence) && (cbp || (s->workaround_bugs&FF_BUG_XVID_ILACE)))
             s->interlaced_dct= get_bits1(&s->gb);
         
         s->mv_dir = MV_DIR_FORWARD;
@@ -2981,7 +3051,7 @@
             s->mv[1][0][0] = 0;
             s->mv[1][0][1] = 0;
             PRINT_MB_TYPE("s");
-            return 0;
+            goto end;
         }
 
         modb1= get_bits1(&s->gb); 
@@ -3160,6 +3230,7 @@
         if (dquant) {
             change_qscale(s, quant_tab[get_bits(&s->gb, 2)]);
         }
+        
         if(!s->progressive_sequence)
             s->interlaced_dct= get_bits1(&s->gb);
 
@@ -3177,7 +3248,7 @@
                 cbp+=cbp;
             }
         }
-        return 0;
+        goto end;
     }
 
     /* decode each block */
@@ -3194,7 +3265,27 @@
             cbp+=cbp;
         }
     }
-    return 0;
+end:
+
+        /* per-MB end of slice check */
+    if(s->codec_id==CODEC_ID_MPEG4){
+        if(mpeg4_is_resync(s)){
+            if(s->pict_type==B_TYPE && s->mbskip_table[s->mb_y * s->mb_width + s->mb_x+1])
+                return SLICE_OK;
+            return SLICE_END;
+        }
+    }else{
+        if(get_bits_count(&s->gb) + 7 >= s->gb.size*8){
+            int v= show_bits(&s->gb, 8) >> (((get_bits_count(&s->gb)-1)&7)+1);
+            if(v==0)
+                return SLICE_END;
+        }else{
+            if(show_bits(&s->gb, 16)==0)
+                return SLICE_END; 
+        }
+    }
+
+    return SLICE_OK;     
 }
 
 static int h263_decode_motion(MpegEncContext * s, int pred, int f_code)
@@ -3314,8 +3405,10 @@
 
     for(;;) {
         code = get_vlc2(&s->gb, rl->vlc.table, TEX_VLC_BITS, 2);
-        if (code < 0)
+        if (code < 0){
+            fprintf(stderr, "illegal ac vlc code at %dx%d\n", s->mb_x, s->mb_y);
             return -1;
+        }
         if (code == rl->n) {
             /* escape */
             last = get_bits1(&s->gb);
@@ -3334,8 +3427,10 @@
                 level = -level;
         }
         i += run;
-        if (i >= 64)
+        if (i >= 64){
+            fprintf(stderr, "run overflow at %dx%d\n", s->mb_x, s->mb_y);
             return -1;
+        }
         j = scan_table[i];
         block[j] = level;
         if (last)
@@ -3372,29 +3467,39 @@
             level = - (level ^ ((1 << code) - 1));
         if (code > 8){
             if(get_bits1(&s->gb)==0){ /* marker */
-                fprintf(stderr, "dc marker bit missing\n");
-                return -1;
+                if(s->error_resilience>=2){
+                    fprintf(stderr, "dc marker bit missing\n");
+                    return -1;
+                }
             }
         }
     }
-
     pred = ff_mpeg4_pred_dc(s, n, &dc_val, dir_ptr);
     level += pred;
-    if (level < 0)
+    if (level < 0){
+        if(s->error_resilience>=3){
+            fprintf(stderr, "dc<0 at %dx%d\n", s->mb_x, s->mb_y);
+            return -1;
+        }
         level = 0;
+    }
     if (n < 4) {
         *dc_val = level * s->y_dc_scale;
     } else {
         *dc_val = level * s->c_dc_scale;
     }
+    if(s->error_resilience>=3){
+        if(*dc_val > 2048 + s->y_dc_scale + s->c_dc_scale){
+            fprintf(stderr, "dc overflow at %dx%d\n", s->mb_x, s->mb_y);
+            return -1;
+        }
+    }
     return level;
 }
 
 /**
- * decode a block
- * returns 0 if everything went ok
- * returns DECODING_AC_LOST   if an error was detected during AC decoding
- * returns DECODING_ACDC_LOST if an error was detected during DC decoding
+ * decodes a block.
+ * @return <0 if an error occured
  */
 static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
                               int n, int coded, int intra)
@@ -3408,7 +3513,7 @@
 
     if(intra) {
 	/* DC coef */
-        if(s->data_partitioning && s->pict_type!=B_TYPE){
+        if(s->partitioned_frame){
             level = s->dc_val[0][ s->block_index[n] ];
             if(n<4) level= (level + (s->y_dc_scale>>1))/s->y_dc_scale; //FIXME optimizs
             else    level= (level + (s->c_dc_scale>>1))/s->c_dc_scale;
@@ -3416,7 +3521,7 @@
         }else{
             level = mpeg4_decode_dc(s, n, &dc_pred_dir);
             if (level < 0)
-                return DECODING_ACDC_LOST;
+                return -1;
         }
         block[0] = level;
         i = 0;
@@ -3474,38 +3579,38 @@
 
                     if(SHOW_UBITS(re, &s->gb, 1)==0){
                         fprintf(stderr, "1. marker bit missing in 3. esc\n");
-                        return DECODING_AC_LOST;
+                        return -1;
                     }; SKIP_CACHE(re, &s->gb, 1);
                     
                     level= SHOW_SBITS(re, &s->gb, 12); SKIP_CACHE(re, &s->gb, 12);
  
                     if(SHOW_UBITS(re, &s->gb, 1)==0){
                         fprintf(stderr, "2. marker bit missing in 3. esc\n");
-                        return DECODING_AC_LOST;
+                        return -1;
                     }; LAST_SKIP_CACHE(re, &s->gb, 1);
                     
                     SKIP_COUNTER(re, &s->gb, 1+12+1);
                     
                     if(level*s->qscale>1024 || level*s->qscale<-1024){
                         fprintf(stderr, "|level| overflow in 3. esc, qp=%d\n", s->qscale);
-                        return DECODING_AC_LOST;
+                        return -1;
                     }
 #if 1 
                     {
                         const int abs_level= ABS(level);
-                        if(abs_level<=MAX_LEVEL && run<=MAX_RUN && s->error_resilience>=0){
+                        if(abs_level<=MAX_LEVEL && run<=MAX_RUN && ((s->workaround_bugs&FF_BUG_AC_VLC)==0)){
                             const int run1= run - rl->max_run[last][abs_level] - 1;
                             if(abs_level <= rl->max_level[last][run]){
                                 fprintf(stderr, "illegal 3. esc, vlc encoding possible\n");
-                                return DECODING_AC_LOST;
+                                return -1;
                             }
                             if(abs_level <= rl->max_level[last][run]*2){
                                 fprintf(stderr, "illegal 3. esc, esc 1 encoding possible\n");
-                                return DECODING_AC_LOST;
+                                return -1;
                             }
                             if(run1 >= 0 && abs_level <= rl->max_level[last][run1]){
                                 fprintf(stderr, "illegal 3. esc, esc 2 encoding possible\n");
-                                return DECODING_AC_LOST;
+                                return -1;
                             }
                         }
                     }
@@ -3551,7 +3656,7 @@
             i-= 192;
             if(i&(~63)){
                 fprintf(stderr, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y);
-                return DECODING_AC_LOST;
+                return -1;
             }
 
             block[scan_table[i]] = level;
@@ -4184,7 +4289,7 @@
                 s->enhancement_type= get_bits1(&s->gb);
                 
                 if(   h_sampling_factor_n==0 || h_sampling_factor_m==0 
-                   || v_sampling_factor_n==0 || v_sampling_factor_m==0 || s->workaround_bugs==1){
+                   || v_sampling_factor_n==0 || v_sampling_factor_m==0){
                    
 //                    fprintf(stderr, "illegal scalability header (VERY broken encoder), trying to workaround\n");
                     s->scalability=0;
@@ -4203,7 +4308,7 @@
         char buf[256];
         int i;
         int e;
-        int ver, build;
+        int ver, build, ver2, ver3;
 
 //printf("user Data %X\n", show_bits(&s->gb, 32));
         buf[0]= show_bits(&s->gb, 8);
@@ -4226,12 +4331,27 @@
                 }
             }
         }
+        e=sscanf(buf, "FFmpeg%d.%d.%db%d", &ver, &ver2, &ver3, &build);
+        if(e!=4)
+            e=sscanf(buf, "FFmpeg v%d.%d.%d / libavcodec build: %d", &ver, &ver2, &ver3, &build); 
+        if(e!=4){
+            if(strcmp(buf, "ffmpeg")==0){
+                s->ffmpeg_version= 0x000406;
+                s->lavc_build= 4600;
+            }
+        }
+        if(e==4){
+            s->ffmpeg_version= ver*256*256 + ver2*256 + ver3;
+            s->lavc_build= build;
+            if(s->picture_number==0)
+                printf("This file was encoded with libavcodec build %d\n", build);
+        }
 //printf("User Data: %s\n", buf);
         goto redo;
     } else if (startcode != 0x1b6) { //VOP
         goto redo;
     }
-
+    
     s->pict_type = get_bits(&s->gb, 2) + I_TYPE;	/* pict type: I = 0 , P = 1 */
 //if(s->pict_type!=I_TYPE) return FRAME_SKIPED;
     if(s->pict_type==B_TYPE && s->low_delay && s->vol_control_parameters==0){
@@ -4240,6 +4360,12 @@
     }
 // printf("pic: %d, qpel:%d part:%d resync:%d\n", s->pict_type, s->quarter_sample, s->data_partitioning, s->resync_marker); 
     
+    s->partitioned_frame= s->data_partitioning && s->pict_type!=B_TYPE;
+    if(s->partitioned_frame)
+        s->decode_mb= mpeg4_decode_partitioned_mb;
+    else
+        s->decode_mb= ff_h263_decode_mb;
+
     if(s->time_increment_resolution==0){
         s->time_increment_resolution=1;
 //        fprintf(stderr, "time_increment_resolution is illegal\n");
@@ -4255,7 +4381,7 @@
         s->last_time_base= s->time_base;
         s->time_base+= time_incr;
         s->time= s->time_base*s->time_increment_resolution + time_increment;
-        if(s->workaround_bugs==3 || s->avctx->fourcc == ff_get_fourcc("UMP4")){
+        if(s->workaround_bugs&FF_BUG_UMP4){
             if(s->time < s->last_non_b_time){
 //                fprintf(stderr, "header is not mpeg4 compatible, broken encoder, trying to workaround\n");
                 s->time_base++;
@@ -4356,10 +4482,7 @@
      }
 
      if (s->shape != BIN_ONLY_SHAPE) {
-         /* note: we do not use quant_precision to avoid problem if no
-            MPEG4 vol header as it is found on some old opendivx
-            movies */
-         s->qscale = get_bits(&s->gb, 5);
+         s->qscale = get_bits(&s->gb, s->quant_precision);
          if(s->qscale==0){
              printf("Error, header damaged or not MPEG4 header (qscale=0)\n");
              return -1; // makes no sense to continue, as there is nothing left from the image then
--- a/h263dec.c	Fri Oct 11 23:01:16 2002 +0000
+++ b/h263dec.c	Sun Oct 13 13:16:04 2002 +0000
@@ -20,6 +20,12 @@
 #include "dsputil.h"
 #include "mpegvideo.h"
 
+#if 1
+#define PRINT_QP(a, b) {}
+#else
+#define PRINT_QP(a, b) printf(a, b)
+#endif
+
 //#define DEBUG
 //#define PRINT_FRAME_TIME
 #ifdef PRINT_FRAME_TIME
@@ -34,6 +40,8 @@
 }
 #endif
 
+const UINT16 ff_mpeg4_resync_prefix[8];
+
 static int h263_decode_init(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
@@ -45,6 +53,11 @@
     s->height = avctx->height;
     s->workaround_bugs= avctx->workaround_bugs;
 
+    // set defaults
+    s->quant_precision=5;
+    s->progressive_sequence=1;
+    s->decode_mb= ff_h263_decode_mb;
+
     /* select sub codec */
     switch(avctx->codec->id) {
     case CODEC_ID_H263:
@@ -115,7 +128,6 @@
  */
 static int get_consumed_bytes(MpegEncContext *s, int buf_size){
     int pos= (get_bits_count(&s->gb)+7)>>3;
-
     if(s->divx_version>=500){
         //we would have to scan through the whole buf to handle the weird reordering ...
         return buf_size; 
@@ -127,12 +139,144 @@
     }
 }
 
+static int decode_slice(MpegEncContext *s){
+    s->last_resync_gb= s->gb;
+    s->first_slice_line= 1;
+        
+    s->resync_mb_x= s->mb_x;
+    s->resync_mb_y= s->mb_y;
+
+    s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
+    s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
+    
+    if(s->partitioned_frame){
+        const int qscale= s->qscale;
+
+        if(s->codec_id==CODEC_ID_MPEG4){
+            if(ff_mpeg4_decode_partitions(s) < 0)
+                return -1; 
+        }
+        
+        /* restore variables which where modified */
+        s->first_slice_line=1;
+        s->mb_x= s->resync_mb_x;
+        s->mb_y= s->resync_mb_y;
+        s->qscale= qscale;
+        s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
+        s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
+    }
+
+    for(; s->mb_y < s->mb_height; s->mb_y++) {
+        /* per-row end of slice checks */
+        if(s->msmpeg4_version){
+            if(s->resync_mb_y + s->slice_height == s->mb_y){
+                const int xy= s->mb_x + s->mb_y*s->mb_width;
+                s->error_status_table[xy-1]|= AC_END|DC_END|MV_END;
+                return 0;
+            }
+        }
+        
+        if(s->msmpeg4_version==1){
+            s->last_dc[0]=
+            s->last_dc[1]=
+            s->last_dc[2]= 128;
+        }
+    
+        ff_init_block_index(s);
+        for(; s->mb_x < s->mb_width; s->mb_x++) {
+            int ret;
+
+            ff_update_block_index(s);
+
+            if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){
+                s->first_slice_line=0; 
+            }
+
+            /* DCT & quantize */
+            clear_blocks(s->block[0]);
+            
+            s->mv_dir = MV_DIR_FORWARD;
+            s->mv_type = MV_TYPE_16X16;
+//printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24));
+            ret= s->decode_mb(s, s->block);
+            
+            PRINT_QP("%2d", s->qscale);
+            MPV_decode_mb(s, s->block);
+
+            if(ret<0){
+                const int xy= s->mb_x + s->mb_y*s->mb_width;
+                if(ret==SLICE_END){
+//printf("%d %d %06X\n", s->mb_x, s->gb.size*8 - get_bits_count(&s->gb), show_bits(&s->gb, 24));
+                    s->error_status_table[xy]|= AC_END;
+                    if(!s->partitioned_frame)
+                        s->error_status_table[xy]|= MV_END|DC_END;
+                    
+                    if(++s->mb_x >= s->mb_width){
+                        s->mb_x=0;
+                        ff_draw_horiz_band(s);
+                        s->mb_y++;
+                    }
+                    return 0; 
+                }else if(ret==SLICE_NOEND){
+                    fprintf(stderr,"Slice mismatch at MB: %d\n", xy);
+                    return -1;
+                }
+                fprintf(stderr,"Error at MB: %d\n", xy);
+                s->error_status_table[xy]|= AC_ERROR;
+                if(!s->partitioned_frame)
+                    s->error_status_table[xy]|= DC_ERROR|MV_ERROR;
+    
+                return -1;
+            }
+        }
+        
+        ff_draw_horiz_band(s);
+        
+        PRINT_QP("%s", "\n");
+        
+        s->mb_x= 0;
+    }
+    
+    assert(s->mb_x==0 && s->mb_y==s->mb_height);
+
+    // handle formats which dont have unique end markers
+    if(s->msmpeg4_version || (s->workaround_bugs&FF_BUG_NO_PADDING)){ //FIXME perhaps solve this more cleanly
+        int left= s->gb.size*8 - get_bits_count(&s->gb);
+        int max_extra=7;
+        
+        /* no markers in M$ crap */
+        if(s->msmpeg4_version && s->pict_type==I_TYPE)
+            max_extra+= 17;
+        
+        /* buggy padding but the frame should still end approximately at the bitstream end */
+        if((s->workaround_bugs&FF_BUG_NO_PADDING) && s->error_resilience>=3)
+            max_extra+= 48;
+        else if((s->workaround_bugs&FF_BUG_NO_PADDING))
+            max_extra+= 256*256*256*64;
+        
+        if(left>max_extra){
+            fprintf(stderr, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24));
+        }
+        else if(left<0){
+            fprintf(stderr, "overreading %d bits\n", -left);
+        }else
+            s->error_status_table[s->mb_num-1]|= AC_END|MV_END|DC_END;
+        
+        return 0;
+    }
+        
+    fprintf(stderr, "slice end not reached but screenspace end (%d left %06X)\n", 
+            s->gb.size*8 - get_bits_count(&s->gb),
+            show_bits(&s->gb, 24));
+    return -1;
+}
+
 static int h263_decode_frame(AVCodecContext *avctx, 
                              void *data, int *data_size,
                              UINT8 *buf, int buf_size)
 {
     MpegEncContext *s = avctx->priv_data;
-    int ret;
+    int ret,i;
     AVPicture *pict = data; 
 #ifdef PRINT_FRAME_TIME
 uint64_t time= rdtsc();
@@ -145,10 +289,6 @@
     s->hurry_up= avctx->hurry_up;
     s->error_resilience= avctx->error_resilience;
 
-    s->workaround_bugs= avctx->workaround_bugs;
-    if(s->avctx->fourcc == ff_get_fourcc("XVIX") && s->workaround_bugs==0) 
-        s->workaround_bugs=2;
-
     s->flags= avctx->flags;
 
     *data_size = 0;
@@ -165,7 +305,7 @@
     s->bitstream_buffer_size=0;
 
     if (!s->context_initialized) {
-        if (MPV_common_init(s) < 0) //we need the idct permutaton for reading a custom matrix
+        if (DCT_common_init(s) < 0) //we need the idct permutaton for reading a custom matrix
             return -1;
     }
         
@@ -181,6 +321,37 @@
         ret = h263_decode_picture_header(s);
     }
     avctx->has_b_frames= s->has_b_frames;
+
+    if(s->workaround_bugs&FF_BUG_AUTODETECT){
+        if(s->avctx->fourcc == ff_get_fourcc("XVIX")) 
+            s->workaround_bugs|= FF_BUG_XVID_ILACE;
+
+        if(s->avctx->fourcc == ff_get_fourcc("MP4S")) 
+            s->workaround_bugs|= FF_BUG_AC_VLC;
+        
+        if(s->avctx->fourcc == ff_get_fourcc("M4S2")) 
+            s->workaround_bugs|= FF_BUG_AC_VLC;
+                
+        if(s->avctx->fourcc == ff_get_fourcc("UMP4")){
+            s->workaround_bugs|= FF_BUG_UMP4;
+            s->workaround_bugs|= FF_BUG_AC_VLC;
+        }
+        
+        if(s->divx_version==500)
+            s->workaround_bugs|= FF_BUG_NO_PADDING;
+
+        /* very ugly XVID padding bug detection FIXME/XXX solve this differently
+         * lets hope this at least works
+         */
+        if(   s->resync_marker==0 && s->data_partitioning==0 && s->divx_version==0
+           && s->codec_id==CODEC_ID_MPEG4 && s->vo_type==0)
+            s->workaround_bugs|= FF_BUG_NO_PADDING;
+        
+        if(s->lavc_build && s->lavc_build<4609) //FIXME not sure about the version num but a 4609 file seems ok
+            s->workaround_bugs|= FF_BUG_NO_PADDING;
+    }
+    
+
 #if 0 // dump bits per frame / qp / complexity
 {
     static FILE *f=NULL;
@@ -210,10 +381,14 @@
 	    avctx->aspected_width = s->aspected_width;
 	    avctx->aspected_height = s->aspected_height;
 	}
+
+        if (s->codec_id==CODEC_ID_H263 && s->codec_id==CODEC_ID_H263)
+            s->gob_index = ff_h263_get_gob_height(s);
+
         if (MPV_common_init(s) < 0)
             return -1;
     }
-
+    
     if(ret==FRAME_SKIPED) return get_consumed_bytes(s, buf_size);
     /* skip if the header was thrashed */
     if (ret < 0){
@@ -238,12 +413,9 @@
     printf("qscale=%d\n", s->qscale);
 #endif
 
-    /* init resync/ error resilience specific variables */
-    s->next_resync_qscale= s->qscale;
-    s->next_resync_gb= s->gb;
-    if(s->resync_marker) s->mb_num_left= 0;
-    else                 s->mb_num_left= s->mb_num;
-
+    if(s->error_resilience)
+        memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_num*sizeof(UINT8));
+    
     /* decode each macroblock */
     s->block_wrap[0]=
     s->block_wrap[1]=
@@ -251,143 +423,25 @@
     s->block_wrap[3]= s->mb_width*2 + 2;
     s->block_wrap[4]=
     s->block_wrap[5]= s->mb_width + 2;
-    for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) {
-        /* Check for GOB headers on H.263 */
-        /* FIXME: In the future H.263+ will have intra prediction */
-        /* and we are gonna need another way to detect MPEG4      */
-        if (s->mb_y && !s->h263_pred) {
-            s->first_slice_line = h263_decode_gob_header(s);
+    s->mb_x=0; 
+    s->mb_y=0;
+    
+    decode_slice(s);
+    s->error_status_table[0]|= VP_START;
+    while(s->mb_y<s->mb_height && s->gb.size*8 - get_bits_count(&s->gb)>32){
+        if(s->msmpeg4_version){
+            if(s->mb_x!=0 || (s->mb_y%s->slice_height)!=0)
+                break;
+        }else{
+            if(ff_h263_resync(s)<0)
+                break;
         }
         
-        if(s->msmpeg4_version==1){
-            s->last_dc[0]=
-            s->last_dc[1]=
-            s->last_dc[2]= 128;
-        }
-
-        s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
-        s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
-
-        s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1;
-        s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1);
-        s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1;
-        s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2);
-        s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1)                    + s->block_wrap[0]*(s->mb_height*2 + 2);
-        s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2);
-        for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
-            s->block_index[0]+=2;
-            s->block_index[1]+=2;
-            s->block_index[2]+=2;
-            s->block_index[3]+=2;
-            s->block_index[4]++;
-            s->block_index[5]++;
-#ifdef DEBUG
-            printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
-#endif
-
-            if(s->resync_marker){
-                if(s->mb_num_left<=0){
-                    /* except the first block */
-                    if(s->mb_x!=0 || s->mb_y!=0){
-                        /* did we miss the next resync marker without noticing an error yet */
-                        if(((get_bits_count(&s->gb)+8)&(~7)) != s->next_resync_pos && s->decoding_error==0){
-                            fprintf(stderr, "slice end missmatch x:%d y:%d %d %d\n", 
-                                    s->mb_x, s->mb_y, get_bits_count(&s->gb), s->next_resync_pos);
-                            ff_conceal_past_errors(s, 1);
-                        }
-                    }
-                    s->qscale= s->next_resync_qscale;
-                    s->y_dc_scale= s->y_dc_scale_table[ s->qscale ];
-                    s->c_dc_scale= s->c_dc_scale_table[ s->qscale ];
-
-                    s->gb= s->next_resync_gb;
-                    s->resync_mb_x= s->mb_x; //we know that the marker is here cuz mb_num_left was the distance to it
-                    s->resync_mb_y= s->mb_y;
-                    s->first_slice_line=1;
-
-                    if(s->codec_id==CODEC_ID_MPEG4){
-                        ff_mpeg4_clean_buffers(s);
-                        ff_mpeg4_resync(s);
-                    }
-                }
-
-                if(   s->resync_mb_x==s->mb_x 
-                   && s->resync_mb_y==s->mb_y && s->decoding_error!=0){
-                    fprintf(stderr, "resynced at %d %d\n", s->mb_x, s->mb_y);
-                    s->decoding_error= 0;
-                }
-            }
+        if(s->msmpeg4_version!=4)
+            ff_mpeg4_clean_buffers(s);
 
-            //fprintf(stderr,"\nFrame: %d\tMB: %d",avctx->frame_number, (s->mb_y * s->mb_width) + s->mb_x);
-            /* DCT & quantize */
-            if(s->decoding_error!=DECODING_DESYNC){
-                int last_error= s->decoding_error;
-                clear_blocks(s->block[0]);
-            
-                s->mv_dir = MV_DIR_FORWARD;
-                s->mv_type = MV_TYPE_16X16;
-                if (s->h263_msmpeg4) {
-                    if (msmpeg4_decode_mb(s, s->block) < 0) {
-                        fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
-                        s->decoding_error=DECODING_DESYNC;
-                    }
-                } else {
-                    if (h263_decode_mb(s, s->block) < 0) {
-                        fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
-                        s->decoding_error=DECODING_DESYNC;
-                    }
-                }
-
-                if(s->decoding_error!=last_error){
-                    ff_conceal_past_errors(s, 0);
-                }
-            }
-
-            /* conceal errors */
-            if(    s->decoding_error==DECODING_DESYNC
-               || (s->decoding_error==DECODING_ACDC_LOST && s->mb_intra)){
-                s->mv_dir = MV_DIR_FORWARD;
-                s->mv_type = MV_TYPE_16X16;
-                s->mb_skiped=0;
-                s->mb_intra=0;
-                s->mv[0][0][0]=0; //FIXME this is not optimal 
-                s->mv[0][0][1]=0;
-                clear_blocks(s->block[0]);
-            }else if(s->decoding_error && !s->mb_intra){
-                clear_blocks(s->block[0]);
-            }
-            //FIXME remove AC for intra
-                        
-            MPV_decode_mb(s, s->block);
-
-            s->mb_num_left--;            
-        }
-        if (    avctx->draw_horiz_band 
-            && (s->num_available_buffers>=1 || (!s->has_b_frames)) ) {
-            UINT8 *src_ptr[3];
-            int y, h, offset;
-            y = s->mb_y * 16;
-            h = s->height - y;
-            if (h > 16)
-                h = 16;
-
-            if(s->pict_type==B_TYPE)
-                offset = 0;
-            else
-                offset = y * s->linesize;
-
-            if(s->pict_type==B_TYPE || (!s->has_b_frames)){
-                src_ptr[0] = s->current_picture[0] + offset;
-                src_ptr[1] = s->current_picture[1] + (offset >> 2);
-                src_ptr[2] = s->current_picture[2] + (offset >> 2);
-            } else {
-                src_ptr[0] = s->last_picture[0] + offset;
-                src_ptr[1] = s->last_picture[1] + (offset >> 2);
-                src_ptr[2] = s->last_picture[2] + (offset >> 2);
-            }
-            avctx->draw_horiz_band(avctx, src_ptr, s->linesize,
-                                   y, s->width, h);
-        }
+        decode_slice(s);
+        s->error_status_table[s->resync_mb_x + s->resync_mb_y*s->mb_width]|= VP_START;
     }
     
     if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE)
@@ -414,24 +468,37 @@
         }
     }
 
-    if(s->bitstream_buffer_size==0 && s->error_resilience>0){
-        int left= s->gb.size*8 - get_bits_count(&s->gb);
-        int max_extra=8;
-        
-        if(s->codec_id==CODEC_ID_MPEG4) max_extra+=32;
+    if(s->error_resilience){
+        int error=0, num_end_markers=0;
+        for(i=0; i<s->mb_num; i++){
+            int status= s->error_status_table[i];
+#if 0
+            if(i%s->mb_width == 0) printf("\n");
+            printf("%2X ", status); 
+#endif
+            if(status==0) continue;
 
-        if(left>max_extra){
-            fprintf(stderr, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24));
-            if(s->decoding_error==0)
-                ff_conceal_past_errors(s, 1);
+            if(status&(DC_ERROR|AC_ERROR|MV_ERROR))
+                error=1;
+            if(status&VP_START){
+                if(num_end_markers) 
+                    error=1;
+                num_end_markers=3;
+            }
+            if(status&AC_END)
+                num_end_markers--;
+            if(status&DC_END)
+                num_end_markers--;
+            if(status&MV_END)
+                num_end_markers--;
         }
-        if(left<0){
-            fprintf(stderr, "overreading %d bits\n", -left);
-            if(s->decoding_error==0)
-                ff_conceal_past_errors(s, 1);
+        if(num_end_markers || error){
+            fprintf(stderr, "concealing errors\n");
+//printf("type:%d\n", s->pict_type);
+            ff_error_resilience(s);
         }
     }
-  
+
     MPV_frame_end(s);
 #if 0 //dirty show MVs, we should export the MV tables and write a filter to show them
 {
--- a/mpeg4data.h	Fri Oct 11 23:01:16 2002 +0000
+++ b/mpeg4data.h	Sun Oct 13 13:16:04 2002 +0000
@@ -166,4 +166,6 @@
     0, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,20,21,22,23,24,25
 };
 
-
+const UINT16 ff_mpeg4_resync_prefix[8]={
+    0x7F00, 0x7E00, 0x7C00, 0x7800, 0x7000, 0x6000, 0x4000, 0x0000
+};
--- a/mpegvideo.c	Fri Oct 11 23:01:16 2002 +0000
+++ b/mpegvideo.c	Sun Oct 13 13:16:04 2002 +0000
@@ -134,19 +134,7 @@
         goto fail;\
     }\
 }
-/*
-static void build_end(void)
-{
-    int lastIndex;
-    int lastIndexAfterPerm=0;
-    for(lastIndex=0; lastIndex<64; lastIndex++)
-    {
-        if(ff_zigzag_direct[lastIndex] > lastIndexAfterPerm) 
-            lastIndexAfterPerm= ff_zigzag_direct[lastIndex];
-        zigzag_end[lastIndex]= lastIndexAfterPerm + 1;
-    }
-}
-*/
+
 void ff_init_scantable(MpegEncContext *s, ScanTable *st, const UINT8 *src_scantable){
     int i;
     int end;
@@ -343,6 +331,8 @@
         }
         CHECKED_ALLOCZ(s->avctx->stats_out, 256);
     }
+        
+    CHECKED_ALLOCZ(s->error_status_table, s->mb_num*sizeof(UINT8))
     
     if (s->out_format == FMT_H263 || s->encoding) {
         int size;
@@ -355,11 +345,13 @@
     }
 
     if(s->codec_id==CODEC_ID_MPEG4){
-        /* 4mv and interlaced direct mode decoding tables */
-        CHECKED_ALLOCZ(s->co_located_type_table, s->mb_num * sizeof(UINT8))
+        /* interlaced direct mode decoding tables */
         CHECKED_ALLOCZ(s->field_mv_table, s->mb_num*2*2 * sizeof(INT16))
         CHECKED_ALLOCZ(s->field_select_table, s->mb_num*2* sizeof(INT8))
     }
+    /* 4mv b frame decoding table */
+    //note this is needed for h263 without b frames too (segfault on damaged streams otherwise)
+    CHECKED_ALLOCZ(s->co_located_type_table, s->mb_num * sizeof(UINT8))
 
     if (s->h263_pred || s->h263_plus) {
         int y_size, c_size, i, size;
@@ -400,7 +392,8 @@
     s->picture_structure = PICT_FRAME;
     
     /* init macroblock skip table */
-    CHECKED_ALLOCZ(s->mbskip_table, s->mb_num);
+    CHECKED_ALLOCZ(s->mbskip_table, s->mb_num+1);
+    //Note the +1 is for a quicker mpeg4 slice_end detection
     
     s->block= s->blocks[0];
 
@@ -453,6 +446,7 @@
     av_freep(&s->field_select_table);
     av_freep(&s->avctx->stats_out);
     av_freep(&s->ac_stats);
+    av_freep(&s->error_status_table);
     
     for(i=0;i<3;i++) {
         int j;
@@ -597,7 +591,7 @@
         s->unrestricted_mv = 1;
         s->has_b_frames= s->max_b_frames ? 1 : 0;
         s->low_delay= !s->has_b_frames;
-        avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); 
+        avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1);
         break;
     case CODEC_ID_MSMPEG4V1:
         s->out_format = FMT_H263;
@@ -767,7 +761,6 @@
     UINT8 *tmp;
 
     s->mb_skiped = 0;
-    s->decoding_error=0;
     avctx->mbskip_table= s->mbskip_table;
 
     if(avctx->flags&CODEC_FLAG_DR1){
@@ -1997,6 +1990,36 @@
 }
 
 #endif
+
+void ff_draw_horiz_band(MpegEncContext *s){
+    if (    s->avctx->draw_horiz_band 
+        && (s->num_available_buffers>=1 || (!s->has_b_frames)) ) {
+        UINT8 *src_ptr[3];
+        int y, h, offset;
+        y = s->mb_y * 16;
+        h = s->height - y;
+        if (h > 16)
+            h = 16;
+
+        if(s->pict_type==B_TYPE)
+            offset = 0;
+        else
+            offset = y * s->linesize;
+
+        if(s->pict_type==B_TYPE || (!s->has_b_frames)){
+            src_ptr[0] = s->current_picture[0] + offset;
+            src_ptr[1] = s->current_picture[1] + (offset >> 2);
+            src_ptr[2] = s->current_picture[2] + (offset >> 2);
+        } else {
+            src_ptr[0] = s->last_picture[0] + offset;
+            src_ptr[1] = s->last_picture[1] + (offset >> 2);
+            src_ptr[2] = s->last_picture[2] + (offset >> 2);
+        }
+        s->avctx->draw_horiz_band(s->avctx, src_ptr, s->linesize,
+                               y, s->width, h);
+    }
+}
+
 static void encode_mb(MpegEncContext *s, int motion_x, int motion_y)
 {
     const int mb_x= s->mb_x;
@@ -2539,23 +2562,17 @@
     s->last_mv[0][0][0] = 0;
     s->last_mv[0][0][1] = 0;
 
-    /* Get the GOB height based on picture height */
-    if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4) {
-        if (s->height <= 400)
-            s->gob_index = 1;
-        else if (s->height <= 800)
-            s->gob_index = 2;
-        else
-            s->gob_index = 4;
-    }else if(s->codec_id==CODEC_ID_MPEG4){
-        s->gob_index = 1;
-    }
+    if (s->codec_id==CODEC_ID_H263 && s->codec_id==CODEC_ID_H263)
+        s->gob_index = ff_h263_get_gob_height(s);
+    else
+        s->gob_index = 1; //FIXME remove 
 
-    if(s->codec_id==CODEC_ID_MPEG4 && s->data_partitioning && s->pict_type!=B_TYPE)
+    if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame)
         ff_mpeg4_init_partitions(s);
 
     s->resync_mb_x=0;
     s->resync_mb_y=0;
+    s->first_slice_line = 1;
     for(mb_y=0; mb_y < s->mb_height; mb_y++) {
         /* Put GOB header based on RTP MTU for formats which support it per line (H263*)*/
         /* TODO: Put all this stuff in a separate generic function */
@@ -2599,7 +2616,7 @@
             s->block_index[3]+=2;
             s->block_index[4]++;
             s->block_index[5]++;
-            
+//printf("%d %d %d %d %d\n", s->mb_x, s->mb_y, s->resync_mb_x, s->resync_mb_y, s->first_slice_line);
             /* write gob / video packet header for formats which support it at any MB (MPEG4) */
             if(s->rtp_mode && s->mb_y>0 && s->codec_id==CODEC_ID_MPEG4){
                 int pdif= pbBufPtr(&s->pb) - s->ptr_lastgob;
@@ -2607,7 +2624,7 @@
                 //the *2 is there so we stay below the requested size
                 if(pdif + s->mb_line_avgsize/s->mb_width >= s->rtp_payload_size){ 
                     if(s->codec_id==CODEC_ID_MPEG4){
-                        if(s->data_partitioning && s->pict_type!=B_TYPE){
+                        if(s->partitioned_frame){
                             ff_mpeg4_merge_partitions(s);
                             ff_mpeg4_init_partitions(s);
                         }
@@ -2625,11 +2642,11 @@
                     s->resync_mb_x=mb_x;
                     s->resync_mb_y=mb_y;
                 }
+            }
 
-                if(  (s->resync_mb_x   == s->mb_x)
-                   && s->resync_mb_y+1 == s->mb_y){
-                    s->first_slice_line=0; 
-                }
+            if(  (s->resync_mb_x   == s->mb_x)
+               && s->resync_mb_y+1 == s->mb_y){
+                s->first_slice_line=0; 
             }
 
             if(mb_type & (mb_type-1)){ // more than 1 MB type possible
@@ -2639,6 +2656,7 @@
                 copy_context_before_encode(&backup_s, s, -1);
                 backup_s.pb= s->pb;
                 best_s.data_partitioning= s->data_partitioning;
+                best_s.partitioned_frame= s->partitioned_frame;
                 if(s->data_partitioning){
                     backup_s.pb2= s->pb2;
                     backup_s.tex_pb= s->tex_pb;
@@ -2827,7 +2845,7 @@
     }
     emms_c();
 
-    if(s->codec_id==CODEC_ID_MPEG4 && s->data_partitioning && s->pict_type!=B_TYPE)
+    if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame)
         ff_mpeg4_merge_partitions(s);
 
     if (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == I_TYPE)
@@ -3090,119 +3108,6 @@
     }
 }
 
-static void remove_ac(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
-{
-    int dc, dcb, dcr, y, i;
-    for(i=0; i<4; i++){
-        dc= s->dc_val[0][mb_x*2+1 + (i&1) + (mb_y*2+1 + (i>>1))*(s->mb_width*2+2)];
-        for(y=0; y<8; y++){
-            int x;
-            for(x=0; x<8; x++){
-                dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
-            }
-        }
-    }
-    dcb = s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
-    dcr= s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
-    for(y=0; y<8; y++){
-        int x;
-        for(x=0; x<8; x++){
-            dest_cb[x + y*(s->uvlinesize)]= dcb/8;
-            dest_cr[x + y*(s->uvlinesize)]= dcr/8;
-        }
-    }
-}
-
-/**
- * will conceal past errors, and allso drop b frames if needed
- *
- */
-void ff_conceal_past_errors(MpegEncContext *s, int unknown_pos)
-{
-    int mb_x= s->mb_x;
-    int mb_y= s->mb_y;
-    int mb_dist=0;
-    int i, intra_count=0, inter_count=0;
-    int intra_conceal= s->msmpeg4_version ? 50 : 50; //FIXME finetune
-    int inter_conceal= s->msmpeg4_version ? 50 : 50;
-
-    // for last block
-    if(mb_x>=s->mb_width)  mb_x= s->mb_width -1;
-    if(mb_y>=s->mb_height) mb_y= s->mb_height-1;
-
-    if(s->decoding_error==0 && unknown_pos){
-        if(s->data_partitioning && s->pict_type!=B_TYPE)
-                s->decoding_error= DECODING_AC_LOST;
-        else
-                s->decoding_error= DECODING_DESYNC;
-    }
-
-    if(s->decoding_error==DECODING_DESYNC && s->pict_type!=B_TYPE) s->next_p_frame_damaged=1;
-
-    for(i=mb_x + mb_y*s->mb_width; i>=0; i--){
-        if(s->mbintra_table[i]) intra_count++;
-        else                    inter_count++;
-    }
-    
-    if(s->decoding_error==DECODING_AC_LOST){
-        intra_conceal*=2;
-        inter_conceal*=2;
-    }else if(s->decoding_error==DECODING_ACDC_LOST){
-        intra_conceal*=2;
-        inter_conceal*=2;
-    }
-
-    if(unknown_pos && (intra_count<inter_count)){
-        intra_conceal= inter_conceal= s->mb_num; 
-//        printf("%d %d\n",intra_count, inter_count);
-    }
-
-    fprintf(stderr, "concealing errors\n");
-
-    /* for all MBs from the current one back until the last resync marker */
-    for(; mb_y>=0 && mb_y>=s->resync_mb_y; mb_y--){
-        for(; mb_x>=0; mb_x--){
-            uint8_t *dest_y  = s->current_picture[0] + (mb_y * 16*  s->linesize      ) + mb_x * 16;
-            uint8_t *dest_cb = s->current_picture[1] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
-            uint8_t *dest_cr = s->current_picture[2] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
-            int mb_x_backup= s->mb_x; //FIXME pass xy to mpeg_motion
-            int mb_y_backup= s->mb_y;
-            s->mb_x=mb_x;
-            s->mb_y=mb_y;
-            if(s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<intra_conceal){
-                if(s->decoding_error==DECODING_AC_LOST){
-                    remove_ac(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
-//                    printf("remove ac to %d %d\n", mb_x, mb_y);
-                }else{
-                    mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, 
-                                s->last_picture, 0, 0, put_pixels_tab,
-                                0/*mx*/, 0/*my*/, 16);
-                }
-            }
-            else if(!s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<inter_conceal){
-                int mx=0;
-                int my=0;
-
-                if(s->decoding_error!=DECODING_DESYNC){
-                    int xy= mb_x*2+1 + (mb_y*2+1)*(s->mb_width*2+2);
-                    mx= s->motion_val[ xy ][0];
-                    my= s->motion_val[ xy ][1];
-                }
-
-                mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, 
-                            s->last_picture, 0, 0, put_pixels_tab,
-                            mx, my, 16);
-            }
-            s->mb_x= mb_x_backup;
-            s->mb_y= mb_y_backup;
-
-            if(mb_x== s->resync_mb_x && mb_y== s->resync_mb_y) return;
-            if(!s->mbskip_table[mb_x + mb_y*s->mb_width]) mb_dist++;
-        }
-        mb_x=s->mb_width-1;
-    }
-}
-
 AVCodec mpeg1video_encoder = {
     "mpeg1video",
     CODEC_TYPE_VIDEO,
--- a/mpegvideo.h	Fri Oct 11 23:01:16 2002 +0000
+++ b/mpegvideo.h	Sun Oct 13 13:16:04 2002 +0000
@@ -322,16 +322,20 @@
     int last_bits; //temp var used for calculating the above vars
     
     /* error concealment / resync */
+    UINT8 *error_status_table;       /* table of the error status of each MB */ 
+#define VP_START            1        /* current MB is the first after a resync marker */
+#define AC_ERROR            2
+#define DC_ERROR            4
+#define MV_ERROR            8
+#define AC_END              16
+#define DC_END              32
+#define MV_END              64
+//FIXME some prefix?
+    
     int resync_mb_x;                 /* x position of last resync marker */
     int resync_mb_y;                 /* y position of last resync marker */
-    int mb_num_left;                 /* number of MBs left in this video packet */
-    GetBitContext next_resync_gb;    /* starts at the next resync marker */
-    int next_resync_qscale;          /* qscale of next resync marker */
-    int next_resync_pos;             /* bitstream position of next resync marker */
-#define DECODING_AC_LOST -1
-#define DECODING_ACDC_LOST -2
-#define DECODING_DESYNC -3
-    int decoding_error;
+    GetBitContext last_resync_gb;    /* used to serach for the next resync marker */
+    int mb_num_left;                 /* number of MBs left in this video packet (for partitioned Slices only)*/
     int next_p_frame_damaged;        /* set if the next p frame is damaged, to avoid showing trashed b frames */
     int error_resilience;
 
@@ -381,7 +385,8 @@
     int aspected_height;
     int sprite_warping_accuracy;
     int low_latency_sprite;
-    int data_partitioning;
+    int data_partitioning;           /* data partitioning flag from header */
+    int partitioned_frame;           /* is current frame partitioned */
     int rvlc;                        /* reversible vlc */
     int resync_marker;               /* could this stream contain resync markers*/
     int low_delay;                   /* no reordering needed / has no b-frames */
@@ -407,6 +412,10 @@
     UINT8 *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them
     int bitstream_buffer_size;
     
+    /* lavc specific stuff, used to workaround bugs in libavcodec */
+    int ffmpeg_version;
+    int lavc_build;
+    
     /* RV10 specific */
     int rv10_version; /* RV10 version: 0 or 3 */
     int rv10_first_dc_coded[3];
@@ -475,6 +484,12 @@
     
     DCTELEM (*block)[64]; /* points to one of the following blocks */
     DCTELEM blocks[2][6][64] __align8; // for HQ mode we need to keep the best block
+    int (*decode_mb)(struct MpegEncContext *s, DCTELEM block[6][64]); // used by some codecs to avoid a switch()
+#define SLICE_OK         0
+#define SLICE_ERROR     -1
+#define SLICE_END       -2 //end marker found
+#define SLICE_NOEND     -3 //no end marker or error found but mb count exceeded
+    
     void (*dct_unquantize_mpeg1)(struct MpegEncContext *s, 
                            DCTELEM *block, int n, int qscale);
     void (*dct_unquantize_mpeg2)(struct MpegEncContext *s, 
@@ -489,6 +504,7 @@
     void (*idct_add)(UINT8 *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
 } MpegEncContext;
 
+
 int DCT_common_init(MpegEncContext *s);
 int MPV_common_init(MpegEncContext *s);
 void MPV_common_end(MpegEncContext *s);
@@ -512,9 +528,30 @@
 void ff_copy_bits(PutBitContext *pb, UINT8 *src, int length);
 void ff_clean_intra_table_entries(MpegEncContext *s);
 void ff_init_scantable(MpegEncContext *s, ScanTable *st, const UINT8 *src_scantable);
+void ff_error_resilience(MpegEncContext *s);
+void ff_draw_horiz_band(MpegEncContext *s);
 
 extern int ff_bit_exact;
 
+static inline void ff_init_block_index(MpegEncContext *s){
+    s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1 + s->mb_x*2;
+    s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1)     + s->mb_x*2;
+    s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1 + s->mb_x*2;
+    s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2)     + s->mb_x*2;
+    s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1)                    + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
+    s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
+}
+
+static inline void ff_update_block_index(MpegEncContext *s){
+    s->block_index[0]+=2;
+    s->block_index[1]+=2;
+    s->block_index[2]+=2;
+    s->block_index[3]+=2;
+    s->block_index[4]++;
+    s->block_index[5]++;
+}
+
+
 /* motion_est.c */
 void ff_estimate_p_frame_motion(MpegEncContext * s,
                              int mb_x, int mb_y);
@@ -524,6 +561,7 @@
 void ff_fix_long_p_mvs(MpegEncContext * s);
 void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type);
 
+
 /* mpeg12.c */
 extern const INT16 ff_mpeg1_default_intra_matrix[64];
 extern const INT16 ff_mpeg1_default_non_intra_matrix[64];
@@ -535,6 +573,7 @@
                      int motion_x, int motion_y);
 void ff_mpeg1_encode_init(MpegEncContext *s);
 
+
 /* h263enc.c */
 typedef struct RLTable {
     int n; /* number of entries of table_vlc minus 1 */
@@ -567,7 +606,6 @@
 extern UINT8 ff_mpeg4_c_dc_scale_table[32];
 extern const INT16 ff_mpeg4_default_intra_matrix[64];
 extern const INT16 ff_mpeg4_default_non_intra_matrix[64];
-
 void h263_encode_mb(MpegEncContext *s, 
                     DCTELEM block[6][64],
                     int motion_x, int motion_y);
@@ -583,30 +621,32 @@
 void ff_set_mpeg4_time(MpegEncContext * s, int picture_number);
 void mpeg4_encode_picture_header(MpegEncContext *s, int picture_number);
 void h263_encode_init(MpegEncContext *s);
-
 void h263_decode_init_vlc(MpegEncContext *s);
 int h263_decode_picture_header(MpegEncContext *s);
-int h263_decode_gob_header(MpegEncContext *s);
+int ff_h263_decode_gob_header(MpegEncContext *s);
 int mpeg4_decode_picture_header(MpegEncContext * s);
 int intel_h263_decode_picture_header(MpegEncContext *s);
-int h263_decode_mb(MpegEncContext *s,
-                   DCTELEM block[6][64]);
+int ff_h263_decode_mb(MpegEncContext *s,
+                      DCTELEM block[6][64]);
 int h263_get_picture_format(int width, int height);
-int ff_mpeg4_decode_video_packet_header(MpegEncContext *s);
-int ff_mpeg4_resync(MpegEncContext *s);
 void ff_mpeg4_encode_video_packet_header(MpegEncContext *s);
 void ff_mpeg4_clean_buffers(MpegEncContext *s);
 void ff_mpeg4_stuffing(PutBitContext * pbc);
 void ff_mpeg4_init_partitions(MpegEncContext *s);
 void ff_mpeg4_merge_partitions(MpegEncContext *s);
-extern inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, UINT16 **dc_val_ptr, int *dir_ptr);
 void ff_clean_mpeg4_qscales(MpegEncContext *s);
 void ff_clean_h263_qscales(MpegEncContext *s);
+int ff_mpeg4_decode_partitions(MpegEncContext *s);
+int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s);
+int ff_h263_resync(MpegEncContext *s);
+int ff_h263_get_gob_height(MpegEncContext *s);
+
 
 /* rv10.c */
 void rv10_encode_picture_header(MpegEncContext *s, int picture_number);
 int rv_decode_dc(MpegEncContext *s, int n);
 
+
 /* msmpeg4.c */
 void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number);
 void msmpeg4_encode_ext_header(MpegEncContext * s);
@@ -615,13 +655,11 @@
                        int motion_x, int motion_y);
 int msmpeg4_decode_picture_header(MpegEncContext * s);
 int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size);
-int msmpeg4_decode_mb(MpegEncContext *s, 
-                      DCTELEM block[6][64]);
 int ff_msmpeg4_decode_init(MpegEncContext *s);
 void ff_msmpeg4_encode_init(MpegEncContext *s);
 
+
 /* mjpegenc.c */
-
 int mjpeg_init(MpegEncContext *s);
 void mjpeg_close(MpegEncContext *s);
 void mjpeg_encode_mb(MpegEncContext *s, 
@@ -629,6 +667,7 @@
 void mjpeg_picture_header(MpegEncContext *s);
 void mjpeg_picture_trailer(MpegEncContext *s);
 
+
 /* rate control */
 int ff_rate_control_init(MpegEncContext *s);
 float ff_rate_estimate_qscale(MpegEncContext *s);
--- a/msmpeg4.c	Fri Oct 11 23:01:16 2002 +0000
+++ b/msmpeg4.c	Sun Oct 13 13:16:04 2002 +0000
@@ -61,7 +61,8 @@
 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]);
 
 extern UINT32 inverse[256];
 
@@ -504,26 +505,7 @@
     if (s->mb_x == 0) {
         if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
             if(s->msmpeg4_version != 4){
-                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);
+                ff_mpeg4_clean_buffers(s);
             }
             s->first_slice_line = 1;
         } else {
@@ -710,6 +692,10 @@
     a = dc_val[ - 1];
     b = dc_val[ - 1 - wrap];
     c = dc_val[ - wrap];
+    
+    if(s->first_slice_line && (n&2)==0){
+        b=c=1024;
+    }
 
     /* XXX: the following solution consumes divisions, but it does not
        necessitate to modify mpegvideo.c. The problem comes from the
@@ -941,6 +927,7 @@
         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 */
@@ -1170,6 +1157,18 @@
                  &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;
+    }
+    
     return 0;
 }
 
@@ -1444,11 +1443,12 @@
     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)) {
@@ -1530,8 +1530,7 @@
     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;
@@ -1542,10 +1541,8 @@
     if(s->mb_y==0) printf("\n");
 }
 #endif
-    /* special slice handling */
-    handle_slices(s);
 
-    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);
@@ -1866,7 +1863,7 @@
             i-= 192;
             if(i&(~63)){
                 const int left= s->gb.size*8 - get_bits_count(&s->gb);
-                if(((i+192 == 64 && level/qmul==-1) || s->error_resilience<0) && left>=0){
+                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{
--- a/rv10.c	Fri Oct 11 23:01:16 2002 +0000
+++ b/rv10.c	Sun Oct 13 13:16:04 2002 +0000
@@ -365,6 +365,7 @@
 
     s->y_dc_scale_table=
     s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
+    s->progressive_sequence=1;
 
     /* init rv vlc */
     if (!done) {
@@ -393,7 +394,6 @@
 {
     MpegEncContext *s = avctx->priv_data;
     int i, mb_count, mb_pos, left;
-    DCTELEM block[6][64];
 
     init_get_bits(&s->gb, buf, buf_size);
     
@@ -430,47 +430,35 @@
     s->rv10_first_dc_coded[1] = 0;
     s->rv10_first_dc_coded[2] = 0;
 
+    if(s->mb_y==0) s->first_slice_line=1;
+    
     s->block_wrap[0]=
     s->block_wrap[1]=
     s->block_wrap[2]=
     s->block_wrap[3]= s->mb_width*2 + 2;
     s->block_wrap[4]=
     s->block_wrap[5]= s->mb_width + 2;
-    s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1 + s->mb_x*2;
-    s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1)     + s->mb_x*2;
-    s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1 + s->mb_x*2;
-    s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2)     + s->mb_x*2;
-    s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1)                    + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
-    s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2) + s->mb_x;
+    ff_init_block_index(s);
     /* decode each macroblock */
     for(i=0;i<mb_count;i++) {
-        s->block_index[0]+=2;
-        s->block_index[1]+=2;
-        s->block_index[2]+=2;
-        s->block_index[3]+=2;
-        s->block_index[4]++;
-        s->block_index[5]++;
+        ff_update_block_index(s);
 #ifdef DEBUG
         printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
 #endif
         
-        memset(block, 0, sizeof(block));
+        clear_blocks(s->block[0]);
         s->mv_dir = MV_DIR_FORWARD;
         s->mv_type = MV_TYPE_16X16; 
-        if (h263_decode_mb(s, block) < 0) {
+        if (ff_h263_decode_mb(s, s->block) == SLICE_ERROR) {
             fprintf(stderr, "ERROR at MB %d %d\n", s->mb_x, s->mb_y);
             return -1;
         }
-        MPV_decode_mb(s, block);
+        MPV_decode_mb(s, s->block);
         if (++s->mb_x == s->mb_width) {
             s->mb_x = 0;
             s->mb_y++;
-            s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1;
-            s->block_index[1]= s->block_wrap[0]*(s->mb_y*2 + 1);
-            s->block_index[2]= s->block_wrap[0]*(s->mb_y*2 + 2) - 1;
-            s->block_index[3]= s->block_wrap[0]*(s->mb_y*2 + 2);
-            s->block_index[4]= s->block_wrap[4]*(s->mb_y + 1)                    + s->block_wrap[0]*(s->mb_height*2 + 2);
-            s->block_index[5]= s->block_wrap[4]*(s->mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2);
+            ff_init_block_index(s);
+            s->first_slice_line=0;
         }
     }
 
--- a/utils.c	Fri Oct 11 23:01:16 2002 +0000
+++ b/utils.c	Sun Oct 13 13:16:04 2002 +0000
@@ -61,6 +61,8 @@
     s->b_quant_offset=1.25;
     s->i_quant_factor=-0.8;
     s->i_quant_offset=0.0;
+    s->error_concealment= 3;
+    s->workaround_bugs= FF_BUG_AUTODETECT;
 }
 
 /**