fix compilation with --disable-everything --enable-decoder=mpeg2video
[ffmpeg.git] / libavcodec / error_resilience.c
1 /*
2  * Error resilience / concealment
3  *
4  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 /**
24  * @file libavcodec/error_resilience.c
25  * Error resilience / concealment.
26  */
27
28 #include <limits.h>
29
30 #include "avcodec.h"
31 #include "dsputil.h"
32 #include "mpegvideo.h"
33 #include "h264.h"
34
35 /*
36  * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264)
37  * but error concealment must support both h264 and h263 thus we must undo this
38  */
39 #undef mb_intra
40
41 static void decode_mb(MpegEncContext *s, int ref){
42     s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize  ) + s->mb_x * 16;
43     s->dest[1] = s->current_picture.data[1] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift);
44     s->dest[2] = s->current_picture.data[2] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift);
45
46     if(CONFIG_H264_DECODER && s->codec_id == CODEC_ID_H264){
47         H264Context *h= (void*)s;
48         h->mb_xy= s->mb_x + s->mb_y*s->mb_stride;
49         memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
50         assert(ref>=0);
51         if(ref >= h->ref_count[0]) //FIXME it is posible albeit uncommon that slice references differ between slices, we take the easy approuch and ignore it for now. If this turns out to have any relevance in practice then correct remapping should be added
52             ref=0;
53         fill_rectangle(&s->current_picture.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1);
54         fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
55         fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4);
56         assert(!FRAME_MBAFF);
57         ff_h264_hl_decode_mb(h);
58     }else{
59         assert(ref==0);
60     MPV_decode_mb(s, s->block);
61     }
62 }
63
64 /**
65  * @param stride the number of MVs to get to the next row
66  * @param mv_step the number of MVs per row or column in a macroblock
67  */
68 static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){
69     if(s->codec_id == CODEC_ID_H264){
70         H264Context *h= (void*)s;
71         assert(s->quarter_sample);
72         *mv_step= 4;
73         *stride= h->b_stride;
74     }else{
75         *mv_step= 2;
76         *stride= s->b8_stride;
77     }
78 }
79
80 /**
81  * replaces the current MB with a flat dc only version.
82  */
83 static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
84 {
85     int dc, dcu, dcv, y, i;
86     for(i=0; i<4; i++){
87         dc= s->dc_val[0][mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*s->b8_stride];
88         if(dc<0) dc=0;
89         else if(dc>2040) dc=2040;
90         for(y=0; y<8; y++){
91             int x;
92             for(x=0; x<8; x++){
93                 dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
94             }
95         }
96     }
97     dcu = s->dc_val[1][mb_x + mb_y*s->mb_stride];
98     dcv = s->dc_val[2][mb_x + mb_y*s->mb_stride];
99     if     (dcu<0   ) dcu=0;
100     else if(dcu>2040) dcu=2040;
101     if     (dcv<0   ) dcv=0;
102     else if(dcv>2040) dcv=2040;
103     for(y=0; y<8; y++){
104         int x;
105         for(x=0; x<8; x++){
106             dest_cb[x + y*(s->uvlinesize)]= dcu/8;
107             dest_cr[x + y*(s->uvlinesize)]= dcv/8;
108         }
109     }
110 }
111
112 static void filter181(int16_t *data, int width, int height, int stride){
113     int x,y;
114
115     /* horizontal filter */
116     for(y=1; y<height-1; y++){
117         int prev_dc= data[0 + y*stride];
118
119         for(x=1; x<width-1; x++){
120             int dc;
121
122             dc= - prev_dc
123                 + data[x     + y*stride]*8
124                 - data[x + 1 + y*stride];
125             dc= (dc*10923 + 32768)>>16;
126             prev_dc= data[x + y*stride];
127             data[x + y*stride]= dc;
128         }
129     }
130
131     /* vertical filter */
132     for(x=1; x<width-1; x++){
133         int prev_dc= data[x];
134
135         for(y=1; y<height-1; y++){
136             int dc;
137
138             dc= - prev_dc
139                 + data[x +  y   *stride]*8
140                 - data[x + (y+1)*stride];
141             dc= (dc*10923 + 32768)>>16;
142             prev_dc= data[x + y*stride];
143             data[x + y*stride]= dc;
144         }
145     }
146 }
147
148 /**
149  * guess the dc of blocks which do not have an undamaged dc
150  * @param w     width in 8 pixel blocks
151  * @param h     height in 8 pixel blocks
152  */
153 static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
154     int b_x, b_y;
155
156     for(b_y=0; b_y<h; b_y++){
157         for(b_x=0; b_x<w; b_x++){
158             int color[4]={1024,1024,1024,1024};
159             int distance[4]={9999,9999,9999,9999};
160             int mb_index, error, j;
161             int64_t guess, weight_sum;
162
163             mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
164
165             error= s->error_status_table[mb_index];
166
167             if(IS_INTER(s->current_picture.mb_type[mb_index])) continue; //inter
168             if(!(error&DC_ERROR)) continue;           //dc-ok
169
170             /* right block */
171             for(j=b_x+1; j<w; j++){
172                 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
173                 int error_j= s->error_status_table[mb_index_j];
174                 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
175                 if(intra_j==0 || !(error_j&DC_ERROR)){
176                     color[0]= dc[j + b_y*stride];
177                     distance[0]= j-b_x;
178                     break;
179                 }
180             }
181
182             /* left block */
183             for(j=b_x-1; j>=0; j--){
184                 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
185                 int error_j= s->error_status_table[mb_index_j];
186                 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
187                 if(intra_j==0 || !(error_j&DC_ERROR)){
188                     color[1]= dc[j + b_y*stride];
189                     distance[1]= b_x-j;
190                     break;
191                 }
192             }
193
194             /* bottom block */
195             for(j=b_y+1; j<h; j++){
196                 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
197                 int error_j= s->error_status_table[mb_index_j];
198                 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
199                 if(intra_j==0 || !(error_j&DC_ERROR)){
200                     color[2]= dc[b_x + j*stride];
201                     distance[2]= j-b_y;
202                     break;
203                 }
204             }
205
206             /* top block */
207             for(j=b_y-1; j>=0; j--){
208                 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
209                 int error_j= s->error_status_table[mb_index_j];
210                 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
211                 if(intra_j==0 || !(error_j&DC_ERROR)){
212                     color[3]= dc[b_x + j*stride];
213                     distance[3]= b_y-j;
214                     break;
215                 }
216             }
217
218             weight_sum=0;
219             guess=0;
220             for(j=0; j<4; j++){
221                 int64_t weight= 256*256*256*16/distance[j];
222                 guess+= weight*(int64_t)color[j];
223                 weight_sum+= weight;
224             }
225             guess= (guess + weight_sum/2) / weight_sum;
226
227             dc[b_x + b_y*stride]= guess;
228         }
229     }
230 }
231
232 /**
233  * simple horizontal deblocking filter used for error resilience
234  * @param w     width in 8 pixel blocks
235  * @param h     height in 8 pixel blocks
236  */
237 static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
238     int b_x, b_y, mvx_stride, mvy_stride;
239     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
240     set_mv_strides(s, &mvx_stride, &mvy_stride);
241     mvx_stride >>= is_luma;
242     mvy_stride *= mvx_stride;
243
244     for(b_y=0; b_y<h; b_y++){
245         for(b_x=0; b_x<w-1; b_x++){
246             int y;
247             int left_status = s->error_status_table[( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_stride];
248             int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride];
249             int left_intra=   IS_INTRA(s->current_picture.mb_type      [( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_stride]);
250             int right_intra=  IS_INTRA(s->current_picture.mb_type      [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]);
251             int left_damage =  left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
252             int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
253             int offset= b_x*8 + b_y*stride*8;
254             int16_t *left_mv=  s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride* b_x   ];
255             int16_t *right_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride*(b_x+1)];
256
257             if(!(left_damage||right_damage)) continue; // both undamaged
258
259             if(   (!left_intra) && (!right_intra)
260                && FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue;
261
262             for(y=0; y<8; y++){
263                 int a,b,c,d;
264
265                 a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
266                 b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
267                 c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
268
269                 d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1);
270                 d= FFMAX(d, 0);
271                 if(b<0) d= -d;
272
273                 if(d==0) continue;
274
275                 if(!(left_damage && right_damage))
276                     d= d*16/9;
277
278                 if(left_damage){
279                     dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
280                     dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
281                     dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
282                     dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
283                 }
284                 if(right_damage){
285                     dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
286                     dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
287                     dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
288                     dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
289                 }
290             }
291         }
292     }
293 }
294
295 /**
296  * simple vertical deblocking filter used for error resilience
297  * @param w     width in 8 pixel blocks
298  * @param h     height in 8 pixel blocks
299  */
300 static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
301     int b_x, b_y, mvx_stride, mvy_stride;
302     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
303     set_mv_strides(s, &mvx_stride, &mvy_stride);
304     mvx_stride >>= is_luma;
305     mvy_stride *= mvx_stride;
306
307     for(b_y=0; b_y<h-1; b_y++){
308         for(b_x=0; b_x<w; b_x++){
309             int x;
310             int top_status   = s->error_status_table[(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_stride];
311             int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride];
312             int top_intra=     IS_INTRA(s->current_picture.mb_type      [(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_stride]);
313             int bottom_intra=  IS_INTRA(s->current_picture.mb_type      [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]);
314             int top_damage =      top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
315             int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
316             int offset= b_x*8 + b_y*stride*8;
317             int16_t *top_mv=    s->current_picture.motion_val[0][mvy_stride* b_y    + mvx_stride*b_x];
318             int16_t *bottom_mv= s->current_picture.motion_val[0][mvy_stride*(b_y+1) + mvx_stride*b_x];
319
320             if(!(top_damage||bottom_damage)) continue; // both undamaged
321
322             if(   (!top_intra) && (!bottom_intra)
323                && FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue;
324
325             for(x=0; x<8; x++){
326                 int a,b,c,d;
327
328                 a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
329                 b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
330                 c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
331
332                 d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1);
333                 d= FFMAX(d, 0);
334                 if(b<0) d= -d;
335
336                 if(d==0) continue;
337
338                 if(!(top_damage && bottom_damage))
339                     d= d*16/9;
340
341                 if(top_damage){
342                     dst[offset + x +  7*stride] = cm[dst[offset + x +  7*stride] + ((d*7)>>4)];
343                     dst[offset + x +  6*stride] = cm[dst[offset + x +  6*stride] + ((d*5)>>4)];
344                     dst[offset + x +  5*stride] = cm[dst[offset + x +  5*stride] + ((d*3)>>4)];
345                     dst[offset + x +  4*stride] = cm[dst[offset + x +  4*stride] + ((d*1)>>4)];
346                 }
347                 if(bottom_damage){
348                     dst[offset + x +  8*stride] = cm[dst[offset + x +  8*stride] - ((d*7)>>4)];
349                     dst[offset + x +  9*stride] = cm[dst[offset + x +  9*stride] - ((d*5)>>4)];
350                     dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
351                     dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
352                 }
353             }
354         }
355     }
356 }
357
358 static void guess_mv(MpegEncContext *s){
359     uint8_t fixed[s->mb_stride * s->mb_height];
360 #define MV_FROZEN    3
361 #define MV_CHANGED   2
362 #define MV_UNCHANGED 1
363     const int mb_stride = s->mb_stride;
364     const int mb_width = s->mb_width;
365     const int mb_height= s->mb_height;
366     int i, depth, num_avail;
367     int mb_x, mb_y, mot_step, mot_stride;
368
369     set_mv_strides(s, &mot_step, &mot_stride);
370
371     num_avail=0;
372     for(i=0; i<s->mb_num; i++){
373         const int mb_xy= s->mb_index2xy[ i ];
374         int f=0;
375         int error= s->error_status_table[mb_xy];
376
377         if(IS_INTRA(s->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check
378         if(!(error&MV_ERROR)) f=MV_FROZEN;           //inter with undamaged MV
379
380         fixed[mb_xy]= f;
381         if(f==MV_FROZEN)
382             num_avail++;
383     }
384
385     if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
386         for(mb_y=0; mb_y<s->mb_height; mb_y++){
387             for(mb_x=0; mb_x<s->mb_width; mb_x++){
388                 const int mb_xy= mb_x + mb_y*s->mb_stride;
389
390                 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))  continue;
391                 if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
392
393                 s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
394                 s->mb_intra=0;
395                 s->mv_type = MV_TYPE_16X16;
396                 s->mb_skipped=0;
397
398                 s->dsp.clear_blocks(s->block[0]);
399
400                 s->mb_x= mb_x;
401                 s->mb_y= mb_y;
402                 s->mv[0][0][0]= 0;
403                 s->mv[0][0][1]= 0;
404                 decode_mb(s, 0);
405             }
406         }
407         return;
408     }
409
410     for(depth=0;; depth++){
411         int changed, pass, none_left;
412
413         none_left=1;
414         changed=1;
415         for(pass=0; (changed || pass<2) && pass<10; pass++){
416             int mb_x, mb_y;
417 int score_sum=0;
418
419             changed=0;
420             for(mb_y=0; mb_y<s->mb_height; mb_y++){
421                 for(mb_x=0; mb_x<s->mb_width; mb_x++){
422                     const int mb_xy= mb_x + mb_y*s->mb_stride;
423                     int mv_predictor[8][2]={{0}};
424                     int ref[8]={0};
425                     int pred_count=0;
426                     int j;
427                     int best_score=256*256*256*64;
428                     int best_pred=0;
429                     const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
430                     int prev_x= s->current_picture.motion_val[0][mot_index][0];
431                     int prev_y= s->current_picture.motion_val[0][mot_index][1];
432
433                     if((mb_x^mb_y^pass)&1) continue;
434
435                     if(fixed[mb_xy]==MV_FROZEN) continue;
436                     assert(!IS_INTRA(s->current_picture.mb_type[mb_xy]));
437                     assert(s->last_picture_ptr && s->last_picture_ptr->data[0]);
438
439                     j=0;
440                     if(mb_x>0           && fixed[mb_xy-1        ]==MV_FROZEN) j=1;
441                     if(mb_x+1<mb_width  && fixed[mb_xy+1        ]==MV_FROZEN) j=1;
442                     if(mb_y>0           && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1;
443                     if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1;
444                     if(j==0) continue;
445
446                     j=0;
447                     if(mb_x>0           && fixed[mb_xy-1        ]==MV_CHANGED) j=1;
448                     if(mb_x+1<mb_width  && fixed[mb_xy+1        ]==MV_CHANGED) j=1;
449                     if(mb_y>0           && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1;
450                     if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1;
451                     if(j==0 && pass>1) continue;
452
453                     none_left=0;
454
455                     if(mb_x>0 && fixed[mb_xy-1]){
456                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0];
457                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1];
458                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy-1)];
459                         pred_count++;
460                     }
461                     if(mb_x+1<mb_width && fixed[mb_xy+1]){
462                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_step][0];
463                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1];
464                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy+1)];
465                         pred_count++;
466                     }
467                     if(mb_y>0 && fixed[mb_xy-mb_stride]){
468                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0];
469                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1];
470                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)];
471                         pred_count++;
472                     }
473                     if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
474                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][0];
475                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1];
476                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)];
477                         pred_count++;
478                     }
479                     if(pred_count==0) continue;
480
481                     if(pred_count>1){
482                         int sum_x=0, sum_y=0, sum_r=0;
483                         int max_x, max_y, min_x, min_y, max_r, min_r;
484
485                         for(j=0; j<pred_count; j++){
486                             sum_x+= mv_predictor[j][0];
487                             sum_y+= mv_predictor[j][1];
488                             sum_r+= ref[j];
489                             if(j && ref[j] != ref[j-1] && s->codec_id == CODEC_ID_H264)
490                                 goto skip_mean_and_median;
491                         }
492
493                         /* mean */
494                         mv_predictor[pred_count][0] = sum_x/j;
495                         mv_predictor[pred_count][1] = sum_y/j;
496                         ref         [pred_count]    = sum_r/j;
497
498                         /* median */
499                         if(pred_count>=3){
500                             min_y= min_x= min_r= 99999;
501                             max_y= max_x= max_r=-99999;
502                         }else{
503                             min_x=min_y=max_x=max_y=min_r=max_r=0;
504                         }
505                         for(j=0; j<pred_count; j++){
506                             max_x= FFMAX(max_x, mv_predictor[j][0]);
507                             max_y= FFMAX(max_y, mv_predictor[j][1]);
508                             max_r= FFMAX(max_r, ref[j]);
509                             min_x= FFMIN(min_x, mv_predictor[j][0]);
510                             min_y= FFMIN(min_y, mv_predictor[j][1]);
511                             min_r= FFMIN(min_r, ref[j]);
512                         }
513                         mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
514                         mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
515                         ref         [pred_count+1]    = sum_r - max_r - min_r;
516
517                         if(pred_count==4){
518                             mv_predictor[pred_count+1][0] /= 2;
519                             mv_predictor[pred_count+1][1] /= 2;
520                             ref         [pred_count+1]    /= 2;
521                         }
522                         pred_count+=2;
523                     }
524 skip_mean_and_median:
525
526                     /* zero MV */
527                     pred_count++;
528
529                     /* last MV */
530                     mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0];
531                     mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1];
532                     ref         [pred_count]   = s->current_picture.ref_index[0][4*mb_xy];
533                     pred_count++;
534
535                     s->mv_dir = MV_DIR_FORWARD;
536                     s->mb_intra=0;
537                     s->mv_type = MV_TYPE_16X16;
538                     s->mb_skipped=0;
539
540                     s->dsp.clear_blocks(s->block[0]);
541
542                     s->mb_x= mb_x;
543                     s->mb_y= mb_y;
544
545                     for(j=0; j<pred_count; j++){
546                         int score=0;
547                         uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
548
549                         s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
550                         s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
551
552                         if(ref[j]<0 && s->codec_id == CODEC_ID_H264) //predictor intra or otherwise not available
553                             continue;
554
555                         decode_mb(s, ref[j]);
556
557                         if(mb_x>0 && fixed[mb_xy-1]){
558                             int k;
559                             for(k=0; k<16; k++)
560                                 score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize   ]);
561                         }
562                         if(mb_x+1<mb_width && fixed[mb_xy+1]){
563                             int k;
564                             for(k=0; k<16; k++)
565                                 score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
566                         }
567                         if(mb_y>0 && fixed[mb_xy-mb_stride]){
568                             int k;
569                             for(k=0; k<16; k++)
570                                 score += FFABS(src[k-s->linesize   ]-src[k               ]);
571                         }
572                         if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
573                             int k;
574                             for(k=0; k<16; k++)
575                                 score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
576                         }
577
578                         if(score <= best_score){ // <= will favor the last MV
579                             best_score= score;
580                             best_pred= j;
581                         }
582                     }
583 score_sum+= best_score;
584                     s->mv[0][0][0]= mv_predictor[best_pred][0];
585                     s->mv[0][0][1]= mv_predictor[best_pred][1];
586
587                     for(i=0; i<mot_step; i++)
588                         for(j=0; j<mot_step; j++){
589                             s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0];
590                             s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1];
591                         }
592
593                     decode_mb(s, ref[best_pred]);
594
595
596                     if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
597                         fixed[mb_xy]=MV_CHANGED;
598                         changed++;
599                     }else
600                         fixed[mb_xy]=MV_UNCHANGED;
601                 }
602             }
603
604 //            printf(".%d/%d", changed, score_sum); fflush(stdout);
605         }
606
607         if(none_left)
608             return;
609
610         for(i=0; i<s->mb_num; i++){
611             int mb_xy= s->mb_index2xy[i];
612             if(fixed[mb_xy])
613                 fixed[mb_xy]=MV_FROZEN;
614         }
615 //        printf(":"); fflush(stdout);
616     }
617 }
618
619 static int is_intra_more_likely(MpegEncContext *s){
620     int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
621
622     if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction
623
624     undamaged_count=0;
625     for(i=0; i<s->mb_num; i++){
626         const int mb_xy= s->mb_index2xy[i];
627         const int error= s->error_status_table[mb_xy];
628         if(!((error&DC_ERROR) && (error&MV_ERROR)))
629             undamaged_count++;
630     }
631
632     if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
633
634     //prevent dsp.sad() check, that requires access to the image
635     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE)
636         return 1;
637
638     skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
639     is_intra_likely=0;
640
641     j=0;
642     for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
643         for(mb_x= 0; mb_x<s->mb_width; mb_x++){
644             int error;
645             const int mb_xy= mb_x + mb_y*s->mb_stride;
646
647             error= s->error_status_table[mb_xy];
648             if((error&DC_ERROR) && (error&MV_ERROR))
649                 continue; //skip damaged
650
651             j++;
652             if((j%skip_amount) != 0) continue; //skip a few to speed things up
653
654             if(s->pict_type==FF_I_TYPE){
655                 uint8_t *mb_ptr     = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
656                 uint8_t *last_mb_ptr= s->last_picture.data   [0] + mb_x*16 + mb_y*16*s->linesize;
657
658                 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr                    , s->linesize, 16);
659                 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
660             }else{
661                 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
662                    is_intra_likely++;
663                 else
664                    is_intra_likely--;
665             }
666         }
667     }
668 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
669     return is_intra_likely > 0;
670 }
671
672 void ff_er_frame_start(MpegEncContext *s){
673     if(!s->error_recognition) return;
674
675     memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_stride*s->mb_height*sizeof(uint8_t));
676     s->error_count= 3*s->mb_num;
677 }
678
679 /**
680  * adds a slice.
681  * @param endx x component of the last macroblock, can be -1 for the last of the previous line
682  * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
683  *               error of the same type occurred
684  */
685 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
686     const int start_i= av_clip(startx + starty * s->mb_width    , 0, s->mb_num-1);
687     const int end_i  = av_clip(endx   + endy   * s->mb_width    , 0, s->mb_num);
688     const int start_xy= s->mb_index2xy[start_i];
689     const int end_xy  = s->mb_index2xy[end_i];
690     int mask= -1;
691
692     if(s->avctx->hwaccel)
693         return;
694
695     if(start_i > end_i || start_xy > end_xy){
696         av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
697         return;
698     }
699
700     if(!s->error_recognition) return;
701
702     mask &= ~VP_START;
703     if(status & (AC_ERROR|AC_END)){
704         mask &= ~(AC_ERROR|AC_END);
705         s->error_count -= end_i - start_i + 1;
706     }
707     if(status & (DC_ERROR|DC_END)){
708         mask &= ~(DC_ERROR|DC_END);
709         s->error_count -= end_i - start_i + 1;
710     }
711     if(status & (MV_ERROR|MV_END)){
712         mask &= ~(MV_ERROR|MV_END);
713         s->error_count -= end_i - start_i + 1;
714     }
715
716     if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
717
718     if(mask == ~0x7F){
719         memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
720     }else{
721         int i;
722         for(i=start_xy; i<end_xy; i++){
723             s->error_status_table[ i ] &= mask;
724         }
725     }
726
727     if(end_i == s->mb_num)
728         s->error_count= INT_MAX;
729     else{
730         s->error_status_table[end_xy] &= mask;
731         s->error_status_table[end_xy] |= status;
732     }
733
734     s->error_status_table[start_xy] |= VP_START;
735
736     if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
737         int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
738
739         prev_status &= ~ VP_START;
740         if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
741     }
742 }
743
744 void ff_er_frame_end(MpegEncContext *s){
745     int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
746     int distance;
747     int threshold_part[4]= {100,100,100};
748     int threshold= 50;
749     int is_intra_likely;
750     int size = s->b8_stride * 2 * s->mb_height;
751     Picture *pic= s->current_picture_ptr;
752
753     if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
754        s->avctx->hwaccel ||
755        s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
756        s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
757        s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
758
759     if(s->current_picture.motion_val[0] == NULL){
760         av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
761
762         for(i=0; i<2; i++){
763             pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
764             pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
765             pic->motion_val[i]= pic->motion_val_base[i]+4;
766         }
767         pic->motion_subsample_log2= 3;
768         s->current_picture= *s->current_picture_ptr;
769     }
770     pic->ref_index[0]= av_realloc(pic->ref_index[0], s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
771
772     if(s->avctx->debug&FF_DEBUG_ER){
773         for(mb_y=0; mb_y<s->mb_height; mb_y++){
774             for(mb_x=0; mb_x<s->mb_width; mb_x++){
775                 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
776
777                 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
778             }
779             av_log(s->avctx, AV_LOG_DEBUG, "\n");
780         }
781     }
782
783 #if 1
784     /* handle overlapping slices */
785     for(error_type=1; error_type<=3; error_type++){
786         int end_ok=0;
787
788         for(i=s->mb_num-1; i>=0; i--){
789             const int mb_xy= s->mb_index2xy[i];
790             int error= s->error_status_table[mb_xy];
791
792             if(error&(1<<error_type))
793                 end_ok=1;
794             if(error&(8<<error_type))
795                 end_ok=1;
796
797             if(!end_ok)
798                 s->error_status_table[mb_xy]|= 1<<error_type;
799
800             if(error&VP_START)
801                 end_ok=0;
802         }
803     }
804 #endif
805 #if 1
806     /* handle slices with partitions of different length */
807     if(s->partitioned_frame){
808         int end_ok=0;
809
810         for(i=s->mb_num-1; i>=0; i--){
811             const int mb_xy= s->mb_index2xy[i];
812             int error= s->error_status_table[mb_xy];
813
814             if(error&AC_END)
815                 end_ok=0;
816             if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
817                 end_ok=1;
818
819             if(!end_ok)
820                 s->error_status_table[mb_xy]|= AC_ERROR;
821
822             if(error&VP_START)
823                 end_ok=0;
824         }
825     }
826 #endif
827     /* handle missing slices */
828     if(s->error_recognition>=4){
829         int end_ok=1;
830
831         for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
832             const int mb_xy= s->mb_index2xy[i];
833             int error1= s->error_status_table[mb_xy  ];
834             int error2= s->error_status_table[s->mb_index2xy[i+1]];
835
836             if(error1&VP_START)
837                 end_ok=1;
838
839             if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
840                && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
841                && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
842                 end_ok=0;
843             }
844
845             if(!end_ok)
846                 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
847         }
848     }
849
850 #if 1
851     /* backward mark errors */
852     distance=9999999;
853     for(error_type=1; error_type<=3; error_type++){
854         for(i=s->mb_num-1; i>=0; i--){
855             const int mb_xy= s->mb_index2xy[i];
856             int error= s->error_status_table[mb_xy];
857
858             if(!s->mbskip_table[mb_xy]) //FIXME partition specific
859                 distance++;
860             if(error&(1<<error_type))
861                 distance= 0;
862
863             if(s->partitioned_frame){
864                 if(distance < threshold_part[error_type-1])
865                     s->error_status_table[mb_xy]|= 1<<error_type;
866             }else{
867                 if(distance < threshold)
868                     s->error_status_table[mb_xy]|= 1<<error_type;
869             }
870
871             if(error&VP_START)
872                 distance= 9999999;
873         }
874     }
875 #endif
876
877     /* forward mark errors */
878     error=0;
879     for(i=0; i<s->mb_num; i++){
880         const int mb_xy= s->mb_index2xy[i];
881         int old_error= s->error_status_table[mb_xy];
882
883         if(old_error&VP_START)
884             error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
885         else{
886             error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
887             s->error_status_table[mb_xy]|= error;
888         }
889     }
890 #if 1
891     /* handle not partitioned case */
892     if(!s->partitioned_frame){
893         for(i=0; i<s->mb_num; i++){
894             const int mb_xy= s->mb_index2xy[i];
895             error= s->error_status_table[mb_xy];
896             if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
897                 error|= AC_ERROR|DC_ERROR|MV_ERROR;
898             s->error_status_table[mb_xy]= error;
899         }
900     }
901 #endif
902
903     dc_error= ac_error= mv_error=0;
904     for(i=0; i<s->mb_num; i++){
905         const int mb_xy= s->mb_index2xy[i];
906         error= s->error_status_table[mb_xy];
907         if(error&DC_ERROR) dc_error ++;
908         if(error&AC_ERROR) ac_error ++;
909         if(error&MV_ERROR) mv_error ++;
910     }
911     av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
912
913     is_intra_likely= is_intra_more_likely(s);
914
915     /* set unknown mb-type to most likely */
916     for(i=0; i<s->mb_num; i++){
917         const int mb_xy= s->mb_index2xy[i];
918         error= s->error_status_table[mb_xy];
919         if(!((error&DC_ERROR) && (error&MV_ERROR)))
920             continue;
921
922         if(is_intra_likely)
923             s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
924         else
925             s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
926     }
927
928     // change inter to intra blocks if no reference frames are available
929     if (!s->last_picture.data[0] && !s->next_picture.data[0])
930         for(i=0; i<s->mb_num; i++){
931             const int mb_xy= s->mb_index2xy[i];
932             if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
933                 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
934         }
935
936     /* handle inter blocks with damaged AC */
937     for(mb_y=0; mb_y<s->mb_height; mb_y++){
938         for(mb_x=0; mb_x<s->mb_width; mb_x++){
939             const int mb_xy= mb_x + mb_y * s->mb_stride;
940             const int mb_type= s->current_picture.mb_type[mb_xy];
941             int dir = !s->last_picture.data[0];
942             error= s->error_status_table[mb_xy];
943
944             if(IS_INTRA(mb_type)) continue; //intra
945             if(error&MV_ERROR) continue;              //inter with damaged MV
946             if(!(error&AC_ERROR)) continue;           //undamaged inter
947
948             s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
949             s->mb_intra=0;
950             s->mb_skipped=0;
951             if(IS_8X8(mb_type)){
952                 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
953                 int j;
954                 s->mv_type = MV_TYPE_8X8;
955                 for(j=0; j<4; j++){
956                     s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
957                     s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
958                 }
959             }else{
960                 s->mv_type = MV_TYPE_16X16;
961                 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
962                 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
963             }
964
965             s->dsp.clear_blocks(s->block[0]);
966
967             s->mb_x= mb_x;
968             s->mb_y= mb_y;
969             decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
970         }
971     }
972
973     /* guess MVs */
974     if(s->pict_type==FF_B_TYPE){
975         for(mb_y=0; mb_y<s->mb_height; mb_y++){
976             for(mb_x=0; mb_x<s->mb_width; mb_x++){
977                 int xy= mb_x*2 + mb_y*2*s->b8_stride;
978                 const int mb_xy= mb_x + mb_y * s->mb_stride;
979                 const int mb_type= s->current_picture.mb_type[mb_xy];
980                 error= s->error_status_table[mb_xy];
981
982                 if(IS_INTRA(mb_type)) continue;
983                 if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
984                 if(!(error&AC_ERROR)) continue;           //undamaged inter
985
986                 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
987                 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
988                 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
989                 s->mb_intra=0;
990                 s->mv_type = MV_TYPE_16X16;
991                 s->mb_skipped=0;
992
993                 if(s->pp_time){
994                     int time_pp= s->pp_time;
995                     int time_pb= s->pb_time;
996
997                     s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
998                     s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
999                     s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1000                     s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1001                 }else{
1002                     s->mv[0][0][0]= 0;
1003                     s->mv[0][0][1]= 0;
1004                     s->mv[1][0][0]= 0;
1005                     s->mv[1][0][1]= 0;
1006                 }
1007
1008                 s->dsp.clear_blocks(s->block[0]);
1009                 s->mb_x= mb_x;
1010                 s->mb_y= mb_y;
1011                 decode_mb(s, 0);
1012             }
1013         }
1014     }else
1015         guess_mv(s);
1016
1017     /* the filters below are not XvMC compatible, skip them */
1018     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1019         goto ec_clean;
1020     /* fill DC for inter blocks */
1021     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1022         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1023             int dc, dcu, dcv, y, n;
1024             int16_t *dc_ptr;
1025             uint8_t *dest_y, *dest_cb, *dest_cr;
1026             const int mb_xy= mb_x + mb_y * s->mb_stride;
1027             const int mb_type= s->current_picture.mb_type[mb_xy];
1028
1029             error= s->error_status_table[mb_xy];
1030
1031             if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1032 //            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1033
1034             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1035             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1036             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1037
1038             dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1039             for(n=0; n<4; n++){
1040                 dc=0;
1041                 for(y=0; y<8; y++){
1042                     int x;
1043                     for(x=0; x<8; x++){
1044                        dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1045                     }
1046                 }
1047                 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1048             }
1049
1050             dcu=dcv=0;
1051             for(y=0; y<8; y++){
1052                 int x;
1053                 for(x=0; x<8; x++){
1054                     dcu+=dest_cb[x + y*(s->uvlinesize)];
1055                     dcv+=dest_cr[x + y*(s->uvlinesize)];
1056                 }
1057             }
1058             s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1059             s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1060         }
1061     }
1062 #if 1
1063     /* guess DC for damaged blocks */
1064     guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1065     guess_dc(s, s->dc_val[1], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1066     guess_dc(s, s->dc_val[2], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1067 #endif
1068     /* filter luma DC */
1069     filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1070
1071 #if 1
1072     /* render DC only intra */
1073     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1074         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1075             uint8_t *dest_y, *dest_cb, *dest_cr;
1076             const int mb_xy= mb_x + mb_y * s->mb_stride;
1077             const int mb_type= s->current_picture.mb_type[mb_xy];
1078
1079             error= s->error_status_table[mb_xy];
1080
1081             if(IS_INTER(mb_type)) continue;
1082             if(!(error&AC_ERROR)) continue;              //undamaged
1083
1084             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1085             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1086             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1087
1088             put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1089         }
1090     }
1091 #endif
1092
1093     if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1094         /* filter horizontal block boundaries */
1095         h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1096         h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1097         h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1098
1099         /* filter vertical block boundaries */
1100         v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1101         v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1102         v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1103     }
1104
1105 ec_clean:
1106     /* clean a few tables */
1107     for(i=0; i<s->mb_num; i++){
1108         const int mb_xy= s->mb_index2xy[i];
1109         int error= s->error_status_table[mb_xy];
1110
1111         if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1112             s->mbskip_table[mb_xy]=0;
1113         }
1114         s->mbintra_table[mb_xy]=1;
1115     }
1116 }