📄 error_resilience.c
字号:
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; 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; decode_mb(s); } } 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 mb_x, mb_y;int score_sum=0; 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 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]; if((mb_x^mb_y^pass)&1) continue; if(fixed[mb_xy]==MV_FROZEN) continue; assert(!IS_INTRA(s->current_picture.mb_type[mb_xy])); assert(s->last_picture_ptr && s->last_picture_ptr->data[0]); j=0; if(mb_x>0 && fixed[mb_xy-1 ]==MV_FROZEN) j=1; if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_FROZEN) j=1; if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1; if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1; if(j==0) continue; j=0; if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1; if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1; if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1; if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1; if(j==0 && pass>1) continue; none_left=0; if(mb_x>0 && fixed[mb_xy-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[mb_xy+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[mb_xy-mb_stride]){ 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[mb_xy+mb_stride]){ 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_t *src= s->current_picture.data[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]; decode_mb(s); if(mb_x>0 && fixed[mb_xy-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[mb_xy+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[mb_xy-mb_stride]){ int k; for(k=0; k<16; k++) score += ABS(src[k-s->linesize ]-src[k ]); } if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){ 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]; decode_mb(s); if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){ fixed[mb_xy]=MV_CHANGED; changed++; }else fixed[mb_xy]=MV_UNCHANGED; } }// printf(".%d/%d", changed, score_sum); fflush(stdout); } if(none_left) return; for(i=0; i<s->mb_num; i++){ int mb_xy= s->mb_index2xy[i]; if(fixed[mb_xy]) fixed[mb_xy]=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; if(s->last_picture_ptr==NULL) return 1; //no previous frame available -> use spatial prediction undamaged_count=0; for(i=0; i<s->mb_num; i++){ const int mb_xy= s->mb_index2xy[i]; const int error= s->error_status_table[mb_xy]; 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; 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; const int mb_xy= mb_x + mb_y*s->mb_stride; error= s->error_status_table[mb_xy]; 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_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; uint8_t *last_mb_ptr= s->last_picture.data [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(IS_INTRA(s->current_picture.mb_type[mb_xy])) 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_er_frame_start(MpegEncContext *s){ if(!s->error_resilience) return; memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_stride*s->mb_height*sizeof(uint8_t)); s->error_count= 3*s->mb_num;}/** * adds a slice. * @param endx x component of the last macroblock, can be -1 for the last of the previous line * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or * error of the same type occured */void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){ const int start_i= clip(startx + starty * s->mb_width , 0, s->mb_num-1); const int end_i = clip(endx + endy * s->mb_width , 0, s->mb_num); const int start_xy= s->mb_index2xy[start_i]; const int end_xy = s->mb_index2xy[end_i]; int mask= -1; if(!s->error_resilience) return; mask &= ~VP_START; if(status & (AC_ERROR|AC_END)){ mask &= ~(AC_ERROR|AC_END); s->error_count -= end_i - start_i + 1; } if(status & (DC_ERROR|DC_END)){ mask &= ~(DC_ERROR|DC_END); s->error_count -= end_i - start_i + 1; } if(status & (MV_ERROR|MV_END)){ mask &= ~(MV_ERROR|MV_END); s->error_count -= end_i - start_i + 1; } if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX; if(mask == ~0x7F){ memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t)); }else{ int i; for(i=start_xy; i<end_xy; i++){ s->error_status_table[ i ] &= mask; } } if(end_i == s->mb_num) s->error_count= INT_MAX; else{ s->error_status_table[end_xy] &= mask; s->error_status_table[end_xy] |= status; } s->error_status_table[start_xy] |= VP_START; if(start_xy > 0){ int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ]; prev_status &= ~ VP_START; if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX; }}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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -