Statistics
| Branch: | Revision:

ffmpeg / libavcodec / error_resilience.c @ 673fc638

History | View | Annotate | Download (42.6 KB)

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 libavcodec/error_resilience.c
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

    
35
/*
36
 * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264)
37
 * but error concealment must support both h264 and h263 thus we must undo this
38
 */
39
#undef mb_intra
40

    
41
static void decode_mb(MpegEncContext *s, int ref){
42
    s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize  ) + s->mb_x * 16;
43
    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);
44
    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);
45

    
46
    if(s->codec_id == CODEC_ID_H264){
47
        H264Context *h= (void*)s;
48
        h->mb_xy= s->mb_x + s->mb_y*s->mb_stride;
49
        memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
50
        assert(ref>=0);
51
        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
52
            ref=0;
53
        fill_rectangle(&s->current_picture.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1);
54
        fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
55
        fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4);
56
        assert(!FRAME_MBAFF);
57
        ff_h264_hl_decode_mb(h);
58
    }else{
59
        assert(ref==0);
60
    MPV_decode_mb(s, s->block);
61
    }
62
}
63

    
64
/**
65
 * @param stride the number of MVs to get to the next row
66
 * @param mv_step the number of MVs per row or column in a macroblock
67
 */
68
static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){
69
    if(s->codec_id == CODEC_ID_H264){
70
        H264Context *h= (void*)s;
71
        assert(s->quarter_sample);
72
        *mv_step= 4;
73
        *stride= h->b_stride;
74
    }else{
75
        *mv_step= 2;
76
        *stride= s->b8_stride;
77
    }
78
}
79

    
80
/**
81
 * replaces the current MB with a flat dc only version.
82
 */
83
static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
84
{
85
    int dc, dcu, dcv, y, i;
86
    for(i=0; i<4; i++){
87
        dc= s->dc_val[0][mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*s->b8_stride];
88
        if(dc<0) dc=0;
89
        else if(dc>2040) dc=2040;
90
        for(y=0; y<8; y++){
91
            int x;
92
            for(x=0; x<8; x++){
93
                dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
94
            }
95
        }
96
    }
97
    dcu = s->dc_val[1][mb_x + mb_y*s->mb_stride];
98
    dcv = s->dc_val[2][mb_x + mb_y*s->mb_stride];
99
    if     (dcu<0   ) dcu=0;
100
    else if(dcu>2040) dcu=2040;
101
    if     (dcv<0   ) dcv=0;
102
    else if(dcv>2040) dcv=2040;
103
    for(y=0; y<8; y++){
104
        int x;
105
        for(x=0; x<8; x++){
106
            dest_cb[x + y*(s->uvlinesize)]= dcu/8;
107
            dest_cr[x + y*(s->uvlinesize)]= dcv/8;
108
        }
109
    }
110
}
111

    
112
static void filter181(int16_t *data, int width, int height, int stride){
113
    int x,y;
114

    
115
    /* horizontal filter */
116
    for(y=1; y<height-1; y++){
117
        int prev_dc= data[0 + y*stride];
118

    
119
        for(x=1; x<width-1; x++){
120
            int dc;
121

    
122
            dc= - prev_dc
123
                + data[x     + y*stride]*8
124
                - data[x + 1 + y*stride];
125
            dc= (dc*10923 + 32768)>>16;
126
            prev_dc= data[x + y*stride];
127
            data[x + y*stride]= dc;
128
        }
129
    }
130

    
131
    /* vertical filter */
132
    for(x=1; x<width-1; x++){
133
        int prev_dc= data[x];
134

    
135
        for(y=1; y<height-1; y++){
136
            int dc;
137

    
138
            dc= - prev_dc
139
                + data[x +  y   *stride]*8
140
                - data[x + (y+1)*stride];
141
            dc= (dc*10923 + 32768)>>16;
142
            prev_dc= data[x + y*stride];
143
            data[x + y*stride]= dc;
144
        }
145
    }
146
}
147

    
148
/**
149
 * guess the dc of blocks which do not have an undamaged dc
150
 * @param w     width in 8 pixel blocks
151
 * @param h     height in 8 pixel blocks
152
 */
153
static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
154
    int b_x, b_y;
155

    
156
    for(b_y=0; b_y<h; b_y++){
157
        for(b_x=0; b_x<w; b_x++){
158
            int color[4]={1024,1024,1024,1024};
159
            int distance[4]={9999,9999,9999,9999};
160
            int mb_index, error, j;
161
            int64_t guess, weight_sum;
162

    
163
            mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
164

    
165
            error= s->error_status_table[mb_index];
166

    
167
            if(IS_INTER(s->current_picture.mb_type[mb_index])) continue; //inter
168
            if(!(error&DC_ERROR)) continue;           //dc-ok
169

    
170
            /* right block */
171
            for(j=b_x+1; j<w; j++){
172
                int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
173
                int error_j= s->error_status_table[mb_index_j];
174
                int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
175
                if(intra_j==0 || !(error_j&DC_ERROR)){
176
                    color[0]= dc[j + b_y*stride];
177
                    distance[0]= j-b_x;
178
                    break;
179
                }
180
            }
181

    
182
            /* left block */
183
            for(j=b_x-1; j>=0; j--){
184
                int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
185
                int error_j= s->error_status_table[mb_index_j];
186
                int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
187
                if(intra_j==0 || !(error_j&DC_ERROR)){
188
                    color[1]= dc[j + b_y*stride];
189
                    distance[1]= b_x-j;
190
                    break;
191
                }
192
            }
193

    
194
            /* bottom block */
195
            for(j=b_y+1; j<h; j++){
196
                int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
197
                int error_j= s->error_status_table[mb_index_j];
198
                int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
199
                if(intra_j==0 || !(error_j&DC_ERROR)){
200
                    color[2]= dc[b_x + j*stride];
201
                    distance[2]= j-b_y;
202
                    break;
203
                }
204
            }
205

    
206
            /* top block */
207
            for(j=b_y-1; j>=0; j--){
208
                int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
209
                int error_j= s->error_status_table[mb_index_j];
210
                int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
211
                if(intra_j==0 || !(error_j&DC_ERROR)){
212
                    color[3]= dc[b_x + j*stride];
213
                    distance[3]= b_y-j;
214
                    break;
215
                }
216
            }
217

    
218
            weight_sum=0;
219
            guess=0;
220
            for(j=0; j<4; j++){
221
                int64_t weight= 256*256*256*16/distance[j];
222
                guess+= weight*(int64_t)color[j];
223
                weight_sum+= weight;
224
            }
225
            guess= (guess + weight_sum/2) / weight_sum;
226

    
227
            dc[b_x + b_y*stride]= guess;
228
        }
229
    }
230
}
231

    
232
/**
233
 * simple horizontal deblocking filter used for error resilience
234
 * @param w     width in 8 pixel blocks
235
 * @param h     height in 8 pixel blocks
236
 */
237
static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
238
    int b_x, b_y, mvx_stride, mvy_stride;
239
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
240
    set_mv_strides(s, &mvx_stride, &mvy_stride);
241
    mvx_stride >>= is_luma;
242
    mvy_stride *= mvx_stride;
243

    
244
    for(b_y=0; b_y<h; b_y++){
245
        for(b_x=0; b_x<w-1; b_x++){
246
            int y;
247
            int left_status = s->error_status_table[( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_stride];
248
            int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride];
249
            int left_intra=   IS_INTRA(s->current_picture.mb_type      [( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_stride]);
250
            int right_intra=  IS_INTRA(s->current_picture.mb_type      [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]);
251
            int left_damage =  left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
252
            int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
253
            int offset= b_x*8 + b_y*stride*8;
254
            int16_t *left_mv=  s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride* b_x   ];
255
            int16_t *right_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride*(b_x+1)];
256

    
257
            if(!(left_damage||right_damage)) continue; // both undamaged
258

    
259
            if(   (!left_intra) && (!right_intra)
260
               && FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue;
261

    
262
            for(y=0; y<8; y++){
263
                int a,b,c,d;
264

    
265
                a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
266
                b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
267
                c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
268

    
269
                d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1);
270
                d= FFMAX(d, 0);
271
                if(b<0) d= -d;
272

    
273
                if(d==0) continue;
274

    
275
                if(!(left_damage && right_damage))
276
                    d= d*16/9;
277

    
278
                if(left_damage){
279
                    dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
280
                    dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
281
                    dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
282
                    dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
283
                }
284
                if(right_damage){
285
                    dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
286
                    dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
287
                    dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
288
                    dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
289
                }
290
            }
291
        }
292
    }
293
}
294

    
295
/**
296
 * simple vertical deblocking filter used for error resilience
297
 * @param w     width in 8 pixel blocks
298
 * @param h     height in 8 pixel blocks
299
 */
300
static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
301
    int b_x, b_y, mvx_stride, mvy_stride;
302
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
303
    set_mv_strides(s, &mvx_stride, &mvy_stride);
304
    mvx_stride >>= is_luma;
305
    mvy_stride *= mvx_stride;
306

    
307
    for(b_y=0; b_y<h-1; b_y++){
308
        for(b_x=0; b_x<w; b_x++){
309
            int x;
310
            int top_status   = s->error_status_table[(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_stride];
311
            int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride];
312
            int top_intra=     IS_INTRA(s->current_picture.mb_type      [(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_stride]);
313
            int bottom_intra=  IS_INTRA(s->current_picture.mb_type      [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]);
314
            int top_damage =      top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
315
            int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
316
            int offset= b_x*8 + b_y*stride*8;
317
            int16_t *top_mv=    s->current_picture.motion_val[0][mvy_stride* b_y    + mvx_stride*b_x];
318
            int16_t *bottom_mv= s->current_picture.motion_val[0][mvy_stride*(b_y+1) + mvx_stride*b_x];
319

    
320
            if(!(top_damage||bottom_damage)) continue; // both undamaged
321

    
322
            if(   (!top_intra) && (!bottom_intra)
323
               && FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue;
324

    
325
            for(x=0; x<8; x++){
326
                int a,b,c,d;
327

    
328
                a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
329
                b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
330
                c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
331

    
332
                d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1);
333
                d= FFMAX(d, 0);
334
                if(b<0) d= -d;
335

    
336
                if(d==0) continue;
337

    
338
                if(!(top_damage && bottom_damage))
339
                    d= d*16/9;
340

    
341
                if(top_damage){
342
                    dst[offset + x +  7*stride] = cm[dst[offset + x +  7*stride] + ((d*7)>>4)];
343
                    dst[offset + x +  6*stride] = cm[dst[offset + x +  6*stride] + ((d*5)>>4)];
344
                    dst[offset + x +  5*stride] = cm[dst[offset + x +  5*stride] + ((d*3)>>4)];
345
                    dst[offset + x +  4*stride] = cm[dst[offset + x +  4*stride] + ((d*1)>>4)];
346
                }
347
                if(bottom_damage){
348
                    dst[offset + x +  8*stride] = cm[dst[offset + x +  8*stride] - ((d*7)>>4)];
349
                    dst[offset + x +  9*stride] = cm[dst[offset + x +  9*stride] - ((d*5)>>4)];
350
                    dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
351
                    dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
352
                }
353
            }
354
        }
355
    }
356
}
357

    
358
static void guess_mv(MpegEncContext *s){
359
    uint8_t fixed[s->mb_stride * s->mb_height];
360
#define MV_FROZEN    3
361
#define MV_CHANGED   2
362
#define MV_UNCHANGED 1
363
    const int mb_stride = s->mb_stride;
364
    const int mb_width = s->mb_width;
365
    const int mb_height= s->mb_height;
366
    int i, depth, num_avail;
367
    int mb_x, mb_y, mot_step, mot_stride;
368

    
369
    set_mv_strides(s, &mot_step, &mot_stride);
370

    
371
    num_avail=0;
372
    for(i=0; i<s->mb_num; i++){
373
        const int mb_xy= s->mb_index2xy[ i ];
374
        int f=0;
375
        int error= s->error_status_table[mb_xy];
376

    
377
        if(IS_INTRA(s->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check
378
        if(!(error&MV_ERROR)) f=MV_FROZEN;           //inter with undamaged MV
379

    
380
        fixed[mb_xy]= f;
381
        if(f==MV_FROZEN)
382
            num_avail++;
383
    }
384

    
385
    if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
386
        for(mb_y=0; mb_y<s->mb_height; mb_y++){
387
            for(mb_x=0; mb_x<s->mb_width; mb_x++){
388
                const int mb_xy= mb_x + mb_y*s->mb_stride;
389

    
390
                if(IS_INTRA(s->current_picture.mb_type[mb_xy]))  continue;
391
                if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
392

    
393
                s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
394
                s->mb_intra=0;
395
                s->mv_type = MV_TYPE_16X16;
396
                s->mb_skipped=0;
397

    
398
                s->dsp.clear_blocks(s->block[0]);
399

    
400
                s->mb_x= mb_x;
401
                s->mb_y= mb_y;
402
                s->mv[0][0][0]= 0;
403
                s->mv[0][0][1]= 0;
404
                decode_mb(s, 0);
405
            }
406
        }
407
        return;
408
    }
409

    
410
    for(depth=0;; depth++){
411
        int changed, pass, none_left;
412

    
413
        none_left=1;
414
        changed=1;
415
        for(pass=0; (changed || pass<2) && pass<10; pass++){
416
            int mb_x, mb_y;
417
int score_sum=0;
418

    
419
            changed=0;
420
            for(mb_y=0; mb_y<s->mb_height; mb_y++){
421
                for(mb_x=0; mb_x<s->mb_width; mb_x++){
422
                    const int mb_xy= mb_x + mb_y*s->mb_stride;
423
                    int mv_predictor[8][2]={{0}};
424
                    int ref[8]={0};
425
                    int pred_count=0;
426
                    int j;
427
                    int best_score=256*256*256*64;
428
                    int best_pred=0;
429
                    const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
430
                    int prev_x= s->current_picture.motion_val[0][mot_index][0];
431
                    int prev_y= s->current_picture.motion_val[0][mot_index][1];
432

    
433
                    if((mb_x^mb_y^pass)&1) continue;
434

    
435
                    if(fixed[mb_xy]==MV_FROZEN) continue;
436
                    assert(!IS_INTRA(s->current_picture.mb_type[mb_xy]));
437
                    assert(s->last_picture_ptr && s->last_picture_ptr->data[0]);
438

    
439
                    j=0;
440
                    if(mb_x>0           && fixed[mb_xy-1        ]==MV_FROZEN) j=1;
441
                    if(mb_x+1<mb_width  && fixed[mb_xy+1        ]==MV_FROZEN) j=1;
442
                    if(mb_y>0           && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1;
443
                    if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1;
444
                    if(j==0) continue;
445

    
446
                    j=0;
447
                    if(mb_x>0           && fixed[mb_xy-1        ]==MV_CHANGED) j=1;
448
                    if(mb_x+1<mb_width  && fixed[mb_xy+1        ]==MV_CHANGED) j=1;
449
                    if(mb_y>0           && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1;
450
                    if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1;
451
                    if(j==0 && pass>1) continue;
452

    
453
                    none_left=0;
454

    
455
                    if(mb_x>0 && fixed[mb_xy-1]){
456
                        mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0];
457
                        mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1];
458
                        ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy-1)];
459
                        pred_count++;
460
                    }
461
                    if(mb_x+1<mb_width && fixed[mb_xy+1]){
462
                        mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_step][0];
463
                        mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1];
464
                        ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy+1)];
465
                        pred_count++;
466
                    }
