diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2003-03-20 01:00:57 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2003-03-20 01:00:57 +0000 |
commit | 46b4feec06035d3507db257eecc762d66e0dd7b6 (patch) | |
tree | 4ac6d20337421b8d032213ec6a6e12b3c6f3122d /libavcodec | |
parent | 5031c5b47bfcd1b1a0684b0993069747f5c9dc4e (diff) | |
download | ffmpeg-46b4feec06035d3507db257eecc762d66e0dd7b6.tar.gz |
error resilience cleanup (its faster too...)
Originally committed as revision 1692 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/avcodec.h | 1 | ||||
-rw-r--r-- | libavcodec/error_resilience.c | 82 | ||||
-rw-r--r-- | libavcodec/h263.c | 32 | ||||
-rw-r--r-- | libavcodec/h263dec.c | 56 | ||||
-rw-r--r-- | libavcodec/mpegvideo.h | 7 | ||||
-rw-r--r-- | libavcodec/msmpeg4.c | 4 | ||||
-rw-r--r-- | libavcodec/wmv2.c | 2 |
7 files changed, 113 insertions, 71 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 42d69c9912..06cd96df8d 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -909,6 +909,7 @@ typedef struct AVCodecContext { #define FF_DEBUG_SKIP 0x00000080 #define FF_DEBUG_STARTCODE 0x00000100 #define FF_DEBUG_PTS 0x00000200 +#define FF_DEBUG_ER 0x00000400 /** * error. diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index bf399634e6..77488cd589 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" +#include "common.h" /** * replaces the current MB with a flat dc only version. @@ -580,12 +581,91 @@ static int is_intra_more_likely(MpegEncContext *s){ return is_intra_likely > 0; } -void ff_error_resilience(MpegEncContext *s){ +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_num*sizeof(uint8_t)); +} + +/** + * 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_xy= clip(startx + starty * s->mb_width, 0, s->mb_num-1); + const int end_xy = clip(endx + endy * s->mb_width, 0, s->mb_num); + const int mb_count= end_xy - start_xy; + int mask= -1; + + if(!s->error_resilience) return; + + mask &= ~VP_START; + if(status & (AC_ERROR|AC_END)) mask &= ~(AC_ERROR|AC_END); + if(status & (DC_ERROR|DC_END)) mask &= ~(DC_ERROR|DC_END); + if(status & (MV_ERROR|MV_END)) mask &= ~(MV_ERROR|MV_END); + + if(mask == ~0x7F){ + memset(&s->error_status_table[start_xy], 0, mb_count * sizeof(uint8_t)); + }else{ + int i; + for(i=start_xy; i<end_xy; i++){ + s->error_status_table[i] &= mask; + } + } + + s->error_status_table[start_xy] |= VP_START; + + if(end_xy < s->mb_num){ + s->error_status_table[end_xy] &= mask; + s->error_status_table[end_xy] |= status; + } +} + +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; + int num_end_markers=0; + + if(!s->error_resilience) return; + + error=0; + for(i=0; i<s->mb_num; i++){ + int status= s->error_status_table[i]; + + if(status==0) continue; + + if(status&(DC_ERROR|AC_ERROR|MV_ERROR)) + error=1; + if(status&VP_START){ + if(num_end_markers) + error=1; + num_end_markers=3; + } + if(status&AC_END) + num_end_markers--; + if(status&DC_END) + num_end_markers--; + if(status&MV_END) + num_end_markers--; + } + if(num_end_markers==0 && error==0) + return; + + fprintf(stderr, "concealing errors\n"); + + if(s->avctx->debug&FF_DEBUG_ER){ + for(i=0; i<s->mb_num; i++){ + int status= s->error_status_table[i]; + + if(i%s->mb_width == 0) printf("\n"); + printf("%2X ", status); + } + } #if 1 /* handle overlapping slices */ diff --git a/libavcodec/h263.c b/libavcodec/h263.c index 2baed96a8d..b9b94efc9c 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -2760,8 +2760,6 @@ static int mpeg4_decode_partition_a(MpegEncContext *s){ if(dc_pred_dir) dir|=1; } s->pred_dir_table[xy]= dir; - - s->error_status_table[xy]= AC_ERROR; }else{ /* P/S_TYPE */ int mx, my, pred_x, pred_y, bits; int16_t * const mot_val= s->motion_val[s->block_index[0]]; @@ -2790,8 +2788,6 @@ static int mpeg4_decode_partition_a(MpegEncContext *s){ if(s->mbintra_table[xy]) ff_clean_intra_table_entries(s); - - s->error_status_table[xy]= AC_ERROR; continue; } cbpc = get_vlc2(&s->gb, inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); @@ -2815,7 +2811,6 @@ static int mpeg4_decode_partition_a(MpegEncContext *s){ mot_val[0+stride]= mot_val[2+stride]= 0; mot_val[1 ]= mot_val[3 ]= mot_val[1+stride]= mot_val[3+stride]= 0; - s->error_status_table[xy]= DC_ERROR|AC_ERROR; }else{ if(s->mbintra_table[xy]) ff_clean_intra_table_entries(s); @@ -2864,7 +2859,6 @@ static int mpeg4_decode_partition_a(MpegEncContext *s){ mot_val[1] = my; } } - s->error_status_table[xy]= AC_ERROR; } } } @@ -2933,7 +2927,6 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count){ s->cbp_table[xy]&= 3; //remove dquant s->cbp_table[xy]|= cbpy<<2; s->pred_dir_table[xy]= dir | (ac_pred<<7); - s->error_status_table[xy]&= ~DC_ERROR; }else if(s->mb_type[xy]&MB_TYPE_SKIPED){ s->current_picture.qscale_table[xy]= s->qscale; s->cbp_table[xy]= 0; @@ -2968,13 +2961,18 @@ static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count){ int ff_mpeg4_decode_partitions(MpegEncContext *s) { int mb_num; + const int part_a_error= s->pict_type==I_TYPE ? (DC_ERROR|MV_ERROR) : MV_ERROR; + const int part_a_end = s->pict_type==I_TYPE ? (DC_END |MV_END) : MV_END; mb_num= mpeg4_decode_partition_a(s); - if(mb_num<0) + if(mb_num<0){ + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error); return -1; + } if(s->resync_mb_x + s->resync_mb_y*s->mb_width + mb_num > s->mb_num){ fprintf(stderr, "slice below monitor ...\n"); + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error); return -1; } @@ -2984,21 +2982,23 @@ int ff_mpeg4_decode_partitions(MpegEncContext *s) if(get_bits(&s->gb, 19)!=DC_MARKER){ fprintf(stderr, "marker missing after first I partition at %d %d\n", s->mb_x, s->mb_y); return -1; - }else - s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= MV_END|DC_END; + } }else{ if(get_bits(&s->gb, 17)!=MOTION_MARKER){ fprintf(stderr, "marker missing after first P partition at %d %d\n", s->mb_x, s->mb_y); return -1; - }else - s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= MV_END; + } } + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, part_a_end); if( mpeg4_decode_partition_b(s, mb_num) < 0){ + if(s->pict_type==P_TYPE) + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, DC_ERROR); return -1; + }else{ + if(s->pict_type==P_TYPE) + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, DC_END); } - - s->error_status_table[s->mb_x + s->mb_y*s->mb_width-1]|= DC_END; return 0; } @@ -3071,8 +3071,6 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, DCTELEM block[6][64]) } } - s->error_status_table[xy]&= ~AC_ERROR; - /* per-MB end of slice check */ if(--s->mb_num_left <= 0){ @@ -3096,8 +3094,6 @@ int ff_h263_decode_mb(MpegEncContext *s, int16_t *mot_val; static int8_t quant_tab[4] = { -1, -2, 1, 2 }; - s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0; - if(s->mb_x==0) PRINT_MB_TYPE("\n"); if (s->pict_type == P_TYPE || s->pict_type==S_TYPE) { diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index bab06c9bca..9c2d26b9b6 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -144,6 +144,7 @@ static int get_consumed_bytes(MpegEncContext *s, int buf_size){ } static int decode_slice(MpegEncContext *s){ + const int part_mask= s->partitioned_frame ? (AC_END|AC_ERROR) : 0x7F; s->last_resync_gb= s->gb; s->first_slice_line= 1; @@ -174,8 +175,8 @@ static int decode_slice(MpegEncContext *s){ /* per-row end of slice checks */ if(s->msmpeg4_version){ if(s->resync_mb_y + s->slice_height == s->mb_y){ - const int xy= s->mb_x + s->mb_y*s->mb_width; - s->error_status_table[xy-1]|= AC_END|DC_END|MV_END; + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END); + return 0; } } @@ -211,9 +212,7 @@ static int decode_slice(MpegEncContext *s){ const int xy= s->mb_x + s->mb_y*s->mb_width; if(ret==SLICE_END){ //printf("%d %d %d %06X\n", s->mb_x, s->mb_y, s->gb.size*8 - get_bits_count(&s->gb), show_bits(&s->gb, 24)); - s->error_status_table[xy]|= AC_END; - if(!s->partitioned_frame) - s->error_status_table[xy]|= MV_END|DC_END; + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask); s->padding_bug_score--; @@ -225,12 +224,11 @@ static int decode_slice(MpegEncContext *s){ return 0; }else if(ret==SLICE_NOEND){ fprintf(stderr,"Slice mismatch at MB: %d\n", xy); + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask); return -1; } fprintf(stderr,"Error at MB: %d\n", xy); - s->error_status_table[xy]|= AC_ERROR; - if(!s->partitioned_frame) - s->error_status_table[xy]|= DC_ERROR|MV_ERROR; + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask); return -1; } @@ -290,7 +288,7 @@ static int decode_slice(MpegEncContext *s){ else if(left<0){ fprintf(stderr, "overreading %d bits\n", -left); }else - s->error_status_table[s->mb_num-1]|= AC_END|MV_END|DC_END; + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END); return 0; } @@ -298,6 +296,9 @@ static int decode_slice(MpegEncContext *s){ fprintf(stderr, "slice end not reached but screenspace end (%d left %06X)\n", s->gb.size_in_bits - get_bits_count(&s->gb), show_bits(&s->gb, 24)); + + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask); + return -1; } @@ -596,7 +597,6 @@ retry: || ABS(new_aspect - avctx->aspect_ratio) > 0.001) { /* H.263 could change picture size any time */ MPV_common_end(s); - s->context_initialized=0; } if (!s->context_initialized) { avctx->width = s->width; @@ -641,8 +641,7 @@ retry: printf("qscale=%d\n", s->qscale); #endif - if(s->error_resilience) - memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_num*sizeof(uint8_t)); + ff_er_frame_start(s); /* decode each macroblock */ s->block_wrap[0]= @@ -655,7 +654,6 @@ retry: s->mb_y=0; decode_slice(s); - s->error_status_table[0]|= VP_START; while(s->mb_y<s->mb_height && s->gb.size_in_bits - get_bits_count(&s->gb)>16){ if(s->msmpeg4_version){ if(s->mb_x!=0 || (s->mb_y%s->slice_height)!=0) @@ -669,8 +667,6 @@ retry: ff_mpeg4_clean_buffers(s); decode_slice(s); - - s->error_status_table[s->resync_mb_x + s->resync_mb_y*s->mb_width]|= VP_START; } if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE) @@ -699,35 +695,7 @@ retry: } } - if(s->error_resilience){ - int error=0, num_end_markers=0; - for(i=0; i<s->mb_num; i++){ - int status= s->error_status_table[i]; -#if 0 - if(i%s->mb_width == 0) printf("\n"); - printf("%2X ", status); -#endif - if(status==0) continue; - - if(status&(DC_ERROR|AC_ERROR|MV_ERROR)) - error=1; - if(status&VP_START){ - if(num_end_markers) - error=1; - num_end_markers=3; - } - if(status&AC_END) - num_end_markers--; - if(status&DC_END) - num_end_markers--; - if(status&MV_END) - num_end_markers--; - } - if(num_end_markers || error){ - fprintf(stderr, "concealing errors\n"); - ff_error_resilience(s); - } - } + ff_er_frame_end(s); MPV_frame_end(s); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index bd1c257b7a..83ae0f1697 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -629,17 +629,20 @@ void MPV_common_init_armv4l(MpegEncContext *s); void MPV_common_init_ppc(MpegEncContext *s); #endif extern void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w); -void ff_conceal_past_errors(MpegEncContext *s, int conceal_all); void ff_copy_bits(PutBitContext *pb, uint8_t *src, int length); void ff_clean_intra_table_entries(MpegEncContext *s); void ff_init_scantable(MpegEncContext *s, ScanTable *st, const uint8_t *src_scantable); -void ff_error_resilience(MpegEncContext *s); void ff_draw_horiz_band(MpegEncContext *s, int y, int h); void ff_emulated_edge_mc(MpegEncContext *s, uint8_t *src, int linesize, int block_w, int block_h, int src_x, int src_y, int w, int h); char ff_get_pict_type_char(int pict_type); int ff_combine_frame( MpegEncContext *s, int next, uint8_t **buf, int *buf_size); +void ff_er_frame_start(MpegEncContext *s); +void ff_er_frame_end(MpegEncContext *s); +void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status); + + extern enum PixelFormat ff_yuv420p_list[2]; static inline void ff_init_block_index(MpegEncContext *s){ diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index 47f8d2bec6..4bac6d3b74 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -1486,8 +1486,6 @@ static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) { int cbp, code, i; - s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0; - if (s->pict_type == P_TYPE) { if (s->use_skip_mb_code) { if (get_bits1(&s->gb)) { @@ -1581,8 +1579,6 @@ if(s->mb_x==0){ } #endif - s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0; - if (s->pict_type == P_TYPE) { set_stat(ST_INTER_MB); if (s->use_skip_mb_code) { diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index 96b6c8ca3b..99780f6f41 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -710,8 +710,6 @@ static int wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) if(w->j_type) return 0; - s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0; - if (s->pict_type == P_TYPE) { if(s->mb_type[s->mb_y * s->mb_width + s->mb_x]&MB_TYPE_SKIPED){ /* skip mb */ |