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