467
                    if(mb_y>0 && fixed[mb_xy-mb_stride]){
468
                        mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0];
469
                        mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1];
470
                        ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)];
471
                        pred_count++;
472
                    }
473
                    if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
474
                        mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][0];
475
                        mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1];
476
                        ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)];
477
                        pred_count++;
478
                    }
479
                    if(pred_count==0) continue;
480

    
481
                    if(pred_count>1){
482
                        int sum_x=0, sum_y=0, sum_r=0;
483
                        int max_x, max_y, min_x, min_y, max_r, min_r;
484

    
485
                        for(j=0; j<pred_count; j++){
486
                            sum_x+= mv_predictor[j][0];
487
                            sum_y+= mv_predictor[j][1];
488
                            sum_r+= ref[j];
489
                            if(j && ref[j] != ref[j-1])
490
                                goto skip_mean_and_median;
491
                        }
492

    
493
                        /* mean */
494
                        mv_predictor[pred_count][0] = sum_x/j;
495
                        mv_predictor[pred_count][1] = sum_y/j;
496
                        ref         [pred_count]    = sum_r/j;
497

    
498
                        /* median */
499
                        if(pred_count>=3){
500
                            min_y= min_x= min_r= 99999;
501
                            max_y= max_x= max_r=-99999;
502
                        }else{
503
                            min_x=min_y=max_x=max_y=min_r=max_r=0;
504
                        }
505
                        for(j=0; j<pred_count; j++){
506
                            max_x= FFMAX(max_x, mv_predictor[j][0]);
507
                            max_y= FFMAX(max_y, mv_predictor[j][1]);
508
                            max_r= FFMAX(max_r, ref[j]);
509
                            min_x= FFMIN(min_x, mv_predictor[j][0]);
510
                            min_y= FFMIN(min_y, mv_predictor[j][1]);
511
                            min_r= FFMIN(min_r, ref[j]);
512
                        }
513
                        mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
514
                        mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
515
                        ref         [pred_count+1]    = sum_r - max_r - min_r;
516

    
517
                        if(pred_count==4){
518
                            mv_predictor[pred_count+1][0] /= 2;
519
                            mv_predictor[pred_count+1][1] /= 2;
520
                            ref         [pred_count+1]    /= 2;
521
                        }
522
                        pred_count+=2;
523
                    }
524
skip_mean_and_median:
525

    
526
                    /* zero MV */
527
                    pred_count++;
528

    
529
                    /* last MV */
530
                    mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0];
531
                    mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1];
532
                    ref         [pred_count]   = s->current_picture.ref_index[0][4*mb_xy];
533
                    pred_count++;
534

    
535
                    s->mv_dir = MV_DIR_FORWARD;
536
                    s->mb_intra=0;
537
                    s->mv_type = MV_TYPE_16X16;
