static void guess_mv(MpegEncContext *s){
uint8_t fixed[s->mb_stride * s->mb_height];
#define MV_FROZEN 3
#define MV_CHANGED 2
#define MV_UNCHANGED 1
const int mb_stride = s->mb_stride;
const int mb_width = s->mb_width;
const int mb_height= s->mb_height;
int i, depth, num_avail;
int mb_x, mb_y, mot_step, mot_stride;
set_mv_strides(s, &mot_step, &mot_stride); //!< mot_step = 4, mot_stride = s->b4_stride
num_avail=0;
for(i=0; i<s->mb_num; i++){
const int mb_xy= s->mb_index2xy[ i ];
int f=0;
int error= s->error_status_table[mb_xy];
if(IS_INTRA(s->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check
if(!(error&MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV
fixed[mb_xy]= f;
if(f==MV_FROZEN)
num_avail++;
}
if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){ //!< 不使用错误隐藏或者宏块可用数少
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;
if(IS_INTRA(s->current_picture.mb_type[mb_xy])) continue;
if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue; //!< mv ok
s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
s->mb_intra=0;
s->mv_type = MV_TYPE_16X16;
s->mb_skipped=0;
s->dsp.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;
decode_mb(s, 0);
}
}
return;
}
for(depth=0;; depth++){
int changed, pass, none_left;
none_left=1;
changed=1;
for(pass=0; (changed || pass<2) && pass<10; pass++){ //!< pass和changed用于控制迭代次数:changed || pass < 2,如果经历了pass=0
int mb_x, mb_y; //!< 和pass=1两次迭代后(刚好做完一整帧的错误隐藏),changed仍为0,即实际没有宏块的mv被修正,
int score_sum=0; //!< 则没有继续下一轮迭代的必要;pass < 10,控制总迭代次数不超过10次
changed=0;
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;
int mv_predictor[8][2]={
{0}};
int re