changeset 454:eda22d628b2d libavcodec

error concealment / error resilience merging s->first_gob_line & s->first_slice_line
author michaelni
date Sun, 02 Jun 2002 12:16:28 +0000
parents 69876443a723
children 7f2d2be2aee9
files h263dec.c
diffstat 1 files changed, 128 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/h263dec.c	Sun Jun 02 12:15:17 2002 +0000
+++ b/h263dec.c	Sun Jun 02 12:16:28 2002 +0000
@@ -49,7 +49,7 @@
     switch(avctx->codec->id) {
     case CODEC_ID_H263:
         s->gob_number = 0;
-        s->first_gob_line = 0;
+        s->first_slice_line = 0;
         break;
     case CODEC_ID_MPEG4:
         s->time_increment_bits = 4; /* default value for broken headers */
@@ -122,7 +122,9 @@
 #endif
 
     s->hurry_up= avctx->hurry_up;
-    
+    s->error_resilience= avctx->error_resilience;
+    s->workaround_bugs= avctx->workaround_bugs;
+
     /* no supplementary picture */
     if (buf_size == 0) {
         *data_size = 0;
@@ -165,19 +167,33 @@
     }
 
     if(ret==FRAME_SKIPED) return 0;
+    /* skip if the header was thrashed */
     if (ret < 0)
         return -1;
     /* skip b frames if we dont have reference frames */
     if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return 0;
     /* skip b frames if we are in a hurry */
     if(s->hurry_up && s->pict_type==B_TYPE) return 0;
-        
+    
+    if(s->next_p_frame_damaged){
+        if(s->pict_type==B_TYPE)
+            return 0;
+        else
+            s->next_p_frame_damaged=0;
+    }
+
     MPV_frame_start(s);
 
 #ifdef DEBUG
     printf("qscale=%d\n", s->qscale);
 #endif
 
+    /* init resync/ error resilience specific variables */
+    s->next_resync_qscale= s->qscale;
+    s->next_resync_gb= s->gb;
+    if(s->resync_marker) s->mb_num_left= 0;
+    else                 s->mb_num_left= s->mb_num;
+
     /* decode each macroblock */
     s->block_wrap[0]=
     s->block_wrap[1]=
@@ -190,7 +206,13 @@
         /* FIXME: In the future H.263+ will have intra prediction */
         /* and we are gonna need another way to detect MPEG4      */
         if (s->mb_y && !s->h263_pred) {
-            s->first_gob_line = h263_decode_gob_header(s);
+            s->first_slice_line = h263_decode_gob_header(s);
+        }
+        
+        if(s->msmpeg4_version==1){
+            s->last_dc[0]=
+            s->last_dc[1]=
+            s->last_dc[2]= 128;
         }
 
         s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1;
@@ -209,9 +231,40 @@
 #ifdef DEBUG
             printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
 #endif
+
+            if(s->resync_marker){
+                if(s->mb_num_left<=0){
+                    /* except the first block */
+                    if(s->mb_x!=0 || s->mb_y!=0){
+                        /* did we miss the next resync marker without noticing an error yet */
+                        if(((get_bits_count(&s->gb)+8)&(~7)) != s->next_resync_pos && s->decoding_error==0){
+                            fprintf(stderr, "slice end missmatch x:%d y:%d %d %d\n", 
+                                    s->mb_x, s->mb_y, get_bits_count(&s->gb), s->next_resync_pos);
+                            ff_conceal_past_errors(s, 1);
+                        }
+                    }
+                    s->qscale= s->next_resync_qscale;
+                    s->gb= s->next_resync_gb;
+                    s->resync_mb_x= s->mb_x; //we know that the marker is here cuz mb_num_left was the distance to it
+                    s->resync_mb_y= s->mb_y;
+                    s->first_slice_line=1;
+
+                    if(s->codec_id==CODEC_ID_MPEG4){
+                        ff_mpeg4_clean_buffers(s);
+                        ff_mpeg4_resync(s);
+                    }
+                }
+
+                if(   s->resync_mb_x==s->mb_x 
+                   && s->resync_mb_y==s->mb_y && s->decoding_error!=0){
+                    fprintf(stderr, "resynced at %d %d\n", s->mb_x, s->mb_y);
+                    s->decoding_error= 0;
+                }
+            }
+
             //fprintf(stderr,"\nFrame: %d\tMB: %d",avctx->frame_number, (s->mb_y * s->mb_width) + s->mb_x);
             /* DCT & quantize */
-            if (s->h263_pred && s->msmpeg4_version!=2) {
+            if (s->h263_pred && !(s->msmpeg4_version==1 || s->msmpeg4_version==2)) {
                 /* old ffmpeg encoded msmpeg4v3 workaround */
                 if(s->workaround_bugs==1 && s->msmpeg4_version==3) 
                     ff_old_msmpeg4_dc_scale(s);
@@ -222,22 +275,48 @@
                 s->y_dc_scale = 8;
                 s->c_dc_scale = 8;
             }
-            clear_blocks(s->block[0]);
+
+            if(s->decoding_error!=DECODING_DESYNC){
+                int last_error= s->decoding_error;
+                clear_blocks(s->block[0]);
             
-            s->mv_dir = MV_DIR_FORWARD;
-            s->mv_type = MV_TYPE_16X16; 
-            if (s->h263_msmpeg4) {
-		if (msmpeg4_decode_mb(s, s->block) < 0) {
-		    fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
-                    return -1;
-		}
-            } else {
-                if (h263_decode_mb(s, s->block) < 0) {
-                    fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
-                    return -1;
+                s->mv_dir = MV_DIR_FORWARD;
+                s->mv_type = MV_TYPE_16X16;
+                if (s->h263_msmpeg4) {
+                    if (msmpeg4_decode_mb(s, s->block) < 0) {
+                        fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
+                        s->decoding_error=DECODING_DESYNC;
+                    }
+                } else {
+                    if (h263_decode_mb(s, s->block) < 0) {
+                        fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
+                        s->decoding_error=DECODING_DESYNC;
+                    }
+                }
+
+                if(s->decoding_error!=last_error){
+                    ff_conceal_past_errors(s, 0);
                 }
             }
+
+            /* conceal errors */
+            if(    s->decoding_error==DECODING_DESYNC
+               || (s->decoding_error==DECODING_ACDC_LOST && s->mb_intra)){
+                s->mv_dir = MV_DIR_FORWARD;
+                s->mv_type = MV_TYPE_16X16;
+                s->mb_skiped=0;
+                s->mb_intra=0;
+                s->mv[0][0][0]=0; //FIXME this is not optimal 
+                s->mv[0][0][1]=0;
+                clear_blocks(s->block[0]);
+            }else if(s->decoding_error && !s->mb_intra){
+                clear_blocks(s->block[0]);
+            }
+            //FIXME remove AC for intra
+                        
             MPV_decode_mb(s, s->block);
+
+            s->mb_num_left--;            
         }
         if (    avctx->draw_horiz_band 
             && (s->num_available_buffers>=1 || (!s->has_b_frames)) ) {
@@ -267,11 +346,40 @@
     
     /* divx 5.01+ bistream reorder stuff */
     if(s->codec_id==CODEC_ID_MPEG4 && s->bitstream_buffer_size==0){
-        int current_pos= get_bits_count(&s->gb)/8;
+        int current_pos= get_bits_count(&s->gb)>>3;
+
         if(   buf_size - current_pos > 5 
            && buf_size - current_pos < BITSTREAM_BUFFER_SIZE){
-            memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos);
-            s->bitstream_buffer_size= buf_size - current_pos;
+            int i;
+            int startcode_found=0;
+            for(i=current_pos; i<buf_size; i++){
+                if(buf[i]==0 && buf[i+1]==0 && buf[i+2]==1 && buf[i+3]==0xB6){
+                    startcode_found=1;
+                    break;
+                }
+            }
+            if(startcode_found){
+                memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos);
+                s->bitstream_buffer_size= buf_size - current_pos;
+            }
+        }
+    }
+
+    if(s->bitstream_buffer_size==0 && s->error_resilience>0){
+        int left= s->gb.size*8 - get_bits_count(&s->gb);
+        int max_extra=8;
+        
+        if(s->codec_id==CODEC_ID_MPEG4) max_extra+=32;
+
+        if(left>max_extra){
+            fprintf(stderr, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24));
+            if(s->decoding_error==0)
+                ff_conceal_past_errors(s, 1);
+        }
+        if(left<0){
+            fprintf(stderr, "overreading %d bits\n", -left);
+            if(s->decoding_error==0)
+                ff_conceal_past_errors(s, 1);
         }
     }