538
                    s->mb_skipped=0;
539

    
540
                    s->dsp.clear_blocks(s->block[0]);
541

    
542
                    s->mb_x= mb_x;
543
                    s->mb_y= mb_y;
544

    
545
                    for(j=0; j<pred_count; j++){
546
                        int score=0;
547
                        uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
548

    
549
                        s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
550
                        s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
551

    
552
                        if(ref[j]<0) //predictor intra or otherwise not available
553
                            continue;
554

    
555
                        decode_mb(s, ref[j]);
556

    
557
                        if(mb_x>0 && fixed[mb_xy-1]){
558
                            int k;
559
                            for(k=0; k<16; k++)
560
                                score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize   ]);
561
                        }
562
                        if(mb_x+1<mb_width && fixed[mb_xy+1]){
563
                            int k;
564
                            for(k=0; k<16; k++)
565
                                score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
566
                        }
567
                        if(mb_y>0 && fixed[mb_xy-mb_stride]){
568
                            int k;
569
                            for(k=0; k<16; k++)
570
                                score += FFABS(src[k-s->linesize   ]-src[k               ]);
571
                        }
572
                        if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
573
                            int k;
574
                            for(k=0; k<16; k++)
575
                                score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
576
                        }
577

    
578
                        if(score <= best_score){ // <= will favor the last MV
579
                            best_score= score;
580
                            best_pred= j;
581
                        }
582
                    }
583
score_sum+= best_score;
584
                    s->mv[0][0][0]= mv_predictor[best_pred][0];
585
                    s->mv[0][0][1]= mv_predictor[best_pred][1];
586

    
587
                    for(i=0; i<mot_step; i++)
588
                        for(j=0; j<mot_step; j++){
589
                            s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0];
590
                            s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1];
591
                        }
592

    
593
                    decode_mb(s, ref[best_pred]);
594

    
595

    
596
                    if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
597
                        fixed[mb_xy]=MV_CHANGED;
598
                        changed++;
599
                    }else
600
                        fixed[mb_xy]=MV_UNCHANGED;
601
                }
602
            }
603

    
604
//            printf(".%d/%d", changed, score_sum); fflush(stdout);
605
        }
606

    
607
        if(none_left)
608
            return;
609

    
610
        for(i=0; i<s->mb_num; i++){
611
            int mb_xy= s->mb_index2xy[i];
612
            if(fixed[mb_xy])
613
                fixed[mb_xy]=MV_FROZEN;
614
        }
615
//        printf(":"); fflush(stdout);
616
    }
617
}
618

    
619
static int is_intra_more_likely(MpegEncContext *s){
620
    int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
621

    
622
    if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction
623

    
624
    undamaged_count=0;
625
    for(i=0; i<s->mb_num; i++){
626
        const int mb_xy= s->mb_index2xy[i];
627
        const int error= s->error_status_table[mb_xy];
628
        if(!((error&DC_ERROR) && (error&MV_ERROR)))
629
            undamaged_count++;
630
    }
631

    
632
    if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
633

    
634
    //prevent dsp.sad() check, that requires access to the image
635
    if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE)
636
        return 1;
637

    
638
    skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
639
    is_intra_likely=0;
640

    
641
    j=0;
642
    for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
643
        for(mb_x= 0; mb_x<s->mb_width; mb_x++){
644
            int error;
645
            const int mb_xy= mb_x + mb_y*s->mb_stride;
646

    
647
            error= s->error_status_table[mb_xy];
648
            if((error&DC_ERROR) && (error&MV_ERROR))
649
                continue; //skip damaged
650

    
651
            j++;
652
            if((j%skip_amount) != 0) continue; //skip a few to speed things up
653

    
654
            if(s->pict_type==FF_I_TYPE){
655
                uint8_t *mb_ptr     = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
656
                uint8_t *last_mb_ptr= s->last_picture.data   [0] + mb_x*16 + mb_y*16*s->linesize;
657

    
658
                is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr                    , s->linesize, 16);
659
                is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
660
            }else{
661
                if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
662
                   is_intra_likely++;
663
                else
664
                   is_intra_likely--;
665
            }
666
        }
667
    }
668
//printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
669
    return is_intra_likely > 0;
670
}
671

    
672
void ff_er_frame_start(MpegEncContext *s){
673
    if(!s->error_recognition) return;
674

    
675
    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));
676
    s->error_count= 3*s->mb_num;
677
}
678

    
679
/**
680
 * adds a slice.
681
 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
682
 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
683
 *               error of the same type occurred
684
 */
685
void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
686
    const int start_i= av_clip(startx + starty * s->mb_width    , 0, s->mb_num-1);
