diff error_resilience.c @ 1144:21c85c4ab2f0 libavcodec

error resilience cleanup (its faster too...)
author michaelni
date Thu, 20 Mar 2003 01:00:57 +0000
parents e10e841c9bf0
children d2fd27d01df8
line wrap: on
line diff
--- a/error_resilience.c	Tue Mar 18 20:08:57 2003 +0000
+++ b/error_resilience.c	Thu Mar 20 01:00:57 2003 +0000
@@ -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 @@
     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 */