Statistics
| Branch: | Revision:

ffmpeg / libavcodec / error_resilience.c @ 46b4feec

History | View | Annotate | Download (35.5 KB)

1
/*
2
 * Error resilience / concealment
3
 *
4
 * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 
21
/**
22
 * @file error_resilience.c
23
 * Error resilience / concealment.
24
 */
25

    
26
#include "avcodec.h"
27
#include "dsputil.h"
28
#include "mpegvideo.h"
29
#include "common.h"
30

    
31
/**
32
 * replaces the current MB with a flat dc only version.
33
 */
34
static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
35
{
36
    int dc, dcu, dcv, y, i;
37
    for(i=0; i<4; i++){
38
        dc= s->dc_val[0][mb_x*2+1 + (i&1) + (mb_y*2+1 + (i>>1))*(s->mb_width*2+2)];
39
        if(dc<0) dc=0;
40
        else if(dc>2040) dc=2040;
41
        for(y=0; y<8; y++){
42
            int x;
43
            for(x=0; x<8; x++){
44
                dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
45
            }
46
        }
47
    }
48
    dcu = s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
49
    dcv = s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)];
50
    if     (dcu<0   ) dcu=0;
51
    else if(dcu>2040) dcu=2040;
52
    if     (dcv<0   ) dcv=0;
53
    else if(dcv>2040) dcv=2040;
54
    for(y=0; y<8; y++){
55
        int x;
56
        for(x=0; x<8; x++){
57
            dest_cb[x + y*(s->uvlinesize)]= dcu/8;
58
            dest_cr[x + y*(s->uvlinesize)]= dcv/8;
59
        }
60
    }
61
}
62

    
63
static void filter181(int16_t *data, int width, int height, int stride){
64
    int x,y;
65

    
66
    /* horizontal filter */
67
    for(y=1; y<height-1; y++){
68
        int prev_dc= data[0 + y*stride];
69

    
70
        for(x=1; x<width-1; x++){
71
            int dc;
72
            
73
            dc= - prev_dc 
74
                + data[x     + y*stride]*8
75
                - data[x + 1 + y*stride];
76
            dc= (dc*10923 + 32768)>>16;
77
            prev_dc= data[x + y*stride];
78
            data[x + y*stride]= dc;
79
        }
80
    }
81
    
82
    /* vertical filter */
83
    for(x=1; x<width-1; x++){
84
        int prev_dc= data[x];
85

    
86
        for(y=1; y<height-1; y++){
87
            int dc;
88
            
89
            dc= - prev_dc 
90
                + data[x +  y   *stride]*8
91
                - data[x + (y+1)*stride];
92
            dc= (dc*10923 + 32768)>>16;
93
            prev_dc= data[x + y*stride];
94
            data[x + y*stride]= dc;
95
        }
96
    }
97
}
98

    
99
/**
100
 * guess the dc of blocks which dont have a undamaged dc
101
 * @param w        width in 8 pixel blocks
102
 * @param h        height in 8 pixel blocks
103
 */
104
static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
105
    int b_x, b_y;
106

    
107
    for(b_y=0; b_y<h; b_y++){
108
        for(b_x=0; b_x<w; b_x++){
109
            int color[4]={1024,1024,1024,1024};
110
            int distance[4]={9999,9999,9999,9999};
111
            int mb_index, error, j;
112
            int64_t guess, weight_sum;
113
            
114
            mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_width;
115
            
116
            error= s->error_status_table[mb_index];
117
            
118
            if(!(s->mb_type[mb_index]&MB_TYPE_INTRA)) continue; //inter
119
            if(!(error&DC_ERROR)) continue;           //dc-ok
120
            
121
            /* right block */
122
            for(j=b_x+1; j<w; j++){
123
                int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_width;
124
                int error_j= s->error_status_table[mb_index_j];
125
                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
126
                if(intra_j==0 || !(error_j&DC_ERROR)){
127
                    color[0]= dc[j + b_y*stride];
128
                    distance[0]= j-b_x;
129
                    break;
130
                }
131
            }
132
            
133
            /* left block */
134
            for(j=b_x-1; j>=0; j--){
135
                int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_width;
136
                int error_j= s->error_status_table[mb_index_j];
137
                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
138
                if(intra_j==0 || !(error_j&DC_ERROR)){
139
                    color[1]= dc[j + b_y*stride];
140
                    distance[1]= b_x-j;
141
                    break;
142
                }
143
            }
144

    
145
            /* bottom block */
146
            for(j=b_y+1; j<h; j++){
147
                int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_width;
148
                int error_j= s->error_status_table[mb_index_j];
149
                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
150
                if(intra_j==0 || !(error_j&DC_ERROR)){
151
                    color[2]= dc[b_x + j*stride];
152
                    distance[2]= j-b_y;
153
                    break;
154
                }
155
            }
156

    
157
            /* top block */
158
            for(j=b_y-1; j>=0; j--){
159
                int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_width;
160
                int error_j= s->error_status_table[mb_index_j];
161
                int intra_j= s->mb_type[mb_index_j]&MB_TYPE_INTRA;
162
                if(intra_j==0 || !(error_j&DC_ERROR)){
163
                    color[3]= dc[b_x + j*stride];
164
                    distance[3]= b_y-j;
165
                    break;
166
                }
167
            }
168
            
169
            weight_sum=0;
170
            guess=0;
171
            for(j=0; j<4; j++){
172
                int64_t weight= 256*256*256*16/distance[j];
173
                guess+= weight*(int64_t)color[j];
174
                weight_sum+= weight;
175
            }
176
            guess= (guess + weight_sum/2) / weight_sum;
177

    
178
            dc[b_x + b_y*stride]= guess;
179
        }
180
    }