687
    const int end_i  = av_clip(endx   + endy   * s->mb_width    , 0, s->mb_num);
688
    const int start_xy= s->mb_index2xy[start_i];
689
    const int end_xy  = s->mb_index2xy[end_i];
690
    int mask= -1;
691

    
692
    if(s->avctx->hwaccel)
693
        return;
694

    
695
    if(start_i > end_i || start_xy > end_xy){
696
        av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
697
        return;
698
    }
699

    
700
    if(!s->error_recognition) return;
701

    
702
    mask &= ~VP_START;
703
    if(status & (AC_ERROR|AC_END)){
704
        mask &= ~(AC_ERROR|AC_END);
705
        s->error_count -= end_i - start_i + 1;
706
    }
707
    if(status & (DC_ERROR|DC_END)){
708
        mask &= ~(DC_ERROR|DC_END);
709
        s->error_count -= end_i - start_i + 1;
710
    }
711
    if(status & (MV_ERROR|MV_END)){
712
        mask &= ~(MV_ERROR|MV_END);
713
        s->error_count -= end_i - start_i + 1;
714
    }
715

    
716
    if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
717

    
718
    if(mask == ~0x7F){
719
        memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
720
    }else{
721
        int i;
722
        for(i=start_xy; i<end_xy; i++){
723
            s->error_status_table[ i ] &= mask;
724
        }
725
    }
726

    
727
    if(end_i == s->mb_num)
728
        s->error_count= INT_MAX;
729
    else{
730
        s->error_status_table[end_xy] &= mask;
731
        s->error_status_table[end_xy] |= status;
732
    }
733

    
734
    s->error_status_table[start_xy] |= VP_START;
735

    
736
    if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
737
        int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
738

    
739
        prev_status &= ~ VP_START;
740
        if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
741
    }
742
}
743

    
744
void ff_er_frame_end(MpegEncContext *s){
745
    int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
746
    int distance;
747
    int threshold_part[4]= {100,100,100};
748
    int threshold= 50;
749
    int is_intra_likely;
750
    int size = s->b8_stride * 2 * s->mb_height;
751
    Picture *pic= s->current_picture_ptr;
752

    
753
    if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
754
       s->avctx->hwaccel ||
755
       s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
756
       s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
757
       s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
758

    
759
    if(s->current_picture.motion_val[0] == NULL){
760
        av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
761

    
762
        for(i=0; i<2; i++){
763
            pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
764
            pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
765
            pic->motion_val[i]= pic->motion_val_base[i]+4;
766
        }
767
        pic->motion_subsample_log2= 3;
768
        s->current_picture= *s->current_picture_ptr;
769
    }
770

    
771
    if(s->avctx->debug&FF_DEBUG_ER){
772
        for(mb_y=0; mb_y<s->mb_height; mb_y++){
773
            for(mb_x=0; mb_x<s->mb_width; mb_x++){
774
                int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
775

    
776
                av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
777
            }
778
            av_log(s->avctx, AV_LOG_DEBUG, "\n");
779
        }
780
    }
781

    
782
#if 1
783
    /* handle overlapping slices */
784
    for(error_type=1; error_type<=3; error_type++){
785
        int end_ok=0;
786

    
787
        for(i=s->mb_num-1; i>=0; i--){
788
            const int mb_xy= s->mb_index2xy[i];
789
            int error= s->error_status_table[mb_xy];
790

    
791
            if(error&(1<<error_type))
792
                end_ok=1;
793
            if(error&(8<<error_type))
794
                end_ok=1;
795

    
796
            if(!end_ok)
797
                s->error_status_table[mb_xy]|= 1<<error_type;
798

    
799
            if(error&VP_START)
800
                end_ok=0;
801
        }
802
    }
803
#endif
804
#if 1
805
    /* handle slices with partitions of different length */
806
    if(s->partitioned_frame){
807
        int end_ok=0;
808

    
809
        for(i=s->mb_num-1; i>=0; i--){
810
            const int mb_xy= s->mb_index2xy[i];
811
            int error= s->error_status_table[mb_xy];
812

    
813
            if(error&AC_END)
814
                end_ok=0;
815
            if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
816
                end_ok=1;
817

    
818
            if(!end_ok)
819
                s->error_status_table[mb_xy]|= AC_ERROR;
820

    
821
            if(error&VP_START)
822
                end_ok=0;
823
        }
824
    }
825
#endif
826
    /* handle missing slices */
827
    if(s->error_recognition>=4){
828
        int end_ok=1;
829

    
830
        for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
831
            const int mb_xy= s->mb_index2xy[i];
832
            int error1= s->error_status_table[mb_xy  ];
833
            int error2= s->error_status_table[s->mb_index2xy[i+1]];
834

    
835
            if(error1&VP_START)
836
                end_ok=1;
837

    
838
            if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
839
               && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
840
               && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
841
                end_ok=0;
842
            }
843

    
844
            if(!end_ok)
845
                s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
846
        }
