X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Ferror_resilience.c;h=a196326e01b8879c6759232dc41fa78801101c2e;hb=31f2616db86fb50174bc053f26c14db7c03e3685;hp=67750cda6932306a4d588b7fdeb0d2dae3e7aba4;hpb=115329f16062074e11ccf3b89ead6176606c9696;p=ffmpeg diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 67750cda693..a196326e01b 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -3,23 +3,25 @@ * * Copyright (c) 2002-2004 Michael Niedermayer * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file error_resilience.c + * @file libavcodec/error_resilience.c * Error resilience / concealment. */ @@ -28,7 +30,6 @@ #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" -#include "common.h" static void decode_mb(MpegEncContext *s){ s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16; @@ -107,9 +108,9 @@ static void filter181(int16_t *data, int width, int height, int stride){ } /** - * guess the dc of blocks which dont have a undamaged dc - * @param w width in 8 pixel blocks - * @param h height in 8 pixel blocks + * guess the dc of blocks which do not have an undamaged dc + * @param w width in 8 pixel blocks + * @param h height in 8 pixel blocks */ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){ int b_x, b_y; @@ -192,12 +193,12 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i /** * simple horizontal deblocking filter used for error resilience - * @param w width in 8 pixel blocks - * @param h height in 8 pixel blocks + * @param w width in 8 pixel blocks + * @param h height in 8 pixel blocks */ static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ int b_x, b_y; - uint8_t *cm = cropTbl + MAX_NEG_CROP; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; for(b_y=0; b_y>1); + d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1); d= FFMAX(d, 0); if(b<0) d= -d; @@ -252,12 +253,12 @@ static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int st /** * simple vertical deblocking filter used for error resilience - * @param w width in 8 pixel blocks - * @param h height in 8 pixel blocks + * @param w width in 8 pixel blocks + * @param h height in 8 pixel blocks */ static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ int b_x, b_y; - uint8_t *cm = cropTbl + MAX_NEG_CROP; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; for(b_y=0; b_y>1); + d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1); d= FFMAX(d, 0); if(b<0) d= -d; @@ -348,7 +349,7 @@ static void guess_mv(MpegEncContext *s){ s->mv_type = MV_TYPE_16X16; s->mb_skipped=0; - s->dsp.clear_blocks(s->block[0]); + s->dsp.clear_blocks(s->block[0]); s->mb_x= mb_x; s->mb_y= mb_y; @@ -476,7 +477,7 @@ int score_sum=0; s->mv_type = MV_TYPE_16X16; s->mb_skipped=0; - s->dsp.clear_blocks(s->block[0]); + s->dsp.clear_blocks(s->block[0]); s->mb_x= mb_x; s->mb_y= mb_y; @@ -493,22 +494,22 @@ int score_sum=0; 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 ]); + score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]); } if(mb_x+1linesize+15]-src[k*s->linesize+16]); + score += FFABS(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 ]); + score += FFABS(src[k-s->linesize ]-src[k ]); } if(mb_y+1linesize*15]-src[k+s->linesize*16]); + score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]); } if(score <= best_score){ // <= will favor the last MV @@ -550,7 +551,7 @@ score_sum+= best_score; 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 + if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction undamaged_count=0; for(i=0; imb_num; i++){ @@ -560,7 +561,11 @@ static int is_intra_more_likely(MpegEncContext *s){ undamaged_count++; } - if(undamaged_count < 5) return 0; //allmost all MBs damaged -> use temporal prediction + if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction + + //prevent dsp.sad() check, that requires access to the image + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE) + return 1; skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs is_intra_likely=0; @@ -578,11 +583,11 @@ static int is_intra_more_likely(MpegEncContext *s){ j++; if((j%skip_amount) != 0) continue; //skip a few to speed things up - if(s->pict_type==I_TYPE){ + if(s->pict_type==FF_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.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16); + is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16); is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16); }else{ if(IS_INTRA(s->current_picture.mb_type[mb_xy])) @@ -597,7 +602,7 @@ static int is_intra_more_likely(MpegEncContext *s){ } void ff_er_frame_start(MpegEncContext *s){ - if(!s->error_resilience) return; + if(!s->error_recognition) 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; @@ -607,16 +612,21 @@ void ff_er_frame_start(MpegEncContext *s){ * 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 + * error of the same type occurred */ 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_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1); + const int end_i = av_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; + if(start_i > end_i || start_xy > end_xy){ + av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n"); + return; + } + + if(!s->error_recognition) return; mask &= ~VP_START; if(status & (AC_ERROR|AC_END)){ @@ -669,7 +679,8 @@ void ff_er_frame_end(MpegEncContext *s){ int size = s->b8_stride * 2 * s->mb_height; Picture *pic= s->current_picture_ptr; - if(!s->error_resilience || s->error_count==0 || + if(!s->error_recognition || s->error_count==0 || s->avctx->lowres || + s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU || s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return; if(s->current_picture.motion_val[0] == NULL){ @@ -745,7 +756,7 @@ void ff_er_frame_end(MpegEncContext *s){ } #endif /* handle missing slices */ - if(s->error_resilience>=4){ + if(s->error_recognition>=4){ int end_ok=1; for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack @@ -758,7 +769,7 @@ void ff_er_frame_end(MpegEncContext *s){ 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 + && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit end_ok=0; } @@ -873,7 +884,7 @@ void ff_er_frame_end(MpegEncContext *s){ s->mv[0][0][1] = s->current_picture.motion_val[0][ mb_x*2 + mb_y*2*s->b8_stride ][1]; } - s->dsp.clear_blocks(s->block[0]); + s->dsp.clear_blocks(s->block[0]); s->mb_x= mb_x; s->mb_y= mb_y; @@ -882,7 +893,7 @@ void ff_er_frame_end(MpegEncContext *s){ } /* guess MVs */ - if(s->pict_type==B_TYPE){ + if(s->pict_type==FF_B_TYPE){ for(mb_y=0; mb_ymb_height; mb_y++){ for(mb_x=0; mb_xmb_width; mb_x++){ int xy= mb_x*2 + mb_y*2*s->b8_stride; @@ -923,10 +934,9 @@ void ff_er_frame_end(MpegEncContext *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 + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) + goto ec_clean; /* fill DC for inter blocks */ for(mb_y=0; mb_ymb_height; mb_y++){ for(mb_x=0; mb_xmb_width; mb_x++){ @@ -1012,15 +1022,13 @@ void ff_er_frame_end(MpegEncContext *s){ v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); } -#ifdef HAVE_XVMC ec_clean: -#endif /* clean a few tables */ for(i=0; imb_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))){ + if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){ s->mbskip_table[mb_xy]=0; } s->mbintra_table[mb_xy]=1;