181
}
182

    
183
/**
184
 * simple horizontal deblocking filter used for error resilience
185
 * @param w        width in 8 pixel blocks
186
 * @param h        height in 8 pixel blocks
187
 */
188
static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
189
    int b_x, b_y;
190
    uint8_t *cm = cropTbl + MAX_NEG_CROP;
191

    
192
    for(b_y=0; b_y<h; b_y++){
193
        for(b_x=0; b_x<w-1; b_x++){
194
            int y;
195
            int left_status = s->error_status_table[( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_width];
196
            int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_width];
197
            int left_intra=   s->mb_type      [( b_x   >>is_luma) + (b_y>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
198
            int right_intra=  s->mb_type      [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
199
            int left_damage =  left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
200
            int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
201
            int offset= b_x*8 + b_y*stride*8;
202
            int16_t *left_mv=  s->motion_val[s->block_wrap[0]*((b_y<<(1-is_luma)) + 1) + ( b_x   <<(1-is_luma))];
203
            int16_t *right_mv= s->motion_val[s->block_wrap[0]*((b_y<<(1-is_luma)) + 1) + ((b_x+1)<<(1-is_luma))];
204
            
205
            if(!(left_damage||right_damage)) continue; // both undamaged
206
            
207
            if(   (!left_intra) && (!right_intra) 
208
               && ABS(left_mv[0]-right_mv[0]) + ABS(left_mv[1]+right_mv[1]) < 2) continue;
209
            
210
            for(y=0; y<8; y++){
211
                int a,b,c,d;
212
                
213
                a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
214
                b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
215
                c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
216
                
217
                d= ABS(b) - ((ABS(a) + ABS(c) + 1)>>1);
218
                d= FFMAX(d, 0);
219
                if(b<0) d= -d;
220
                
221
                if(d==0) continue;
222

    
223
                if(!(left_damage && right_damage))
224
                    d= d*16/9;
225
                
226
                if(left_damage){
227
                    dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
228
                    dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
229
                    dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
230
                    dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
231
                }
232
                if(right_damage){
233
                    dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
234
                    dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
235
                    dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
236
                    dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
237
                }
238
            }
239
        }
240
    }
241
}
242

    
243
/**
244
 * simple vertical deblocking filter used for error resilience
245
 * @param w        width in 8 pixel blocks
246
 * @param h        height in 8 pixel blocks
247
 */
248
static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
249
    int b_x, b_y;
250
    uint8_t *cm = cropTbl + MAX_NEG_CROP;
251

    
252
    for(b_y=0; b_y<h-1; b_y++){
253
        for(b_x=0; b_x<w; b_x++){
254
            int x;
255
            int top_status   = s->error_status_table[(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_width];
256
            int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_width];
257
            int top_intra=     s->mb_type      [(b_x>>is_luma) + ( b_y   >>is_luma)*s->mb_width]&MB_TYPE_INTRA;
258
            int bottom_intra=  s->mb_type      [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_width]&MB_TYPE_INTRA;
259
            int top_damage =      top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
260
            int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
261
            int offset= b_x*8 + b_y*stride*8;
262
            int16_t *top_mv=    s->motion_val[s->block_wrap[0]*(( b_y   <<(1-is_luma)) + 1) + (b_x<<(1-is_luma))];
263
            int16_t *bottom_mv= s->motion_val[s->block_wrap[0]*(((b_y+1)<<(1-is_luma)) + 1) + (b_x<<(1-is_luma))];
264
            
265
            if(!(top_damage||bottom_damage)) continue; // both undamaged
266
            
267
            if(   (!top_intra) && (!bottom_intra) 
268
               && ABS(top_mv[0]-bottom_mv[0]) + ABS(top_mv[1]+bottom_mv[1]) < 2) continue;
269
            
270
            for(x=0; x<8; x++){
271
                int a,b,c,d;
272
                
273
                a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
274
                b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
275
                c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
276
                
277
                d= ABS(b) - ((ABS(a) + ABS(c)+1)>>1);
278
                d= FFMAX(d, 0);
279
                if(b<0) d= -d;
280
                
281
                if(d==0) continue;
282

    
283
                if(!(top_damage && bottom_damage))
284
                    d= d*16/9;
285
                
286
                if(top_damage){
287
                    dst[offset + x +  7*stride] = cm[dst[offset + x +  7*stride] + ((d*7)>>4)];
288
                    dst[offset + x +  6*stride] = cm[dst[offset + x +  6*stride] + ((d*5)>>4)];
289
                    dst[offset + x +  5*stride] = cm[dst[offset + x +  5*stride] + ((d*3)>>4)];
290
                    dst[offset + x +  4*stride] = cm[dst[offset + x +  4*stride] + ((d*1)>>4)];
291
                }
292
                if(bottom_damage){
293
                    dst[offset + x +  8*stride] = cm[dst[offset + x +  8*stride] - ((d*7)>>4)];
294
                    dst[offset + x +  9*stride] = cm[dst[offset + x +  9*stride] - ((d*5)>>4)];
295
                    dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
296
                    dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
297
                }
298
            }
299
        }
300
    }
301
}
302

    
303
static void guess_mv(MpegEncContext *s){
304
    uint8_t fixed[s->mb_num];
305
#define MV_FROZEN    3
306
#define MV_CHANGED   2
307
#define MV_UNCHANGED 1
308
    const int mb_width = s->mb_width;
309
    const int mb_height= s->mb_height;
310
    int i, depth, num_avail;
311
   
312
    num_avail=0;
313
    for(i=0; i<s->mb_num; i++){
314
        int f=0;
315
        int error= s->error_status_table[i];
316

    
317
        if(s->mb_type[i]&MB_TYPE_INTRA) f=MV_FROZEN; //intra //FIXME check
318
        if(!(error&MV_ERROR)) f=MV_FROZEN;           //inter with undamaged MV
319
        
320
        fixed[i]= f;
321
        if(f==MV_FROZEN)
322
            num_avail++;
323
    }
324
    
325
    if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
326
        int mb_x, mb_y;
327
        i= -1;
328
        for(mb_y=0; mb_y<s->mb_height; mb_y++){
329
            for(mb_x=0; mb_x<s->mb_width; mb_x++){
330
                i++;
331
                
332
                if(s->mb_type[i]&MB_TYPE_INTRA) continue;
333
                if(!(s->error_status_table[i]&MV_ERROR)) continue;
334

    
335
                s->mv_dir = MV_DIR_FORWARD;
336
                s->mb_intra=0;
337
                s->mv_type = MV_TYPE_16X16;
338
                s->mb_skiped=0;
339

    
340
                s->dsp.clear_blocks(s->block[0]);
341

    
342
                s->mb_x= mb_x;
343
                s->mb_y= mb_y;
344
                s->mv[0][0][0]= 0;
345
                s->mv[0][0][1]= 0;
346
                MPV_decode_mb(s, s->block);
347
            }
348
        }
349
        return;
350
    }
351
    
352
    for(depth=0;; depth++){
353
        int changed, pass, none_left;
354

    
355
        none_left=1;
356
        changed=1;
357
        for(pass=0; (changed || pass<2) && pass<10; pass++){
358
            int i,mb_x, mb_y;
359
int score_sum=0;
360
 
361
            changed=0;
362
            i= -1;
363
            for(mb_y=0; mb_y<s->mb_height; mb_y++){
364
                for(mb_x=0; mb_x<s->mb_width; mb_x++){
365
                    int mv_predictor[8][2]={{0}};
366
                    int pred_count=0;
367
                    int j;
368
                    int best_score=256*256*256*64;
369
                    int best_pred=0;
370
                    const int mot_stride= mb_width*2+2;
371
                    const int mot_index= mb_x*2 + 1 + (mb_y*2+1)*mot_stride;
372
                    int prev_x= s->motion_val[mot_index][0];
373
                    int prev_y= s->motion_val[mot_index][1];
374

    
375
                    i++;
376
                    if((mb_x^mb_y^pass)&1) continue;
377
                    
378
                    if(fixed[i]==MV_FROZEN) continue;
379
                    
380
                    j=0;
381
                    if(mb_x>0           && fixed[i-1       ]==MV_FROZEN) j=1;
382
                    if(mb_x+1<mb_width  && fixed[i+1       ]==MV_FROZEN) j=1;
383
                    if(mb_y>0           && fixed[i-mb_width]==MV_FROZEN) j=1;
384
                    if(mb_y+1<mb_height && fixed[i+mb_width]==MV_FROZEN) j=1;
385
                    if(j==0) continue;
386

    
387
                    j=0;
388
                    if(mb_x>0           && fixed[i-1       ]==MV_CHANGED) j=1;
389
                    if(mb_x+1<mb_width  && fixed[i+1       ]==MV_CHANGED) j=1;
390
                    if(mb_y>0           && fixed[i-mb_width]==MV_CHANGED) j=1;
391
                    if(mb_y+1<mb_height && fixed[i+mb_width]==MV_CHANGED) j=1;
392
                    if(j==0 && pass>1) continue;
393
                    
394
                    none_left=0;
395
                    
396
                    if(mb_x>0 && fixed[i-1]){
397
                        mv_predictor[pred_count][0]= s->motion_val[mot_index - 2][0];
398
                        mv_predictor[pred_count][1]= s->motion_val[mot_index - 2][1];
399
                        pred_count++;
400
                    }
401
                    if(mb_x+1<mb_width && fixed[i+1]){
402
                        mv_predictor[pred_count][0]= s->motion_val[mot_index + 2][0];
403
                        mv_predictor[pred_count][1]= s->motion_val[mot_index + 2][1];
404
                        pred_count++;
405
                    }
406
                    if(mb_y>0 && fixed[i-mb_width]){
407
                        mv_predictor[pred_count][0]= s->motion_val[mot_index - mot_stride*2][0];
408
                        mv_predictor[pred_count][1]= s->motion_val[mot_index - mot_stride*2][1];
409
                        pred_count++;
410
                    }
411
                    if(mb_y+1<mb_height && fixed[i+mb_width]){
412
                        mv_predictor[pred_count][0]= s->motion_val[mot_index + mot_stride*2][0];
413
                        mv_predictor[pred_count][1]= s->motion_val[mot_index + mot_stride*2][1];
414
                        pred_count++;
415
                    }
416
                    if(pred_count==0) continue;
417
                    
418
                    if(pred_count>1){
419
                        int sum_x=0, sum_y=0;
420
                        int max_x, max_y, min_x, min_y;
421

    
422
                        for(j=0; j<pred_count; j++){
423
                            sum_x+= mv_predictor[j][0];
424
                            sum_y+= mv_predictor[j][1];
425
                        }
426
                    
427
                        /* mean */
428
                        mv_predictor[pred_count][0] = sum_x/j;
429
                        mv_predictor[pred_count][1] = sum_y/j;
430
                    
431
                        /* median */
432
                        if(pred_count>=3){
433
                            min_y= min_x= 99999;
434
                            max_y= max_x=-99999;
435
                        }else{
436
                            min_x=min_y=max_x=max_y=0;
437
                        }
438
                        for(j=0; j<pred_count; j++){
439
                            max_x= FFMAX(max_x, mv_predictor[j][0]);
440
                            max_y= FFMAX(max_y, mv_predictor[j][1]);
441
                            min_x= FFMIN(min_x, mv_predictor[j][0]);
442
                            min_y= FFMIN(min_y, mv_predictor[j][1]);
443
                        }
444
                        mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
445
                        mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
446
                        
447
                        if(pred_count==4){
448
                            mv_predictor[pred_count+1][0] /= 2;
449
                            mv_predictor[pred_count+1][1] /= 2;
450
                        }
451
                        pred_count+=2;
452
                    }
453
                    
454
                    /* zero MV */
455
                    pred_count++;
456

    
457
                    /* last MV */
458
                    mv_predictor[pred_count][0]= s->motion_val[mot_index][0];
459
                    mv_predictor[pred_count][1]= s->motion_val[mot_index][1];
460
                    pred_count++;                    
461
                    
462
                    s->mv_dir = MV_DIR_FORWARD;
463
                    s->mb_intra=0;
464
                    s->mv_type = MV_TYPE_16X16;
465
                    s->mb_skiped=0;
466

    
467
                    s->dsp.clear_blocks(s->block[0]);
468

    
469
                    s->mb_x= mb_x;
470
                    s->mb_y= mb_y;
471
                    for(j=0; j<pred_count; j++){
472
                        int score=0;
473
                        uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
474

    
475
                        s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
476
                        s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
477
                        MPV_decode_mb(s, s->block);
478
                        
479
                        if(mb_x>0 && fixed[i-1]){
480
                            int k;
481
                            for(k=0; k<16; k++)
482
                                score += ABS(src[k*s->linesize-1 ]-src[k*s->linesize   ]);
483
                        }
484
                        if(mb_x+1<mb_width && fixed[i+1]){
485
                            int k;
486
                            for(k=0; k<16; k++)
487
                                score += ABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
488
                        }
489
                        if(mb_y>0 && fixed[i-mb_width]){
490
                            int k;
491
                            for(k=0; k<16; k++)
492
                                score += ABS(src[k-s->linesize   ]-src[k               ]);
493
                        }
494
                        if(mb_y+1<mb_height && fixed[i+mb_width]){
495
                            int k;
496
                            for(k=0; k<16; k++)
497
                                score += ABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
498
                        }
499
                        
500
                        if(score <= best_score){ // <= will favor the last MV
501
                            best_score= score;
502
                            best_pred= j;
503
                        }
504
                    }
505
score_sum+= best_score;
506
//FIXME no need to set s->motion_val[mot_index][0] explicit
507
                    s->motion_val[mot_index][0]= s->mv[0][0][0]= mv_predictor[best_pred][0];
508
                    s->motion_val[mot_index][1]= s->mv[0][0][1]= mv_predictor[best_pred][1];
509

    
510
                    MPV_decode_mb(s, s->block);
511

    
512
                    
513
                    if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
514
                        fixed[i]=MV_CHANGED;
515
                        changed++;
516
                    }else
517
                        fixed[i]=MV_UNCHANGED;
518
                }
519
            }
520

    
521
//            printf(".%d/%d", changed, score_sum); fflush(stdout);
522
        }
523
        
524
        if(none_left) 
525
            return;
526
            
527
        for(i=0; i<s->mb_num; i++){
528
            if(fixed[i])
529
                fixed[i]=MV_FROZEN;
530
        }
531
//        printf(":"); fflush(stdout);
532
    }
