OSDN Git Service

Merge remote-tracking branch 'qatar/master'
[coroid/ffmpeg_saccubus.git] / 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         else if(s->last_picture.data[0] && s->last_picture.motion_val[0]){
385             const int mb_y= mb_xy / s->mb_stride;
386             const int mb_x= mb_xy % s->mb_stride;
387             const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
388             s->current_picture.motion_val[0][mot_index][0]= s->last_picture.motion_val[0][mot_index][0];
389             s->current_picture.motion_val[0][mot_index][1]= s->last_picture.motion_val[0][mot_index][1];
390             s->current_picture.ref_index[0][4*mb_xy]      = s->last_picture.ref_index[0][4*mb_xy];
391         }
392     }
393
394     if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
395         for(mb_y=0; mb_y<s->mb_height; mb_y++){
396             for(mb_x=0; mb_x<s->mb_width; mb_x++){
397                 const int mb_xy= mb_x + mb_y*s->mb_stride;
398
399                 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))  continue;
400                 if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
401
402                 s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
403                 s->mb_intra=0;
404                 s->mv_type = MV_TYPE_16X16;
405                 s->mb_skipped=0;
406
407                 s->dsp.clear_blocks(s->block[0]);
408
409                 s->mb_x= mb_x;
410                 s->mb_y= mb_y;
411                 s->mv[0][0][0]= 0;
412                 s->mv[0][0][1]= 0;
413                 decode_mb(s, 0);
414             }
415         }
416         return;
417     }
418
419     for(depth=0;; depth++){
420         int changed, pass, none_left;
421
422         none_left=1;
423         changed=1;
424         for(pass=0; (changed || pass<2) && pass<10; pass++){
425             int mb_x, mb_y;
426 int score_sum=0;
427
428             changed=0;
429             for(mb_y=0; mb_y<s->mb_height; mb_y++){
430                 for(mb_x=0; mb_x<s->mb_width; mb_x++){
431                     const int mb_xy= mb_x + mb_y*s->mb_stride;
432                     int mv_predictor[8][2]={{0}};
433                     int ref[8]={0};
434                     int pred_count=0;
435                     int j;
436                     int best_score=256*256*256*64;
437                     int best_pred=0;
438                     const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
439                     int prev_x= s->current_picture.motion_val[0][mot_index][0];
440                     int prev_y= s->current_picture.motion_val[0][mot_index][1];
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                     /* last MV */
539                     mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0];
540                     mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1];
541                     ref         [pred_count]   = s->current_picture.ref_index[0][4*mb_xy];
542                     pred_count++;
543
544                     s->mv_dir = MV_DIR_FORWARD;
545                     s->mb_intra=0;
546                     s->mv_type = MV_TYPE_16X16;
547                     s->mb_skipped=0;
548
549                     s->dsp.clear_blocks(s->block[0]);
550
551                     s->mb_x= mb_x;
552                     s->mb_y= mb_y;
553
554                     for(j=0; j<pred_count; j++){
555                         int score=0;
556                         uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
557
558                         s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
559                         s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
560
561                         if(ref[j]<0) //predictor intra or otherwise not available
562                             continue;
563
564                         decode_mb(s, ref[j]);
565
566                         if(mb_x>0 && fixed[mb_xy-1]){
567                             int k;
568                             for(k=0; k<16; k++)
569                                 score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize   ]);
570                         }
571                         if(mb_x+1<mb_width && fixed[mb_xy+1]){
572                             int k;
573                             for(k=0; k<16; k++)
574                                 score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
575                         }
576                         if(mb_y>0 && fixed[mb_xy-mb_stride]){
577                             int k;
578                             for(k=0; k<16; k++)
579                                 score += FFABS(src[k-s->linesize   ]-src[k               ]);
580                         }
581                         if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
582                             int k;
583                             for(k=0; k<16; k++)
584                                 score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
585                         }
586
587                         if(score <= best_score){ // <= will favor the last MV
588                             best_score= score;
589                             best_pred= j;
590                         }
591                     }
592 score_sum+= best_score;
593                     s->mv[0][0][0]= mv_predictor[best_pred][0];
594                     s->mv[0][0][1]= mv_predictor[best_pred][1];
595
596                     for(i=0; i<mot_step; i++)
597                         for(j=0; j<mot_step; j++){
598                             s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0];
599                             s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1];
600                         }
601
602                     decode_mb(s, ref[best_pred]);
603
604
605                     if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
606                         fixed[mb_xy]=MV_CHANGED;
607                         changed++;
608                     }else
609                         fixed[mb_xy]=MV_UNCHANGED;
610                 }
611             }
612
613 //            printf(".%d/%d", changed, score_sum); fflush(stdout);
614         }
615
616         if(none_left)
617             return;
618
619         for(i=0; i<s->mb_num; i++){
620             int mb_xy= s->mb_index2xy[i];
621             if(fixed[mb_xy])
622                 fixed[mb_xy]=MV_FROZEN;
623         }
624 //        printf(":"); fflush(stdout);
625     }
626 }
627
628 static int is_intra_more_likely(MpegEncContext *s){
629     int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
630
631     if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction
632
633     undamaged_count=0;
634     for(i=0; i<s->mb_num; i++){
635         const int mb_xy= s->mb_index2xy[i];
636         const int error= s->error_status_table[mb_xy];
637         if(!((error&DC_ERROR) && (error&MV_ERROR)))
638             undamaged_count++;
639     }
640
641     if(s->codec_id == CODEC_ID_H264){
642         H264Context *h= (void*)s;
643         if(h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0])
644             return 1;
645     }
646
647     if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
648
649     //prevent dsp.sad() check, that requires access to the image
650     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == AV_PICTURE_TYPE_I)
651         return 1;
652
653     skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
654     is_intra_likely=0;
655
656     j=0;
657     for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
658         for(mb_x= 0; mb_x<s->mb_width; mb_x++){
659             int error;
660             const int mb_xy= mb_x + mb_y*s->mb_stride;
661
662             error= s->error_status_table[mb_xy];
663             if((error&DC_ERROR) && (error&MV_ERROR))
664                 continue; //skip damaged
665
666             j++;
667             if((j%skip_amount) != 0) continue; //skip a few to speed things up
668
669             if(s->pict_type==AV_PICTURE_TYPE_I){
670                 uint8_t *mb_ptr     = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
671                 uint8_t *last_mb_ptr= s->last_picture.data   [0] + mb_x*16 + mb_y*16*s->linesize;
672
673                 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr                    , s->linesize, 16);
674                 // FIXME need await_progress() here
675                 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
676             }else{
677                 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
678                    is_intra_likely++;
679                 else
680                    is_intra_likely--;
681             }
682         }
683     }
684 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
685     return is_intra_likely > 0;
686 }
687
688 void ff_er_frame_start(MpegEncContext *s){
689     if(!s->error_recognition) return;
690
691     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));
692     s->error_count= 3*s->mb_num;
693 }
694
695 /**
696  * adds a slice.
697  * @param endx x component of the last macroblock, can be -1 for the last of the previous line
698  * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
699  *               error of the same type occurred
700  */
701 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
702     const int start_i= av_clip(startx + starty * s->mb_width    , 0, s->mb_num-1);
703     const int end_i  = av_clip(endx   + endy   * s->mb_width    , 0, s->mb_num);
704     const int start_xy= s->mb_index2xy[start_i];
705     const int end_xy  = s->mb_index2xy[end_i];
706     int mask= -1;
707
708     if(s->avctx->hwaccel)
709         return;
710
711     if(start_i > end_i || start_xy > end_xy){
712         av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
713         return;
714     }
715
716     if(!s->error_recognition) return;
717
718     mask &= ~VP_START;
719     if(status & (AC_ERROR|AC_END)){
720         mask &= ~(AC_ERROR|AC_END);
721         s->error_count -= end_i - start_i + 1;
722     }
723     if(status & (DC_ERROR|DC_END)){
724         mask &= ~(DC_ERROR|DC_END);
725         s->error_count -= end_i - start_i + 1;
726     }
727     if(status & (MV_ERROR|MV_END)){
728         mask &= ~(MV_ERROR|MV_END);
729         s->error_count -= end_i - start_i + 1;
730     }
731
732     if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
733
734     if(mask == ~0x7F){
735         memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
736     }else{
737         int i;
738         for(i=start_xy; i<end_xy; i++){
739             s->error_status_table[ i ] &= mask;
740         }
741     }
742
743     if(end_i == s->mb_num)
744         s->error_count= INT_MAX;
745     else{
746         s->error_status_table[end_xy] &= mask;
747         s->error_status_table[end_xy] |= status;
748     }
749
750     s->error_status_table[start_xy] |= VP_START;
751
752     if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
753         int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
754
755         prev_status &= ~ VP_START;
756         if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
757     }
758 }
759
760 void ff_er_frame_end(MpegEncContext *s){
761     int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
762     int distance;
763     int threshold_part[4]= {100,100,100};
764     int threshold= 50;
765     int is_intra_likely;
766     int size = s->b8_stride * 2 * s->mb_height;
767     Picture *pic= s->current_picture_ptr;
768
769     if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
770        s->avctx->hwaccel ||
771        s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
772        s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
773        s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
774
775     if(s->current_picture.motion_val[0] == NULL){
776         av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
777
778         for(i=0; i<2; i++){
779             pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
780             pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
781             pic->motion_val[i]= pic->motion_val_base[i]+4;
782         }
783         pic->motion_subsample_log2= 3;
784         s->current_picture= *s->current_picture_ptr;
785     }
786
787     if(s->avctx->debug&FF_DEBUG_ER){
788         for(mb_y=0; mb_y<s->mb_height; mb_y++){
789             for(mb_x=0; mb_x<s->mb_width; mb_x++){
790                 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
791
792                 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
793             }
794             av_log(s->avctx, AV_LOG_DEBUG, "\n");
795         }
796     }
797
798 #if 1
799     /* handle overlapping slices */
800     for(error_type=1; error_type<=3; error_type++){
801         int end_ok=0;
802
803         for(i=s->mb_num-1; i>=0; i--){
804             const int mb_xy= s->mb_index2xy[i];
805             int error= s->error_status_table[mb_xy];
806
807             if(error&(1<<error_type))
808                 end_ok=1;
809             if(error&(8<<error_type))
810                 end_ok=1;
811
812             if(!end_ok)
813                 s->error_status_table[mb_xy]|= 1<<error_type;
814
815             if(error&VP_START)
816                 end_ok=0;
817         }
818     }
819 #endif
820 #if 1
821     /* handle slices with partitions of different length */
822     if(s->partitioned_frame){
823         int end_ok=0;
824
825         for(i=s->mb_num-1; i>=0; i--){
826             const int mb_xy= s->mb_index2xy[i];
827             int error= s->error_status_table[mb_xy];
828
829             if(error&AC_END)
830                 end_ok=0;
831             if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
832                 end_ok=1;
833
834             if(!end_ok)
835                 s->error_status_table[mb_xy]|= AC_ERROR;
836
837             if(error&VP_START)
838                 end_ok=0;
839         }
840     }
841 #endif
842     /* handle missing slices */
843     if(s->error_recognition>=4){
844         int end_ok=1;
845
846         for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
847             const int mb_xy= s->mb_index2xy[i];
848             int error1= s->error_status_table[mb_xy  ];
849             int error2= s->error_status_table[s->mb_index2xy[i+1]];
850
851             if(error1&VP_START)
852                 end_ok=1;
853
854             if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
855                && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
856                && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
857                 end_ok=0;
858             }
859
860             if(!end_ok)
861                 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
862         }
863     }
864
865 #if 1
866     /* backward mark errors */
867     distance=9999999;
868     for(error_type=1; error_type<=3; error_type++){
869         for(i=s->mb_num-1; i>=0; i--){
870             const int mb_xy= s->mb_index2xy[i];
871             int error= s->error_status_table[mb_xy];
872
873             if(!s->mbskip_table[mb_xy]) //FIXME partition specific
874                 distance++;
875             if(error&(1<<error_type))
876                 distance= 0;
877
878             if(s->partitioned_frame){
879                 if(distance < threshold_part[error_type-1])
880                     s->error_status_table[mb_xy]|= 1<<error_type;
881             }else{
882                 if(distance < threshold)
883                     s->error_status_table[mb_xy]|= 1<<error_type;
884             }
885
886             if(error&VP_START)
887                 distance= 9999999;
888         }
889     }
890 #endif
891
892     /* forward mark errors */
893     error=0;
894     for(i=0; i<s->mb_num; i++){
895         const int mb_xy= s->mb_index2xy[i];
896         int old_error= s->error_status_table[mb_xy];
897
898         if(old_error&VP_START)
899             error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
900         else{
901             error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
902             s->error_status_table[mb_xy]|= error;
903         }
904     }
905 #if 1
906     /* handle not partitioned case */
907     if(!s->partitioned_frame){
908         for(i=0; i<s->mb_num; i++){
909             const int mb_xy= s->mb_index2xy[i];
910             error= s->error_status_table[mb_xy];
911             if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
912                 error|= AC_ERROR|DC_ERROR|MV_ERROR;
913             s->error_status_table[mb_xy]= error;
914         }
915     }
916 #endif
917
918     dc_error= ac_error= mv_error=0;
919     for(i=0; i<s->mb_num; i++){
920         const int mb_xy= s->mb_index2xy[i];
921         error= s->error_status_table[mb_xy];
922         if(error&DC_ERROR) dc_error ++;
923         if(error&AC_ERROR) ac_error ++;
924         if(error&MV_ERROR) mv_error ++;
925     }
926     av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
927
928     is_intra_likely= is_intra_more_likely(s);
929
930     /* set unknown mb-type to most likely */
931     for(i=0; i<s->mb_num; i++){
932         const int mb_xy= s->mb_index2xy[i];
933         error= s->error_status_table[mb_xy];
934         if(!((error&DC_ERROR) && (error&MV_ERROR)))
935             continue;
936
937         if(is_intra_likely)
938             s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
939         else
940             s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
941     }
942
943     // change inter to intra blocks if no reference frames are available
944     if (!s->last_picture.data[0] && !s->next_picture.data[0])
945         for(i=0; i<s->mb_num; i++){
946             const int mb_xy= s->mb_index2xy[i];
947             if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
948                 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
949         }
950
951     /* handle inter blocks with damaged AC */
952     for(mb_y=0; mb_y<s->mb_height; mb_y++){
953         for(mb_x=0; mb_x<s->mb_width; mb_x++){
954             const int mb_xy= mb_x + mb_y * s->mb_stride;
955             const int mb_type= s->current_picture.mb_type[mb_xy];
956             int dir = !s->last_picture.data[0];
957             error= s->error_status_table[mb_xy];
958
959             if(IS_INTRA(mb_type)) continue; //intra
960             if(error&MV_ERROR) continue;              //inter with damaged MV
961             if(!(error&AC_ERROR)) continue;           //undamaged inter
962
963             s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
964             s->mb_intra=0;
965             s->mb_skipped=0;
966             if(IS_8X8(mb_type)){
967                 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
968                 int j;
969                 s->mv_type = MV_TYPE_8X8;
970                 for(j=0; j<4; j++){
971                     s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
972                     s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
973                 }
974             }else{
975                 s->mv_type = MV_TYPE_16X16;
976                 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
977                 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
978             }
979
980             s->dsp.clear_blocks(s->block[0]);
981
982             s->mb_x= mb_x;
983             s->mb_y= mb_y;
984             decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
985         }
986     }
987
988     /* guess MVs */
989     if(s->pict_type==AV_PICTURE_TYPE_B){
990         for(mb_y=0; mb_y<s->mb_height; mb_y++){
991             for(mb_x=0; mb_x<s->mb_width; mb_x++){
992                 int xy= mb_x*2 + mb_y*2*s->b8_stride;
993                 const int mb_xy= mb_x + mb_y * s->mb_stride;
994                 const int mb_type= s->current_picture.mb_type[mb_xy];
995                 error= s->error_status_table[mb_xy];
996
997                 if(IS_INTRA(mb_type)) continue;
998                 if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
999                 if(!(error&AC_ERROR)) continue;           //undamaged inter
1000
1001                 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
1002                 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
1003                 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
1004                 s->mb_intra=0;
1005                 s->mv_type = MV_TYPE_16X16;
1006                 s->mb_skipped=0;
1007
1008                 if(s->pp_time){
1009                     int time_pp= s->pp_time;
1010                     int time_pb= s->pb_time;
1011
1012                     // FIXME await_progress here
1013                     s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
1014                     s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
1015                     s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1016                     s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1017                 }else{
1018                     s->mv[0][0][0]= 0;
1019                     s->mv[0][0][1]= 0;
1020                     s->mv[1][0][0]= 0;
1021                     s->mv[1][0][1]= 0;
1022                 }
1023
1024                 s->dsp.clear_blocks(s->block[0]);
1025                 s->mb_x= mb_x;
1026                 s->mb_y= mb_y;
1027                 decode_mb(s, 0);
1028             }
1029         }
1030     }else
1031         guess_mv(s);
1032
1033     /* the filters below are not XvMC compatible, skip them */
1034     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1035         goto ec_clean;
1036     /* fill DC for inter blocks */
1037     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1038         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1039             int dc, dcu, dcv, y, n;
1040             int16_t *dc_ptr;
1041             uint8_t *dest_y, *dest_cb, *dest_cr;
1042             const int mb_xy= mb_x + mb_y * s->mb_stride;
1043             const int mb_type= s->current_picture.mb_type[mb_xy];
1044
1045             error= s->error_status_table[mb_xy];
1046
1047             if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1048 //            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1049
1050             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1051             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1052             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1053
1054             dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1055             for(n=0; n<4; n++){
1056                 dc=0;
1057                 for(y=0; y<8; y++){
1058                     int x;
1059                     for(x=0; x<8; x++){
1060                        dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1061                     }
1062                 }
1063                 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1064             }
1065
1066             dcu=dcv=0;
1067             for(y=0; y<8; y++){
1068                 int x;
1069                 for(x=0; x<8; x++){
1070                     dcu+=dest_cb[x + y*(s->uvlinesize)];
1071                     dcv+=dest_cr[x + y*(s->uvlinesize)];
1072                 }
1073             }
1074             s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1075             s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1076         }
1077     }
1078 #if 1
1079     /* guess DC for damaged blocks */
1080     guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1081     guess_dc(s, s->dc_val[1], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1082     guess_dc(s, s->dc_val[2], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1083 #endif
1084     /* filter luma DC */
1085     filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1086
1087 #if 1
1088     /* render DC only intra */
1089     for(mb_y=0; mb_y<s->mb_height; mb_y++){
1090         for(mb_x=0; mb_x<s->mb_width; mb_x++){
1091             uint8_t *dest_y, *dest_cb, *dest_cr;
1092             const int mb_xy= mb_x + mb_y * s->mb_stride;
1093             const int mb_type= s->current_picture.mb_type[mb_xy];
1094
1095             error= s->error_status_table[mb_xy];
1096
1097             if(IS_INTER(mb_type)) continue;
1098             if(!(error&AC_ERROR)) continue;              //undamaged
1099
1100             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1101             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1102             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1103
1104             put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1105         }
1106     }
1107 #endif
1108
1109     if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1110         /* filter horizontal block boundaries */
1111         h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1112         h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1113         h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1114
1115         /* filter vertical block boundaries */
1116         v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1117         v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1118         v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1119     }
1120
1121 ec_clean:
1122     /* clean a few tables */
1123     for(i=0; i<s->mb_num; i++){
1124         const int mb_xy= s->mb_index2xy[i];
1125         int error= s->error_status_table[mb_xy];
1126
1127         if(s->pict_type!=AV_PICTURE_TYPE_B && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1128             s->mbskip_table[mb_xy]=0;
1129         }
1130         s->mbintra_table[mb_xy]=1;
1131     }
1132 }