+static void remove_ac(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
+{
+ int dc, dcb, dcr, y, i;
+ for(i=0; i<4; i++){
+ dc= s->dc_val[0][mb_x*2+1 + (i&1) + (mb_y*2+1 + (i>>1))*(s->mb_width*2+2)];
+ for(y=0; y<8; y++){
+ int x;
+ for(x=0; x<8; x++){
+ dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
+ }
+ }
+ }
+ dcb = s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
+ dcr= s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
+ for(y=0; y<8; y++){
+ int x;
+ for(x=0; x<8; x++){
+ dest_cb[x + y*(s->uvlinesize)]= dcb/8;
+ dest_cr[x + y*(s->uvlinesize)]= dcr/8;
+ }
+ }
+}
+
+/**
+ * will conceal past errors, and allso drop b frames if needed
+ *
+ */
+void ff_conceal_past_errors(MpegEncContext *s, int unknown_pos)
+{
+ int mb_x= s->mb_x;
+ int mb_y= s->mb_y;
+ int mb_dist=0;
+ int i, intra_count=0, inter_count=0;
+ int intra_conceal= s->msmpeg4_version ? 50 : 50; //FIXME finetune
+ int inter_conceal= s->msmpeg4_version ? 50 : 50;
+
+ // for last block
+ if(mb_x>=s->mb_width) mb_x= s->mb_width -1;
+ if(mb_y>=s->mb_height) mb_y= s->mb_height-1;
+
+ if(s->decoding_error==0 && unknown_pos){
+ if(s->data_partitioning && s->pict_type!=B_TYPE)
+ s->decoding_error= DECODING_AC_LOST;
+ else
+ s->decoding_error= DECODING_DESYNC;
+ }
+
+ if(s->decoding_error==DECODING_DESYNC && s->pict_type!=B_TYPE) s->next_p_frame_damaged=1;
+
+ for(i=mb_x + mb_y*s->mb_width; i>=0; i--){
+ if(s->mbintra_table[i]) intra_count++;
+ else inter_count++;
+ }
+
+ if(s->decoding_error==DECODING_AC_LOST){
+ intra_conceal*=2;
+ inter_conceal*=2;
+ }else if(s->decoding_error==DECODING_ACDC_LOST){
+ intra_conceal*=2;
+ inter_conceal*=2;
+ }
+
+ if(unknown_pos && (intra_count<inter_count)){
+ intra_conceal= inter_conceal= s->mb_num;
+// printf("%d %d\n",intra_count, inter_count);
+ }
+
+ fprintf(stderr, "concealing errors\n");
+
+ /* for all MBs from the current one back until the last resync marker */
+ for(; mb_y>=0 && mb_y>=s->resync_mb_y; mb_y--){
+ for(; mb_x>=0; mb_x--){
+ uint8_t *dest_y = s->current_picture[0] + (mb_y * 16* s->linesize ) + mb_x * 16;
+ uint8_t *dest_cb = s->current_picture[1] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
+ uint8_t *dest_cr = s->current_picture[2] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
+ int mb_x_backup= s->mb_x; //FIXME pass xy to mpeg_motion
+ int mb_y_backup= s->mb_y;
+ s->mb_x=mb_x;
+ s->mb_y=mb_y;
+ if(s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<intra_conceal){
+ if(s->decoding_error==DECODING_AC_LOST){
+ remove_ac(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
+// printf("remove ac to %d %d\n", mb_x, mb_y);
+ }else{
+ mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
+ s->last_picture, 0, 0, put_pixels_tab,
+ 0/*mx*/, 0/*my*/, 16);
+ }
+ }
+ else if(!s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<inter_conceal){
+ int mx=0;
+ int my=0;
+
+ if(s->decoding_error!=DECODING_DESYNC){
+ int xy= mb_x*2+1 + (mb_y*2+1)*(s->mb_width*2+2);
+ mx= s->motion_val[ xy ][0];
+ my= s->motion_val[ xy ][1];
+ }
+
+ mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
+ s->last_picture, 0, 0, put_pixels_tab,
+ mx, my, 16);
+ }
+ s->mb_x= mb_x_backup;
+ s->mb_y= mb_y_backup;
+
+ if(mb_x== s->resync_mb_x && mb_y== s->resync_mb_y) return;
+ if(!s->mbskip_table[mb_x + mb_y*s->mb_width]) mb_dist++;
+ }
+ mb_x=s->mb_width-1;
+ }
+}
+