📄 error_resilience.c
字号:
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; 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; 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= FFMAX(max_x, mv_predictor[j][0]); max_y= FFMAX(max_y, mv_predictor[j][1]); min_x= FFMIN(min_x, mv_predictor[j][0]); min_y= FFMIN(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; s->dsp.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= FFMAX(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 += s->dsp.pix_abs16x16(last_mb_ptr, mb_ptr , s->linesize); is_intra_likely -= s->dsp.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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -