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