847
    }
848

    
849
#if 1
850
    /* backward mark errors */
851
    distance=9999999;
852
    for(error_type=1; error_type<=3; error_type++){
853
        for(i=s->mb_num-1; i>=0; i--){
854
            const int mb_xy= s->mb_index2xy[i];
855
            int error= s->error_status_table[mb_xy];
856

    
857
            if(!s->mbskip_table[mb_xy]) //FIXME partition specific
858
                distance++;
859
            if(error&(1<<error_type))
860
                distance= 0;
861

    
862
            if(s->partitioned_frame){
863
                if(distance < threshold_part[error_type-1])
864
                    s->error_status_table[mb_xy]|= 1<<error_type;
865
            }else{
866
                if(distance < threshold)
867
                    s->error_status_table[mb_xy]|= 1<<error_type;
868
            }
869

    
870
            if(error&VP_START)
871
                distance= 9999999;
872
        }
873
    }
874
#endif
875

    
876
    /* forward mark errors */
877
    error=0;
878
    for(i=0; i<s->mb_num; i++){
879
        const int mb_xy= s->mb_index2xy[i];
880
        int old_error= s->error_status_table[mb_xy];
881

    
882
        if(old_error&VP_START)
883
            error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
884
        else{
885
            error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
886
            s->error_status_table[mb_xy]|= error;
887
        }
888
    }
889
#if 1
890
    /* handle not partitioned case */
891
    if(!s->partitioned_frame){
892
        for(i=0; i<s->mb_num; i++){
893
            const int mb_xy= s->mb_index2xy[i];
894
            error= s->error_status_table[mb_xy];
895
            if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
896
                error|= AC_ERROR|DC_ERROR|MV_ERROR;
897
            s->error_status_table[mb_xy]= error;
898
        }
899
    }
900
#endif
901

    
902
    dc_error= ac_error= mv_error=0;
903
    for(i=0; i<s->mb_num; i++){
904
        const int mb_xy= s->mb_index2xy[i];
905
        error= s->error_status_table[mb_xy];
906
        if(error&DC_ERROR) dc_error ++;
907
        if(error&AC_ERROR) ac_error ++;
908
        if(error&MV_ERROR) mv_error ++;
909
    }
910
    av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
911

    
912
    is_intra_likely= is_intra_more_likely(s);
913

    
914
    /* set unknown mb-type to most likely */
915
    for(i=0; i<s->mb_num; i++){
916
        const int mb_xy= s->mb_index2xy[i];
917
        error= s->error_status_table[mb_xy];
918
        if(!((error&DC_ERROR) && (error&MV_ERROR)))
919
            continue;
920

    
921
        if(is_intra_likely)
922
            s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
923
        else
924
            s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
925
    }
926

    
927
    // change inter to intra blocks if no reference frames are available
928
    if (!s->last_picture.data[0] && !s->next_picture.data[0])
929
        for(i=0; i<s->mb_num; i++){
930
            const int mb_xy= s->mb_index2xy[i];
931
            if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
932
                s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
933
        }
934

    
935
    /* handle inter blocks with damaged AC */
936
    for(mb_y=0; mb_y<s->mb_height; mb_y++){
937
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
938
            const int mb_xy= mb_x + mb_y * s->mb_stride;
939
            const int mb_type= s->current_picture.mb_type[mb_xy];
940
            int dir = !s->last_picture.data[0];
941
            error= s->error_status_table[mb_xy];
942

    
943
            if(IS_INTRA(mb_type)) continue; //intra
944
            if(error&MV_ERROR) continue;              //inter with damaged MV
945
            if(!(error&AC_ERROR)) continue;           //undamaged inter
946

    
947
            s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
948
            s->mb_intra=0;
949
            s->mb_skipped=0;
950
            if(IS_8X8(mb_type)){
951
                int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
952
                int j;
953
                s->mv_type = MV_TYPE_8X8;
954
                for(j=0; j<4; j++){
955
                    s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
956
                    s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
957
                }
958
            }else{
959
                s->mv_type = MV_TYPE_16X16;
960
                s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
961
                s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
962
            }
963

    
964
            s->dsp.clear_blocks(s->block[0]);
965

    
966
            s->mb_x= mb_x;
967
            s->mb_y= mb_y;
968
            decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
969
        }
970
    }
971

    
972
    /* guess MVs */