533
}
534
    
535
static int is_intra_more_likely(MpegEncContext *s){
536
    int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
537
    
538
    if(s->last_picture_ptr==NULL) return 1; //no previous frame available -> use spatial prediction
539

    
540
    undamaged_count=0;
541
    for(i=0; i<s->mb_num; i++){
542
        int error= s->error_status_table[i];
543
        if(!((error&DC_ERROR) && (error&MV_ERROR)))
544
            undamaged_count++;
545
    }
546
    
547
    if(undamaged_count < 5) return 0; //allmost all MBs damaged -> use temporal prediction
548
    
549
    skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs 
550
    is_intra_likely=0;
551

    
552
    j=0;
553
    i=-1;
554
    for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
555
        for(mb_x= 0; mb_x<s->mb_width; mb_x++){
556
            int error;
557

    
558
            i++;
559
            error= s->error_status_table[i];
560
            if((error&DC_ERROR) && (error&MV_ERROR))
561
                continue; //skip damaged
562
        
563
            j++;    
564
            if((j%skip_amount) != 0) continue; //skip a few to speed things up
565
    
566
            if(s->pict_type==I_TYPE){
567
                uint8_t *mb_ptr     = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
568
                uint8_t *last_mb_ptr= s->last_picture.data   [0] + mb_x*16 + mb_y*16*s->linesize;
569
    
570
                is_intra_likely += s->dsp.pix_abs16x16(last_mb_ptr, mb_ptr                    , s->linesize);
571
                is_intra_likely -= s->dsp.pix_abs16x16(last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize);
572
            }else{
573
                if(s->mbintra_table[i]) //HACK (this is allways inited but we should use mb_type[])
574
                   is_intra_likely++;
575
                else
576
                   is_intra_likely--;
577
            }
578
        }
579
    }
