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