973
    if(s->pict_type==FF_B_TYPE){
974
        for(mb_y=0; mb_y<s->mb_height; mb_y++){
975
            for(mb_x=0; mb_x<s->mb_width; mb_x++){
976
                int xy= mb_x*2 + mb_y*2*s->b8_stride;
977
                const int mb_xy= mb_x + mb_y * s->mb_stride;
978
                const int mb_type= s->current_picture.mb_type[mb_xy];
979
                error= s->error_status_table[mb_xy];
980

    
981
                if(IS_INTRA(mb_type)) continue;
982
                if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
983
                if(!(error&AC_ERROR)) continue;           //undamaged inter
984

    
985
                s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
986
                if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
987
                if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
988
                s->mb_intra=0;
989
                s->mv_type = MV_TYPE_16X16;
990
                s->mb_skipped=0;
991

    
992
                if(s->pp_time){
993
                    int time_pp= s->pp_time;
994
                    int time_pb= s->pb_time;
995

    
996
                    s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
997
                    s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
998
                    s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
999
                    s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1000
                }else{
1001
                    s->mv[0][0][0]= 0;
1002
                    s->mv[0][0][1]= 0;
1003
                    s->mv[1][0][0]= 0;
1004
                    s->mv[1][0][1]= 0;
1005
                }
1006

    
1007
                s->dsp.clear_blocks(s->block[0]);
1008
                s->mb_x= mb_x;
1009
                s->mb_y= mb_y;
1010
                decode_mb(s, 0);
1011
            }
1012
        }
1013
    }else
1014
        guess_mv(s);
1015

    
1016
    /* the filters below are not XvMC compatible, skip them */
1017
    if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1018
        goto ec_clean;
1019
    /* fill DC for inter blocks */
1020
    for(mb_y=0; mb_y<s->mb_height; mb_y++){
1021
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
1022
            int dc, dcu, dcv, y, n;
1023
            int16_t *dc_ptr;
1024
            uint8_t *dest_y, *dest_cb, *dest_cr;
1025
            const int mb_xy= mb_x + mb_y * s->mb_stride;
1026
            const int mb_type= s->current_picture.mb_type[mb_xy];
1027

    
1028
            error= s->error_status_table[mb_xy];
1029

    
1030
            if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1031
//            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1032

    
1033
            dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1034
            dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1035
            dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1036

    
1037
            dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1038
            for(n=0; n<4; n++){
1039
                dc=0;
1040
                for(y=0; y<8; y++){
1041
                    int x;
1042
                    for(x=0; x<8; x++){
1043
                       dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1044
                    }
1045
                }
1046
                dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1047
            }
1048

    
1049
            dcu=dcv=0;
1050
            for(y=0; y<8; y++){
1051
                int x;
1052
                for(x=0; x<8; x++){
1053
                    dcu+=dest_cb[x + y*(s->uvlinesize)];
1054
                    dcv+=dest_cr[x + y*(s->uvlinesize)];
1055
                }
1056
            }
1057
            s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1058
            s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1059
        }
1060
    }
1061
#if 1
1062
    /* guess DC for damaged blocks */
1063
    guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1064
    guess_dc(s, s->dc_val[1], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1065
    guess_dc(s, s->dc_val[2], s->mb_width  , s->mb_height  , s->mb_stride, 0);
1066
#endif
1067
    /* filter luma DC */
1068
    filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1069

    
1070
#if 1
1071
    /* render DC only intra */
1072
    for(mb_y=0; mb_y<s->mb_height; mb_y++){
1073
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
1074
            uint8_t *dest_y, *dest_cb, *dest_cr;
1075
            const int mb_xy= mb_x + mb_y * s->mb_stride;
1076
            const int mb_type= s->current_picture.mb_type[mb_xy];
1077

    
1078
            error= s->error_status_table[mb_xy];
1079

    
1080
            if(IS_INTER(mb_type)) continue;
1081
            if(!(error&AC_ERROR)) continue;              //undamaged
1082

    
1083
            dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1084
            dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
1085
            dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
1086

    
1087
            put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1088
        }
1089
    }
1090
#endif
1091

    
1092
    if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1093
        /* filter horizontal block boundaries */
1094
        h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1095
        h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1096
        h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1097

    
1098
        /* filter vertical block boundaries */
1099
        v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
1100
        v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1101
        v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
1102
    }
1103

    
1104
ec_clean:
1105
    /* clean a few tables */
1106
    for(i=0; i<s->mb_num; i++){
1107
        const int mb_xy= s->mb_index2xy[i];
1108
        int error= s->error_status_table[mb_xy];
1109

    
1110
        if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1111
            s->mbskip_table[mb_xy]=0;
1112
        }
1113
        s->mbintra_table[mb_xy]=1;
1114
    }
1115
}