580
//printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
581
    return is_intra_likely > 0;    
582
}
583

    
584
void ff_er_frame_start(MpegEncContext *s){
585
    if(!s->error_resilience) return;
586

    
587
    memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_num*sizeof(uint8_t));
588
}
589

    
590
/**
591
 * adds a slice.
592
 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
593
 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
594
 *               error of the same type occured
595
 */
596
void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
597
    const int start_xy= clip(startx + starty * s->mb_width, 0, s->mb_num-1);
598
    const int end_xy  = clip(endx   + endy   * s->mb_width, 0, s->mb_num);
599
    const int mb_count= end_xy - start_xy;
600
    int mask= -1;
601
    
602
    if(!s->error_resilience) return;
603

    
604
    mask &= ~VP_START;
605
    if(status & (AC_ERROR|AC_END)) mask &= ~(AC_ERROR|AC_END);
606
    if(status & (DC_ERROR|DC_END)) mask &= ~(DC_ERROR|DC_END);
607
    if(status & (MV_ERROR|MV_END)) mask &= ~(MV_ERROR|MV_END);    
608

    
609
    if(mask == ~0x7F){
610
        memset(&s->error_status_table[start_xy], 0, mb_count * sizeof(uint8_t));
611
    }else{
612
        int i;
613
        for(i=start_xy; i<end_xy; i++){
614
            s->error_status_table[i] &= mask;
615
        }
616
    }
