]> git.sesse.net Git - ffmpeg/blob - libavcodec/error_resilience.c
Error concealment of h264 with multiple references.
[ffmpeg] / 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(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])
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) //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
771     if(s->avctx->debug&FF_DEBUG_ER){
772         for(mb_y=0; mb_y<s->mb_height; mb_y++){
773             for(mb_x=0; mb_x<s->mb_width; mb_x++){
774                 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
775
776                 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
777             }
778             av_log(s->avctx, AV_LOG_DEBUG, "\n");
779         }
780     }
781
782 #if 1
783     /* handle overlapping slices */
784     for(error_type=1; error_type<=3; error_type++){
785         int end_ok=0;
786
787         for(i=s->mb_num-1; i>=0; i--){
788             const int mb_xy= s->mb_index2xy[i];
789             int error= s->error_status_table[mb_xy];
790
791             if(error&(1<<error_type))
792                 end_ok=1;
793             if(error&(8<<error_type))
794                 end_ok=1;
795
796             if(!end_ok)
797                 s->error_status_table[mb_xy]|= 1<<error_type;
798
799             if(error&VP_START)
800                 end_ok=0;
801         }
802     }
803 #endif
804 #if 1
805     /* handle slices with partitions of different length */
806     if(s->partitioned_frame){
807         int end_ok=0;
808
809         for(i=s->mb_num-1; i>=0; i--){
810             const int mb_xy= s->mb_index2xy[i];
811             int error= s->error_status_table[mb_xy];
812
813             if(error&AC_END)
814                 end_ok=0;
815             if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
816                 end_ok=1;
817
818             if(!end_ok)
819                 s->error_status_table[mb_xy]|= AC_ERROR;
820
821             if(error&VP_START)
822                 end_ok=0;
823         }
824     }
825 #endif
826     /* handle missing slices */
827     if(s->error_recognition>=4){
828         int end_ok=1;
829
830         for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
831             const int mb_xy= s->mb_index2xy[i];
832             int error1= s->error_status_table[mb_xy  ];
833             int error2= s->error_status_table[s->mb_index2xy[i+1]];
834
835             if(error1&VP_START)
836                 end_ok=1;
837
838             if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
839                && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
840                && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
841                 end_ok=0;
842             }
843
844             if(!end_ok)
845                 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
846         }
847     }
848
849 #if 1
850     /* backward mark errors */
851     distance=9999999;
852     for(error_type=1; error_type<=3; error_type++){
853         for(i=s->mb_num-1; i>=0; i--){
854             const int mb_xy= s->mb_index2xy[i];
855             int error= s->error_status_table[mb_xy];
856
857             if(!s->mbskip_table[mb_xy]) //FIXME partition specific
858                 distance++;
859             if(error&(1<<error_type))
860                 distance= 0;
861
862             if(s->partitioned_frame){
863                 if(distance < threshold_part[error_type-1])
864                     s->error_status_table[mb_xy]|= 1<<error_type;
865             }else{
866                 if(distance < threshold)
867                     s->error_status_table[mb_xy]|= 1<<error_type;
868             }
869
870             if(error&VP_START)
871                 distance= 9999999;
872         }
873     }
874 #endif
875
876     /* forward mark errors */
877     error=0;
878     for(i=0; i<s->mb_num; i++){
879         const int mb_xy= s->mb_index2xy[i];
880         int old_error= s->error_status_table[mb_xy];
881
882         if(old_error&VP_START)
883             error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
884         else{
885             error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
886             s->error_status_table[mb_xy]|= error;
887         }
888     }
889 #if 1
890     /* handle not partitioned case */
891     if(!s->partitioned_frame){
892         for(i=0; i<s->mb_num; i++){
893             const int mb_xy= s->mb_index2xy[i];
894             error= s->error_status_table[mb_xy];
895             if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
896                 error|= AC_ERROR|DC_ERROR|MV_ERROR;
897             s->error_status_table[mb_xy]= error;
898         }
899     }
900 #endif
901
902     dc_error= ac_error= mv_error=0;
903     for(i=0; i<s->mb_num; i++){
904         const int mb_xy= s->mb_index2xy[i];
905         error= s->error_status_table[mb_xy];
906         if(error&DC_ERROR) dc_error ++;
907         if(error&AC_ERROR) ac_error ++;
908         if(error&MV_ERROR) mv_error ++;
909     }
910     av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
911
912     is_intra_likely= is_intra_more_likely(s);
913
914     /* set unknown mb-type to most likely */
915     for(i=0; i<s->mb_num; i++){
916         const int mb_xy= s->mb_index2xy[i];
917         error= s->error_status_table[mb_xy];
918         if(!((error&DC_ERROR) && (error&MV_ERROR)))
919             continue;
920
921         if(is_intra_likely)
922             s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
923         else
924             s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
925     }
926
927     // change inter to intra blocks if no reference frames are available
928     if (!s->last_picture.data[0] && !s->next_picture.data[0])
929         for(i=0; i<s->mb_num; i++){
930             const int mb_xy= s->mb_index2xy[i];
931             if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
932                 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
933         }
934
935     /* handle inter blocks with damaged AC */
936     for(mb_y=0; mb_y<s->mb_height; mb_y++){
937         for(mb_x=0; mb_x<s->mb_width; mb_x++){
938             const int mb_xy= mb_x + mb_y * s->mb_stride;
939             const int mb_type= s->current_picture.mb_type[mb_xy];
940             int dir = !s->last_picture.data[0];
941             error= s->error_status_table[mb_xy];
942
943             if(IS_INTRA(mb_type)) continue; //intra
944             if(error&MV_ERROR) continue;              //inter with damaged MV
945             if(!(error&AC_ERROR)) continue;           //undamaged inter
946
947             s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
948             s->mb_intra=0;
949             s->mb_skipped=0;
950             if(IS_8X8(mb_type)){
951                 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
952                 int j;
953                 s->mv_type = MV_TYPE_8X8;
954                 for(j=0; j<4; j++){
955                     s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
956                     s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
957                 }
958             }else{
959                 s->mv_type = MV_TYPE_16X16;
960                 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
961                 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
962             }
963
964             s->dsp.clear_blocks(s->block[0]);
965
966             s->mb_x= mb_x;
967             s->mb_y= mb_y;
968             decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
969         }
970     }
971
972     /* guess MVs */
973     if(s->pict_type==FF_B_TYPE){
974         for(mb_y=0; mb_y<s->mb_height; mb_y++){
975             for(mb_x=0; mb_x<s->mb_width; mb_x++){
976                 int xy= mb_x*2 + mb_y*2*s->b8_stride;
977                 const int mb_xy= mb_x + mb_y * s->mb_stride;
978                 const int mb_type= s->current_picture.mb_type[mb_xy];
979                 error= s->error_status_table[mb_xy];
980
981                 if(IS_INTRA(mb_type)) continue;
982                 if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
983                 if(!(error&AC_ERROR)) continue;           //undamaged inter
984
985                 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
986                 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
987                 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
988                 s->mb_intra=0;
989                 s->mv_type = MV_TYPE_16X16;
990                 s->mb_skipped=0;
991
992                 if(s->pp_time){
993                     int time_pp= s->pp_time;
994                     int time_pb= s->pb_time;
995
996                     s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
997                     s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
998                     s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
999                     s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1000                 }else{
1001                     s->mv[0][0][0]= 0;
1002                     s->mv[0][0][1]= 0;
1003                     s->mv[1][0][0]= 0;
1004                     s->mv[1][0][1]= 0;
1005                 }
1006
1007                 s->dsp.clear_blocks(s->block[0]);
1008                 s->mb_x= mb_x;
1009                 s->mb_y= mb_y;
1010                 decode_mb(s, 0);
1011             }
1012         }
1013     }else
1014         guess_mv(s);
1015
1016     /* the filters below are not XvMC compatible, skip them */
1017     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1018         goto ec_clean;
1019     /* fill DC for inter blocks */
1020     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1021         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1022             int dc, dcu, dcv, y, n;
1023             int16_t *dc_ptr;
1024             uint8_t *dest_y, *dest_cb, *dest_cr;
1025             const int mb_xy= mb_x + mb_y * s->mb_stride;
1026             const int mb_type= s->current_picture.mb_type[mb_xy];
1027
1028             error= s->error_status_table[mb_xy];
1029
1030             if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1031 //            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1032
1033             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1034             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1035             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1036
1037             dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1038             for(n=0; n<4; n++){
1039                 dc=0;
1040                 for(y=0; y<8; y++){
1041                     int x;
1042                     for(x=0; x<8; x++){
1043                        dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1044                     }
1045                 }
1046                 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1047             }
1048
1049             dcu=dcv=0;
1050             for(y=0; y<8; y++){
1051                 int x;
1052                 for(x=0; x<8; x++){
1053                     dcu+=dest_cb[x + y*(s->uvlinesize)];
1054                     dcv+=dest_cr[x + y*(s->uvlinesize)];
1055                 }
1056             }
1057             s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1058             s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1059         }
1060     }
1061 #if 1
1062     /* guess DC for damaged blocks */
1063     guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1064     guess_dc(s, s->dc_val[1], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1065     guess_dc(s, s->dc_val[2], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1066 #endif
1067     /* filter luma DC */
1068     filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1069
1070 #if 1
1071     /* render DC only intra */
1072     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1073         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1074             uint8_t *dest_y, *dest_cb, *dest_cr;
1075             const int mb_xy= mb_x + mb_y * s->mb_stride;
1076             const int mb_type= s->current_picture.mb_type[mb_xy];
1077
1078             error= s->error_status_table[mb_xy];
1079
1080             if(IS_INTER(mb_type)) continue;
1081             if(!(error&AC_ERROR)) continue;              //undamaged
1082
1083             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1084             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1085             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1086
1087             put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1088         }
1089     }
1090 #endif
1091
1092     if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1093         /* filter horizontal block boundaries */
1094         h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1095         h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1096         h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1097
1098         /* filter vertical block boundaries */
1099         v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1100         v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1101         v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1102     }
1103
1104 ec_clean:
1105     /* clean a few tables */
1106     for(i=0; i<s->mb_num; i++){
1107         const int mb_xy= s->mb_index2xy[i];
1108         int error= s->error_status_table[mb_xy];
1109
1110         if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1111             s->mbskip_table[mb_xy]=0;
1112         }
1113         s->mbintra_table[mb_xy]=1;
1114     }
1115 }