]> git.sesse.net Git - ffmpeg/blob - libavcodec/error_resilience.c
DCA: ARM/NEON optimised lfe_fir
[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(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])
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(s->codec_id == CODEC_ID_H264){
633         H264Context *h= (void*)s;
634         if(h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0])
635             return 1;
636     }
637
638     if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
639
640     //prevent dsp.sad() check, that requires access to the image
641     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE)
642         return 1;
643
644     skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
645     is_intra_likely=0;
646
647     j=0;
648     for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
649         for(mb_x= 0; mb_x<s->mb_width; mb_x++){
650             int error;
651             const int mb_xy= mb_x + mb_y*s->mb_stride;
652
653             error= s->error_status_table[mb_xy];
654             if((error&DC_ERROR) && (error&MV_ERROR))
655                 continue; //skip damaged
656
657             j++;
658             if((j%skip_amount) != 0) continue; //skip a few to speed things up
659
660             if(s->pict_type==FF_I_TYPE){
661                 uint8_t *mb_ptr     = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
662                 uint8_t *last_mb_ptr= s->last_picture.data   [0] + mb_x*16 + mb_y*16*s->linesize;
663
664                 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr                    , s->linesize, 16);
665                 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
666             }else{
667                 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
668                    is_intra_likely++;
669                 else
670                    is_intra_likely--;
671             }
672         }
673     }
674 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
675     return is_intra_likely > 0;
676 }
677
678 void ff_er_frame_start(MpegEncContext *s){
679     if(!s->error_recognition) return;
680
681     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));
682     s->error_count= 3*s->mb_num;
683 }
684
685 /**
686  * adds a slice.
687  * @param endx x component of the last macroblock, can be -1 for the last of the previous line
688  * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
689  *               error of the same type occurred
690  */
691 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
692     const int start_i= av_clip(startx + starty * s->mb_width    , 0, s->mb_num-1);
693     const int end_i  = av_clip(endx   + endy   * s->mb_width    , 0, s->mb_num);
694     const int start_xy= s->mb_index2xy[start_i];
695     const int end_xy  = s->mb_index2xy[end_i];
696     int mask= -1;
697
698     if(s->avctx->hwaccel)
699         return;
700
701     if(start_i > end_i || start_xy > end_xy){
702         av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
703         return;
704     }
705
706     if(!s->error_recognition) return;
707
708     mask &= ~VP_START;
709     if(status & (AC_ERROR|AC_END)){
710         mask &= ~(AC_ERROR|AC_END);
711         s->error_count -= end_i - start_i + 1;
712     }
713     if(status & (DC_ERROR|DC_END)){
714         mask &= ~(DC_ERROR|DC_END);
715         s->error_count -= end_i - start_i + 1;
716     }
717     if(status & (MV_ERROR|MV_END)){
718         mask &= ~(MV_ERROR|MV_END);
719         s->error_count -= end_i - start_i + 1;
720     }
721
722     if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
723
724     if(mask == ~0x7F){
725         memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
726     }else{
727         int i;
728         for(i=start_xy; i<end_xy; i++){
729             s->error_status_table[ i ] &= mask;
730         }
731     }
732
733     if(end_i == s->mb_num)
734         s->error_count= INT_MAX;
735     else{
736         s->error_status_table[end_xy] &= mask;
737         s->error_status_table[end_xy] |= status;
738     }
739
740     s->error_status_table[start_xy] |= VP_START;
741
742     if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
743         int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
744
745         prev_status &= ~ VP_START;
746         if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
747     }
748 }
749
750 void ff_er_frame_end(MpegEncContext *s){
751     int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
752     int distance;
753     int threshold_part[4]= {100,100,100};
754     int threshold= 50;
755     int is_intra_likely;
756     int size = s->b8_stride * 2 * s->mb_height;
757     Picture *pic= s->current_picture_ptr;
758
759     if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
760        s->avctx->hwaccel ||
761        s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
762        s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
763        s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
764
765     if(s->current_picture.motion_val[0] == NULL){
766         av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
767
768         for(i=0; i<2; i++){
769             pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
770             pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
771             pic->motion_val[i]= pic->motion_val_base[i]+4;
772         }
773         pic->motion_subsample_log2= 3;
774         s->current_picture= *s->current_picture_ptr;
775     }
776
777     if(s->avctx->debug&FF_DEBUG_ER){
778         for(mb_y=0; mb_y<s->mb_height; mb_y++){
779             for(mb_x=0; mb_x<s->mb_width; mb_x++){
780                 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
781
782                 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
783             }
784             av_log(s->avctx, AV_LOG_DEBUG, "\n");
785         }
786     }
787
788 #if 1
789     /* handle overlapping slices */
790     for(error_type=1; error_type<=3; error_type++){
791         int end_ok=0;
792
793         for(i=s->mb_num-1; i>=0; i--){
794             const int mb_xy= s->mb_index2xy[i];
795             int error= s->error_status_table[mb_xy];
796
797             if(error&(1<<error_type))
798                 end_ok=1;
799             if(error&(8<<error_type))
800                 end_ok=1;
801
802             if(!end_ok)
803                 s->error_status_table[mb_xy]|= 1<<error_type;
804
805             if(error&VP_START)
806                 end_ok=0;
807         }
808     }
809 #endif
810 #if 1
811     /* handle slices with partitions of different length */
812     if(s->partitioned_frame){
813         int end_ok=0;
814
815         for(i=s->mb_num-1; i>=0; i--){
816             const int mb_xy= s->mb_index2xy[i];
817             int error= s->error_status_table[mb_xy];
818
819             if(error&AC_END)
820                 end_ok=0;
821             if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
822                 end_ok=1;
823
824             if(!end_ok)
825                 s->error_status_table[mb_xy]|= AC_ERROR;
826
827             if(error&VP_START)
828                 end_ok=0;
829         }
830     }
831 #endif
832     /* handle missing slices */
833     if(s->error_recognition>=4){
834         int end_ok=1;
835
836         for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
837             const int mb_xy= s->mb_index2xy[i];
838             int error1= s->error_status_table[mb_xy  ];
839             int error2= s->error_status_table[s->mb_index2xy[i+1]];
840
841             if(error1&VP_START)
842                 end_ok=1;
843
844             if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
845                && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
846                && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
847                 end_ok=0;
848             }
849
850             if(!end_ok)
851                 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
852         }
853     }
854
855 #if 1
856     /* backward mark errors */
857     distance=9999999;
858     for(error_type=1; error_type<=3; error_type++){
859         for(i=s->mb_num-1; i>=0; i--){
860             const int mb_xy= s->mb_index2xy[i];
861             int error= s->error_status_table[mb_xy];
862
863             if(!s->mbskip_table[mb_xy]) //FIXME partition specific
864                 distance++;
865             if(error&(1<<error_type))
866                 distance= 0;
867
868             if(s->partitioned_frame){
869                 if(distance < threshold_part[error_type-1])
870                     s->error_status_table[mb_xy]|= 1<<error_type;
871             }else{
872                 if(distance < threshold)
873                     s->error_status_table[mb_xy]|= 1<<error_type;
874             }
875
876             if(error&VP_START)
877                 distance= 9999999;
878         }
879     }
880 #endif
881
882     /* forward mark errors */
883     error=0;
884     for(i=0; i<s->mb_num; i++){
885         const int mb_xy= s->mb_index2xy[i];
886         int old_error= s->error_status_table[mb_xy];
887
888         if(old_error&VP_START)
889             error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
890         else{
891             error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
892             s->error_status_table[mb_xy]|= error;
893         }
894     }
895 #if 1
896     /* handle not partitioned case */
897     if(!s->partitioned_frame){
898         for(i=0; i<s->mb_num; i++){
899             const int mb_xy= s->mb_index2xy[i];
900             error= s->error_status_table[mb_xy];
901             if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
902                 error|= AC_ERROR|DC_ERROR|MV_ERROR;
903             s->error_status_table[mb_xy]= error;
904         }
905     }
906 #endif
907
908     dc_error= ac_error= mv_error=0;
909     for(i=0; i<s->mb_num; i++){
910         const int mb_xy= s->mb_index2xy[i];
911         error= s->error_status_table[mb_xy];
912         if(error&DC_ERROR) dc_error ++;
913         if(error&AC_ERROR) ac_error ++;
914         if(error&MV_ERROR) mv_error ++;
915     }
916     av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
917
918     is_intra_likely= is_intra_more_likely(s);
919
920     /* set unknown mb-type to most likely */
921     for(i=0; i<s->mb_num; i++){
922         const int mb_xy= s->mb_index2xy[i];
923         error= s->error_status_table[mb_xy];
924         if(!((error&DC_ERROR) && (error&MV_ERROR)))
925             continue;
926
927         if(is_intra_likely)
928             s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
929         else
930             s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
931     }
932
933     // change inter to intra blocks if no reference frames are available
934     if (!s->last_picture.data[0] && !s->next_picture.data[0])
935         for(i=0; i<s->mb_num; i++){
936             const int mb_xy= s->mb_index2xy[i];
937             if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
938                 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
939         }
940
941     /* handle inter blocks with damaged AC */
942     for(mb_y=0; mb_y<s->mb_height; mb_y++){
943         for(mb_x=0; mb_x<s->mb_width; mb_x++){
944             const int mb_xy= mb_x + mb_y * s->mb_stride;
945             const int mb_type= s->current_picture.mb_type[mb_xy];
946             int dir = !s->last_picture.data[0];
947             error= s->error_status_table[mb_xy];
948
949             if(IS_INTRA(mb_type)) continue; //intra
950             if(error&MV_ERROR) continue;              //inter with damaged MV
951             if(!(error&AC_ERROR)) continue;           //undamaged inter
952
953             s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
954             s->mb_intra=0;
955             s->mb_skipped=0;
956             if(IS_8X8(mb_type)){
957                 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
958                 int j;
959                 s->mv_type = MV_TYPE_8X8;
960                 for(j=0; j<4; j++){
961                     s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
962                     s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
963                 }
964             }else{
965                 s->mv_type = MV_TYPE_16X16;
966                 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
967                 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
968             }
969
970             s->dsp.clear_blocks(s->block[0]);
971
972             s->mb_x= mb_x;
973             s->mb_y= mb_y;
974             decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
975         }
976     }
977
978     /* guess MVs */
979     if(s->pict_type==FF_B_TYPE){
980         for(mb_y=0; mb_y<s->mb_height; mb_y++){
981             for(mb_x=0; mb_x<s->mb_width; mb_x++){
982                 int xy= mb_x*2 + mb_y*2*s->b8_stride;
983                 const int mb_xy= mb_x + mb_y * s->mb_stride;
984                 const int mb_type= s->current_picture.mb_type[mb_xy];
985                 error= s->error_status_table[mb_xy];
986
987                 if(IS_INTRA(mb_type)) continue;
988                 if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
989                 if(!(error&AC_ERROR)) continue;           //undamaged inter
990
991                 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
992                 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
993                 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
994                 s->mb_intra=0;
995                 s->mv_type = MV_TYPE_16X16;
996                 s->mb_skipped=0;
997
998                 if(s->pp_time){
999                     int time_pp= s->pp_time;
1000                     int time_pb= s->pb_time;
1001
1002                     s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
1003                     s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
1004                     s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1005                     s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1006                 }else{
1007                     s->mv[0][0][0]= 0;
1008                     s->mv[0][0][1]= 0;
1009                     s->mv[1][0][0]= 0;
1010                     s->mv[1][0][1]= 0;
1011                 }
1012
1013                 s->dsp.clear_blocks(s->block[0]);
1014                 s->mb_x= mb_x;
1015                 s->mb_y= mb_y;
1016                 decode_mb(s, 0);
1017             }
1018         }
1019     }else
1020         guess_mv(s);
1021
1022     /* the filters below are not XvMC compatible, skip them */
1023     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1024         goto ec_clean;
1025     /* fill DC for inter blocks */
1026     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1027         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1028             int dc, dcu, dcv, y, n;
1029             int16_t *dc_ptr;
1030             uint8_t *dest_y, *dest_cb, *dest_cr;
1031             const int mb_xy= mb_x + mb_y * s->mb_stride;
1032             const int mb_type= s->current_picture.mb_type[mb_xy];
1033
1034             error= s->error_status_table[mb_xy];
1035
1036             if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1037 //            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1038
1039             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1040             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1041             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1042
1043             dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1044             for(n=0; n<4; n++){
1045                 dc=0;
1046                 for(y=0; y<8; y++){
1047                     int x;
1048                     for(x=0; x<8; x++){
1049                        dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1050                     }
1051                 }
1052                 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1053             }
1054
1055             dcu=dcv=0;
1056             for(y=0; y<8; y++){
1057                 int x;
1058                 for(x=0; x<8; x++){
1059                     dcu+=dest_cb[x + y*(s->uvlinesize)];
1060                     dcv+=dest_cr[x + y*(s->uvlinesize)];
1061                 }
1062             }
1063             s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1064             s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1065         }
1066     }
1067 #if 1
1068     /* guess DC for damaged blocks */
1069     guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1070     guess_dc(s, s->dc_val[1], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1071     guess_dc(s, s->dc_val[2], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1072 #endif
1073     /* filter luma DC */
1074     filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1075
1076 #if 1
1077     /* render DC only intra */
1078     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1079         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1080             uint8_t *dest_y, *dest_cb, *dest_cr;
1081             const int mb_xy= mb_x + mb_y * s->mb_stride;
1082             const int mb_type= s->current_picture.mb_type[mb_xy];
1083
1084             error= s->error_status_table[mb_xy];
1085
1086             if(IS_INTER(mb_type)) continue;
1087             if(!(error&AC_ERROR)) continue;              //undamaged
1088
1089             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1090             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1091             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1092
1093             put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1094         }
1095     }
1096 #endif
1097
1098     if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1099         /* filter horizontal block boundaries */
1100         h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1101         h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1102         h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1103
1104         /* filter vertical block boundaries */
1105         v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1106         v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1107         v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1108     }
1109
1110 ec_clean:
1111     /* clean a few tables */
1112     for(i=0; i<s->mb_num; i++){
1113         const int mb_xy= s->mb_index2xy[i];
1114         int error= s->error_status_table[mb_xy];
1115
1116         if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1117             s->mbskip_table[mb_xy]=0;
1118         }
1119         s->mbintra_table[mb_xy]=1;
1120     }
1121 }