617

    
618
    s->error_status_table[start_xy] |= VP_START;
619
    
620
    if(end_xy < s->mb_num){
621
        s->error_status_table[end_xy] &= mask;
622
        s->error_status_table[end_xy] |= status;
623
    }
624
}
625

    
626
void ff_er_frame_end(MpegEncContext *s){
627
    int i, mb_x, mb_y, error, error_type;
628
    int distance;
629
    int threshold_part[4]= {100,100,100};
630
    int threshold= 50;
631
    int is_intra_likely;
632
    int num_end_markers=0;
633
    
634
    if(!s->error_resilience) return;
635

    
636
    error=0;
637
    for(i=0; i<s->mb_num; i++){
638
        int status= s->error_status_table[i];
639
        
640
        if(status==0) continue;
641

    
642
        if(status&(DC_ERROR|AC_ERROR|MV_ERROR))
643
            error=1;
644
        if(status&VP_START){
645
            if(num_end_markers) 
646
                error=1;
647
            num_end_markers=3;
648
        }
649
        if(status&AC_END)
650
            num_end_markers--;
651
        if(status&DC_END)
652
            num_end_markers--;
653
        if(status&MV_END)
654
            num_end_markers--;
655
    }
656
    if(num_end_markers==0 && error==0)
657
        return;
658

    
659
    fprintf(stderr, "concealing errors\n");
660

    
661
    if(s->avctx->debug&FF_DEBUG_ER){    
662
        for(i=0; i<s->mb_num; i++){
663
            int status= s->error_status_table[i];
664
            
665
            if(i%s->mb_width == 0) printf("\n");
666
            printf("%2X ", status); 
667
        }
668
    }
669
    
670
#if 1
671
    /* handle overlapping slices */
672
    for(error_type=1; error_type<=3; error_type++){
673
        int end_ok=0;
674

    
675
        for(i=s->mb_num-1; i>=0; i--){
676
            int error= s->error_status_table[i];
677
        
678
            if(error&(1<<error_type))
679
                end_ok=1;
680
            if(error&(8<<error_type))
681
                end_ok=1;
682

    
683
            if(!end_ok)
684
                s->error_status_table[i]|= 1<<error_type;
685

    
686
            if(error&VP_START)
687
                end_ok=0;
688
        }
689
    }
690
#endif
691
#if 1
692
    /* handle slices with partitions of different length */
693
    if(s->partitioned_frame){
694
        int end_ok=0;
695

    
696
        for(i=s->mb_num-1; i>=0; i--){
697
            int error= s->error_status_table[i];
698
        
699
            if(error&AC_END)
700
                end_ok=0;
701
            if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
702
                end_ok=1;
703

    
704
            if(!end_ok)
705
                s->error_status_table[i]|= AC_ERROR;
706

    
707
            if(error&VP_START)
708
                end_ok=0;
709
        }
710
    }
711
#endif
712
    /* handle missing slices */
713
    if(s->error_resilience>=4){
714
        int end_ok=1;
715
                
716
        for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
717
            int error1= s->error_status_table[i  ];
718
            int error2= s->error_status_table[i+1];
719
        
720
            if(error1&VP_START)
721
                end_ok=1;
722
             
723
            if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
724
               && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END) 
725
               && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninited
726
                end_ok=0;
727
            }
