if(s->motion_val == NULL){
if(s->current_picture.motion_val[0] == NULL){
void ff_er_frame_end(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(!s->error_resilience || s->error_count==0) return;    av_log(s->avctx, AV_LOG_INFO, "concealing errors\n");        if(s->motion_val == NULL){        int size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2);                av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");                s->motion_val= av_mallocz(size * 2 * sizeof(int16_t));    }        if(s->avctx->debug&FF_DEBUG_ER){        for(mb_y=0; mb_y<s->mb_height; mb_y++){            for(mb_x=0; mb_x<s->mb_width; mb_x++){                int status= s->error_status_table[mb_x + mb_y*s->mb_stride];                            av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);             }            av_log(s->avctx, AV_LOG_DEBUG, "\n");        }    }    #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--){            const int mb_xy= s->mb_index2xy[i];            int error= s->error_status_table[mb_xy];                    if(error&(1<<error_type))                end_ok=1;            if(error&(8<<error_type))                end_ok=1;            if(!end_ok)                s->error_status_table[mb_xy]|= 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--){            const int mb_xy= s->mb_index2xy[i];            int error= s->error_status_table[mb_xy];                    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[mb_xy]|= 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            const int mb_xy= s->mb_index2xy[i];            int error1= s->error_status_table[mb_xy  ];            int error2= s->error_status_table[s->mb_index2xy[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[mb_xy]|= 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--){            const int mb_xy= s->mb_index2xy[i];            int error= s->error_status_table[mb_xy];                        if(!s->mbskip_table[mb_xy]) //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[mb_xy]|= 1<<error_type;            }else{                if(distance < threshold)                    s->error_status_table[mb_xy]|= 1<<error_type;            }            if(error&VP_START)                distance= 9999999;        }    }#endif    /* forward mark errors */    error=0;    for(i=0; i<s->mb_num; i++){        const int mb_xy= s->mb_index2xy[i];        int old_error= s->error_status_table[mb_xy];                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[mb_xy]|= error;        }    }#if 1    /* handle not partitioned case */    if(!s->partitioned_frame){        for(i=0; i<s->mb_num; i++){            const int mb_xy= s->mb_index2xy[i];            error= s->error_status_table[mb_xy];            if(error&(AC_ERROR|DC_ERROR|MV_ERROR))                error|= AC_ERROR|DC_ERROR|MV_ERROR;            s->error_status_table[mb_xy]= 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++){        const int mb_xy= s->mb_index2xy[i];        error= s->error_status_table[mb_xy];        if(!((error&DC_ERROR) && (error&MV_ERROR)))            continue;        if(is_intra_likely)            s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;        else            s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;    }        /* handle inter blocks with damaged AC */    for(mb_y=0; mb_y<s->mb_height; mb_y++){        for(mb_x=0; mb_x<s->mb_width; mb_x++){            const int mb_xy= mb_x + mb_y * s->mb_stride;            const int mb_type= s->current_picture.mb_type[mb_xy];            error= s->error_status_table[mb_xy];            if(IS_INTRA(mb_type)) 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(IS_8X8(mb_type)){                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];            }        	    s->dsp.clear_blocks(s->block[0]);            s->mb_x= mb_x;            s->mb_y= mb_y;            decode_mb(s);        }    }    /* guess MVs */    if(s->pict_type==B_TYPE){        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];                const int mb_xy= mb_x + mb_y * s->mb_stride;                const int mb_type= s->current_picture.mb_type[mb_xy];                error= s->error_status_table[mb_xy];                if(IS_INTRA(mb_type)) continue;                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;                }                s->dsp.clear_blocks(s->block[0]);                s->mb_x= mb_x;                s->mb_y= mb_y;                decode_mb(s);            }        }    }else        guess_mv(s);#ifdef HAVE_XVMC    /* the filters below are not XvMC compatible, skip them */    if(s->avctx->xvmc_acceleration) goto ec_clean;#endif    /* fill DC for inter blocks */    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_t *dc_ptr;            uint8_t *dest_y, *dest_cb, *dest_cr;            const int mb_xy= mb_x + mb_y * s->mb_stride;            const int mb_type= s->current_picture.mb_type[mb_xy];                       error= s->error_status_table[mb_xy];            if(IS_INTRA(mb_type) && s->partitioned_frame) continue;//            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?                        dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;            dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;            dest_cr= s->current_picture.data[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 */    for(mb_y=0; mb_y<s->mb_height; mb_y++){        for(mb_x=0; mb_x<s->mb_width; mb_x++){            uint8_t *dest_y, *dest_cb, *dest_cr;            const int mb_xy= mb_x + mb_y * s->mb_stride;            const int mb_type= s->current_picture.mb_type[mb_xy];            error= s->error_status_table[mb_xy];            if(IS_INTER(mb_type)) continue;            if(!(error&AC_ERROR)) continue;              //undamaged                        dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;            dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;            dest_cr= s->current_picture.data[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.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);        h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);        h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);        /* filter vertical block boundaries */        v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);        v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);        v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);    }#ifdef HAVE_XVMCec_clean:#endif    /* clean a few tables */    for(i=0; i<s->mb_num; i++){        const int mb_xy= s->mb_index2xy[i];        int error= s->error_status_table[mb_xy];                if(s->pict_type!=B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){            s->mbskip_table[mb_xy]=0;        }        s->mbintra_table[mb_xy]=1;    }    }