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