728
        
729
            if(!end_ok)
730
                s->error_status_table[i]|= DC_ERROR|AC_ERROR|MV_ERROR;
731
        }
732
    }
733
    
734
#if 1
735
    /* backward mark errors */
736
    distance=9999999;
737
    for(error_type=1; error_type<=3; error_type++){
738
        for(i=s->mb_num-1; i>=0; i--){
739
            int error= s->error_status_table[i];
740
            
741
            if(!s->mbskip_table[i]) //FIXME partition specific
742
                distance++;            
743
            if(error&(1<<error_type))
744
                distance= 0;
745

    
746
            if(s->partitioned_frame){
747
                if(distance < threshold_part[error_type-1])
748
                    s->error_status_table[i]|= 1<<error_type;
749
            }else{
750
                if(distance < threshold)
751
                    s->error_status_table[i]|= 1<<error_type;
752
            }
753

    
754
            if(error&VP_START)
755
                distance= 9999999;
756
        }
757
    }
758
#endif
759

    
760
    /* forward mark errors */
761
    error=0;
762
    for(i=0; i<s->mb_num; i++){
763
        int old_error= s->error_status_table[i];
764
        
765
        if(old_error&VP_START)
766
            error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
767
        else{
768
            error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
769
            s->error_status_table[i]|= error;
770
        }
771
    }
