X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Ferror_resilience.c;h=dc015b9f6af63beb30528b32044ca0d3e9b7a51e;hb=080ce9071dc1d05fcfd40629eeb6d4a163abd840;hp=c0c786f8e32b766ea627a9e578a7eb1170e0e113;hpb=686c781766e92d2798714a668b172a4bdf33a91f;p=ffmpeg diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index c0c786f8e32..dc015b9f6af 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -21,7 +21,7 @@ */ /** - * @file libavcodec/error_resilience.c + * @file * Error resilience / concealment. */ @@ -31,6 +31,7 @@ #include "dsputil.h" #include "mpegvideo.h" #include "h264.h" +#include "rectangle.h" /* * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264) @@ -38,12 +39,27 @@ */ #undef mb_intra -static void decode_mb(MpegEncContext *s){ +static void decode_mb(MpegEncContext *s, int ref){ s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16; s->dest[1] = s->current_picture.data[1] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift); s->dest[2] = s->current_picture.data[2] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift); + if(CONFIG_H264_DECODER && s->codec_id == CODEC_ID_H264){ + H264Context *h= (void*)s; + h->mb_xy= s->mb_x + s->mb_y*s->mb_stride; + memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache)); + assert(ref>=0); + if(ref >= h->ref_count[0]) //FIXME it is posible albeit uncommon that slice references differ between slices, we take the easy approuch and ignore it for now. If this turns out to have any relevance in practice then correct remapping should be added + ref=0; + fill_rectangle(&s->current_picture.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1); + fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); + fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4); + assert(!FRAME_MBAFF); + ff_h264_hl_decode_mb(h); + }else{ + assert(ref==0); MPV_decode_mb(s, s->block); + } } /** @@ -386,7 +402,7 @@ static void guess_mv(MpegEncContext *s){ s->mb_y= mb_y; s->mv[0][0][0]= 0; s->mv[0][0][1]= 0; - decode_mb(s); + decode_mb(s, 0); } } return; @@ -406,6 +422,7 @@ int score_sum=0; for(mb_x=0; mb_xmb_width; mb_x++){ const int mb_xy= mb_x + mb_y*s->mb_stride; int mv_predictor[8][2]={{0}}; + int ref[8]={0}; int pred_count=0; int j; int best_score=256*256*256*64; @@ -439,60 +456,73 @@ int score_sum=0; if(mb_x>0 && fixed[mb_xy-1]){ mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0]; mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1]; + ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-1)]; pred_count++; } if(mb_x+1current_picture.motion_val[0][mot_index + mot_step][0]; mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1]; + ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+1)]; pred_count++; } if(mb_y>0 && fixed[mb_xy-mb_stride]){ mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0]; mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1]; + ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)]; pred_count++; } if(mb_y+1current_picture.motion_val[0][mot_index + mot_stride*mot_step][0]; mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1]; + ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)]; 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; + int sum_x=0, sum_y=0, sum_r=0; + int max_x, max_y, min_x, min_y, max_r, min_r; for(j=0; j=3){ - min_y= min_x= 99999; - max_y= max_x=-99999; + min_y= min_x= min_r= 99999; + max_y= max_x= max_r=-99999; }else{ - min_x=min_y=max_x=max_y=0; + min_x=min_y=max_x=max_y=min_r=max_r=0; } for(j=0; jcurrent_picture.motion_val[0][mot_index][0]; mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1]; + ref [pred_count] = s->current_picture.ref_index[0][4*mb_xy]; pred_count++; s->mv_dir = MV_DIR_FORWARD; @@ -519,7 +550,10 @@ int score_sum=0; s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0]; s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1]; - decode_mb(s); + if(ref[j]<0) //predictor intra or otherwise not available + continue; + + decode_mb(s, ref[j]); if(mb_x>0 && fixed[mb_xy-1]){ int k; @@ -557,7 +591,7 @@ score_sum+= best_score; s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1]; } - decode_mb(s); + decode_mb(s, ref[best_pred]); if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){ @@ -596,6 +630,12 @@ static int is_intra_more_likely(MpegEncContext *s){ undamaged_count++; } + if(s->codec_id == CODEC_ID_H264){ + H264Context *h= (void*)s; + if(h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0]) + return 1; + } + if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction //prevent dsp.sad() check, that requires access to the image @@ -735,11 +775,6 @@ void ff_er_frame_end(MpegEncContext *s){ s->current_picture= *s->current_picture_ptr; } - for(i=0; i<2; i++){ - if(pic->ref_index[i]) - memset(pic->ref_index[i], 0, size * sizeof(uint8_t)); - } - if(s->avctx->debug&FF_DEBUG_ER){ for(mb_y=0; mb_ymb_height; mb_y++){ for(mb_x=0; mb_xmb_width; mb_x++){ @@ -937,7 +972,7 @@ void ff_er_frame_end(MpegEncContext *s){ s->mb_x= mb_x; s->mb_y= mb_y; - decode_mb(s); + decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/); } } @@ -979,7 +1014,7 @@ void ff_er_frame_end(MpegEncContext *s){ s->dsp.clear_blocks(s->block[0]); s->mb_x= mb_x; s->mb_y= mb_y; - decode_mb(s); + decode_mb(s, 0); } } }else