aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2003-03-20 01:00:57 +0000
committerMichael Niedermayer <michaelni@gmx.at>2003-03-20 01:00:57 +0000
commit46b4feec06035d3507db257eecc762d66e0dd7b6 (patch)
tree4ac6d20337421b8d032213ec6a6e12b3c6f3122d /libavcodec
parent5031c5b47bfcd1b1a0684b0993069747f5c9dc4e (diff)
downloadffmpeg-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.h1
-rw-r--r--libavcodec/error_resilience.c82
-rw-r--r--libavcodec/h263.c32
-rw-r--r--libavcodec/h263dec.c56
-rw-r--r--libavcodec/mpegvideo.h7
-rw-r--r--libavcodec/msmpeg4.c4
-rw-r--r--libavcodec/wmv2.c2
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 */