772
#if 1
773
    /* handle not partitioned case */
774
    if(!s->partitioned_frame){
775
        for(i=0; i<s->mb_num; i++){
776
            error= s->error_status_table[i];
777
            if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
778
                error|= AC_ERROR|DC_ERROR|MV_ERROR;
779
            s->error_status_table[i]= error;
780
        }
781
    }
782
#endif
783
    is_intra_likely= is_intra_more_likely(s);
784

    
785
    /* set unknown mb-type to most likely */
786
    for(i=0; i<s->mb_num; i++){
787
        int intra;
788
        error= s->error_status_table[i];
789
        if((error&DC_ERROR) && (error&MV_ERROR))
790
            intra= is_intra_likely;
791
        else
792
            intra= s->mbintra_table[i];
793

    
794
        if(intra)
795
            s->mb_type[i]|= MB_TYPE_INTRA;
796
        else
797
            s->mb_type[i]&= ~MB_TYPE_INTRA;
798
    }
799
    
800
    /* handle inter blocks with damaged AC */
801
    i= -1;
802
    for(mb_y=0; mb_y<s->mb_height; mb_y++){
803
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
804
            i++;
805
            error= s->error_status_table[i];
806

    
807
            if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
808
            if(error&MV_ERROR) continue;              //inter with damaged MV
809
            if(!(error&AC_ERROR)) continue;           //undamaged inter
810
            
811
            s->mv_dir = MV_DIR_FORWARD;
812
            s->mb_intra=0;
813
            s->mb_skiped=0;
814
            if(s->mb_type[i]&MB_TYPE_INTER4V){
815
                int mb_index= mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0];
816
                int j;
817
                s->mv_type = MV_TYPE_8X8;
818
                for(j=0; j<4; j++){
819
                    s->mv[0][j][0] = s->motion_val[ mb_index + (j&1) + (j>>1)*s->block_wrap[0] ][0];
820
                    s->mv[0][j][1] = s->motion_val[ mb_index + (j&1) + (j>>1)*s->block_wrap[0] ][1];
821
                }
822
            }else{
823
                s->mv_type = MV_TYPE_16X16;
824
                s->mv[0][0][0] = s->motion_val[ mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0] ][0];
825
                s->mv[0][0][1] = s->motion_val[ mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0] ][1];
826
            }
827
        
828
            s->dsp.clear_blocks(s->block[0]);
829

    
830
            s->mb_x= mb_x;
831
            s->mb_y= mb_y;
832
            MPV_decode_mb(s, s->block);
833
        }
834
    }
835

    
836
    /* guess MVs */
837
    if(s->pict_type==B_TYPE){
838
        i= -1;
839
        for(mb_y=0; mb_y<s->mb_height; mb_y++){
840
            for(mb_x=0; mb_x<s->mb_width; mb_x++){
841
                int xy= mb_x*2+1 + (mb_y*2+1)*s->block_wrap[0];
842
                i++;
843
                error= s->error_status_table[i];
844

    
845
                if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
846
                if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
847
                if(!(error&AC_ERROR)) continue;           //undamaged inter
848
            
849
                s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
850
                s->mb_intra=0;
851
                s->mv_type = MV_TYPE_16X16;
852
                s->mb_skiped=0;
853
                
854
                if(s->pp_time){
855
                    int time_pp= s->pp_time;
856
                    int time_pb= s->pb_time;
857
            
858
                    s->mv[0][0][0] = s->motion_val[xy][0]*time_pb/time_pp;
859
                    s->mv[0][0][1] = s->motion_val[xy][1]*time_pb/time_pp;
860
                    s->mv[1][0][0] = s->motion_val[xy][0]*(time_pb - time_pp)/time_pp;
861
                    s->mv[1][0][1] = s->motion_val[xy][1]*(time_pb - time_pp)/time_pp;
862
                }else{
863
                    s->mv[0][0][0]= 0;
864
                    s->mv[0][0][1]= 0;
865
                    s->mv[1][0][0]= 0;
866
                    s->mv[1][0][1]= 0;
867
                }
868

    
869
                s->dsp.clear_blocks(s->block[0]);
870
                s->mb_x= mb_x;
871
                s->mb_y= mb_y;
872
                MPV_decode_mb(s, s->block);
873
            }
874
        }
875
    }else
876
        guess_mv(s);
877

    
878
    /* fill DC for inter blocks */
879
    i= -1;
880
    for(mb_y=0; mb_y<s->mb_height; mb_y++){
881
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
882
            int dc, dcu, dcv, y, n;
883
            int16_t *dc_ptr;
884
            uint8_t *dest_y, *dest_cb, *dest_cr;
885
           
886
            i++;
887
            error= s->error_status_table[i];
888

    
889
            if(s->mb_type[i]&MB_TYPE_INTRA) continue; //intra
890
//            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
891
            
892
            dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
893
            dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
894
            dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
895
           
896
            dc_ptr= &s->dc_val[0][mb_x*2+1 + (mb_y*2+1)*(s->mb_width*2+2)];
897
            for(n=0; n<4; n++){
898
                dc=0;
899
                for(y=0; y<8; y++){
900
                    int x;
901
                    for(x=0; x<8; x++){
902
                       dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
903
                    }
904
                }
905
                dc_ptr[(n&1) + (n>>1)*(s->mb_width*2+2)]= (dc+4)>>3;
906
            }
907

    
908
            dcu=dcv=0;
909
            for(y=0; y<8; y++){
910
                int x;
911
                for(x=0; x<8; x++){
912
                    dcu+=dest_cb[x + y*(s->uvlinesize)];
913
                    dcv+=dest_cr[x + y*(s->uvlinesize)];
914
                }
915
            }
916
            s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)]= (dcu+4)>>3;
917
            s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)]= (dcv+4)>>3;   
918
        }
919
    }
920
#if 1
921
    /* guess DC for damaged blocks */
922
    guess_dc(s, s->dc_val[0] + s->mb_width*2+3, s->mb_width*2, s->mb_height*2, s->mb_width*2+2, 1);
923
    guess_dc(s, s->dc_val[1] + s->mb_width  +3, s->mb_width  , s->mb_height  , s->mb_width  +2, 0);
924
    guess_dc(s, s->dc_val[2] + s->mb_width  +3, s->mb_width  , s->mb_height  , s->mb_width  +2, 0);
925
#endif   
926
    /* filter luma DC */
927
    filter181(s->dc_val[0] + s->mb_width*2+3, s->mb_width*2, s->mb_height*2, s->mb_width*2+2);
928
    
929
#if 1
930
    /* render DC only intra */
931
    i= -1;
932
    for(mb_y=0; mb_y<s->mb_height; mb_y++){
933
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
934
            uint8_t *dest_y, *dest_cb, *dest_cr;
935
           
936
            i++;
937
            error= s->error_status_table[i];
938

    
939
            if(!(s->mb_type[i]&MB_TYPE_INTRA)) continue; //inter
940
            if(!(error&AC_ERROR)) continue;              //undamaged
941
            
942
            dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
943
            dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
944
            dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
945
            
946
            put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
947
        }
948
    }
949
#endif
950
    
951
    if(s->avctx->error_concealment&FF_EC_DEBLOCK){
952
        /* filter horizontal block boundaries */
953
        h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
954
        h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
955
        h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
956

    
957
        /* filter vertical block boundaries */
958
        v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
959
        v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
960
        v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
961
    }
962

    
963
    /* clean a few tables */
964
    for(i=0; i<s->mb_num; i++){
965
        int error= s->error_status_table[i];
966
        
967
        if(s->pict_type!=B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
968
            s->mbskip_table[i]=0;
969
        }
970
        s->mbintra_table[i]=1;
971
    }    
972
}