2 * Error resilience / concealment
4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 * This file is part of FFmpeg.
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.
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.
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
24 * @file libavcodec/error_resilience.c
25 * Error resilience / concealment.
32 #include "mpegvideo.h"
34 static void decode_mb(MpegEncContext
*s
){
35 s
->dest
[0] = s
->current_picture
.data
[0] + (s
->mb_y
* 16* s
->linesize
) + s
->mb_x
* 16;
36 s
->dest
[1] = s
->current_picture
.data
[1] + (s
->mb_y
* 8 * s
->uvlinesize
) + s
->mb_x
* 8;
37 s
->dest
[2] = s
->current_picture
.data
[2] + (s
->mb_y
* 8 * s
->uvlinesize
) + s
->mb_x
* 8;
39 MPV_decode_mb(s
, s
->block
);
43 * replaces the current MB with a flat dc only version.
45 static void put_dc(MpegEncContext
*s
, uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
, int mb_x
, int mb_y
)
47 int dc
, dcu
, dcv
, y
, i
;
49 dc
= s
->dc_val
[0][mb_x
*2 + (i
&1) + (mb_y
*2 + (i
>>1))*s
->b8_stride
];
51 else if(dc
>2040) dc
=2040;
55 dest_y
[x
+ (i
&1)*8 + (y
+ (i
>>1)*8)*s
->linesize
]= dc
/8;
59 dcu
= s
->dc_val
[1][mb_x
+ mb_y
*s
->mb_stride
];
60 dcv
= s
->dc_val
[2][mb_x
+ mb_y
*s
->mb_stride
];
62 else if(dcu
>2040) dcu
=2040;
64 else if(dcv
>2040) dcv
=2040;
68 dest_cb
[x
+ y
*(s
->uvlinesize
)]= dcu
/8;
69 dest_cr
[x
+ y
*(s
->uvlinesize
)]= dcv
/8;
74 static void filter181(int16_t *data
, int width
, int height
, int stride
){
77 /* horizontal filter */
78 for(y
=1; y
<height
-1; y
++){
79 int prev_dc
= data
[0 + y
*stride
];
81 for(x
=1; x
<width
-1; x
++){
85 + data
[x
+ y
*stride
]*8
86 - data
[x
+ 1 + y
*stride
];
87 dc
= (dc
*10923 + 32768)>>16;
88 prev_dc
= data
[x
+ y
*stride
];
89 data
[x
+ y
*stride
]= dc
;
94 for(x
=1; x
<width
-1; x
++){
97 for(y
=1; y
<height
-1; y
++){
101 + data
[x
+ y
*stride
]*8
102 - data
[x
+ (y
+1)*stride
];
103 dc
= (dc
*10923 + 32768)>>16;
104 prev_dc
= data
[x
+ y
*stride
];
105 data
[x
+ y
*stride
]= dc
;
111 * guess the dc of blocks which do not have an undamaged dc
112 * @param w width in 8 pixel blocks
113 * @param h height in 8 pixel blocks
115 static void guess_dc(MpegEncContext
*s
, int16_t *dc
, int w
, int h
, int stride
, int is_luma
){
118 for(b_y
=0; b_y
<h
; b_y
++){
119 for(b_x
=0; b_x
<w
; b_x
++){
120 int color
[4]={1024,1024,1024,1024};
121 int distance
[4]={9999,9999,9999,9999};
122 int mb_index
, error
, j
;
123 int64_t guess
, weight_sum
;
125 mb_index
= (b_x
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_stride
;
127 error
= s
->error_status_table
[mb_index
];
129 if(IS_INTER(s
->current_picture
.mb_type
[mb_index
])) continue; //inter
130 if(!(error
&DC_ERROR
)) continue; //dc-ok
133 for(j
=b_x
+1; j
<w
; j
++){
134 int mb_index_j
= (j
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_stride
;
135 int error_j
= s
->error_status_table
[mb_index_j
];
136 int intra_j
= IS_INTRA(s
->current_picture
.mb_type
[mb_index_j
]);
137 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
138 color
[0]= dc
[j
+ b_y
*stride
];
145 for(j
=b_x
-1; j
>=0; j
--){
146 int mb_index_j
= (j
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_stride
;
147 int error_j
= s
->error_status_table
[mb_index_j
];
148 int intra_j
= IS_INTRA(s
->current_picture
.mb_type
[mb_index_j
]);
149 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
150 color
[1]= dc
[j
+ b_y
*stride
];
157 for(j
=b_y
+1; j
<h
; j
++){
158 int mb_index_j
= (b_x
>>is_luma
) + (j
>>is_luma
)*s
->mb_stride
;
159 int error_j
= s
->error_status_table
[mb_index_j
];
160 int intra_j
= IS_INTRA(s
->current_picture
.mb_type
[mb_index_j
]);
161 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
162 color
[2]= dc
[b_x
+ j
*stride
];
169 for(j
=b_y
-1; j
>=0; j
--){
170 int mb_index_j
= (b_x
>>is_luma
) + (j
>>is_luma
)*s
->mb_stride
;
171 int error_j
= s
->error_status_table
[mb_index_j
];
172 int intra_j
= IS_INTRA(s
->current_picture
.mb_type
[mb_index_j
]);
173 if(intra_j
==0 || !(error_j
&DC_ERROR
)){
174 color
[3]= dc
[b_x
+ j
*stride
];
183 int64_t weight
= 256*256*256*16/distance
[j
];
184 guess
+= weight
*(int64_t)color
[j
];
187 guess
= (guess
+ weight_sum
/2) / weight_sum
;
189 dc
[b_x
+ b_y
*stride
]= guess
;
195 * simple horizontal deblocking filter used for error resilience
196 * @param w width in 8 pixel blocks
197 * @param h height in 8 pixel blocks
199 static void h_block_filter(MpegEncContext
*s
, uint8_t *dst
, int w
, int h
, int stride
, int is_luma
){
201 uint8_t *cm
= ff_cropTbl
+ MAX_NEG_CROP
;
203 for(b_y
=0; b_y
<h
; b_y
++){
204 for(b_x
=0; b_x
<w
-1; b_x
++){
206 int left_status
= s
->error_status_table
[( b_x
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_stride
];
207 int right_status
= s
->error_status_table
[((b_x
+1)>>is_luma
) + (b_y
>>is_luma
)*s
->mb_stride
];
208 int left_intra
= IS_INTRA(s
->current_picture
.mb_type
[( b_x
>>is_luma
) + (b_y
>>is_luma
)*s
->mb_stride
]);
209 int right_intra
= IS_INTRA(s
->current_picture
.mb_type
[((b_x
+1)>>is_luma
) + (b_y
>>is_luma
)*s
->mb_stride
]);
210 int left_damage
= left_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
211 int right_damage
= right_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
212 int offset
= b_x
*8 + b_y
*stride
*8;
213 int16_t *left_mv
= s
->current_picture
.motion_val
[0][s
->b8_stride
*(b_y
<<(1-is_luma
)) + ( b_x
<<(1-is_luma
))];
214 int16_t *right_mv
= s
->current_picture
.motion_val
[0][s
->b8_stride
*(b_y
<<(1-is_luma
)) + ((b_x
+1)<<(1-is_luma
))];
216 if(!(left_damage
||right_damage
)) continue; // both undamaged
218 if( (!left_intra
) && (!right_intra
)
219 && FFABS(left_mv
[0]-right_mv
[0]) + FFABS(left_mv
[1]+right_mv
[1]) < 2) continue;
224 a
= dst
[offset
+ 7 + y
*stride
] - dst
[offset
+ 6 + y
*stride
];
225 b
= dst
[offset
+ 8 + y
*stride
] - dst
[offset
+ 7 + y
*stride
];
226 c
= dst
[offset
+ 9 + y
*stride
] - dst
[offset
+ 8 + y
*stride
];
228 d
= FFABS(b
) - ((FFABS(a
) + FFABS(c
) + 1)>>1);
234 if(!(left_damage
&& right_damage
))
238 dst
[offset
+ 7 + y
*stride
] = cm
[dst
[offset
+ 7 + y
*stride
] + ((d
*7)>>4)];
239 dst
[offset
+ 6 + y
*stride
] = cm
[dst
[offset
+ 6 + y
*stride
] + ((d
*5)>>4)];
240 dst
[offset
+ 5 + y
*stride
] = cm
[dst
[offset
+ 5 + y
*stride
] + ((d
*3)>>4)];
241 dst
[offset
+ 4 + y
*stride
] = cm
[dst
[offset
+ 4 + y
*stride
] + ((d
*1)>>4)];
244 dst
[offset
+ 8 + y
*stride
] = cm
[dst
[offset
+ 8 + y
*stride
] - ((d
*7)>>4)];
245 dst
[offset
+ 9 + y
*stride
] = cm
[dst
[offset
+ 9 + y
*stride
] - ((d
*5)>>4)];
246 dst
[offset
+ 10+ y
*stride
] = cm
[dst
[offset
+10 + y
*stride
] - ((d
*3)>>4)];
247 dst
[offset
+ 11+ y
*stride
] = cm
[dst
[offset
+11 + y
*stride
] - ((d
*1)>>4)];
255 * simple vertical deblocking filter used for error resilience
256 * @param w width in 8 pixel blocks
257 * @param h height in 8 pixel blocks
259 static void v_block_filter(MpegEncContext
*s
, uint8_t *dst
, int w
, int h
, int stride
, int is_luma
){
261 uint8_t *cm
= ff_cropTbl
+ MAX_NEG_CROP
;
263 for(b_y
=0; b_y
<h
-1; b_y
++){
264 for(b_x
=0; b_x
<w
; b_x
++){
266 int top_status
= s
->error_status_table
[(b_x
>>is_luma
) + ( b_y
>>is_luma
)*s
->mb_stride
];
267 int bottom_status
= s
->error_status_table
[(b_x
>>is_luma
) + ((b_y
+1)>>is_luma
)*s
->mb_stride
];
268 int top_intra
= IS_INTRA(s
->current_picture
.mb_type
[(b_x
>>is_luma
) + ( b_y
>>is_luma
)*s
->mb_stride
]);
269 int bottom_intra
= IS_INTRA(s
->current_picture
.mb_type
[(b_x
>>is_luma
) + ((b_y
+1)>>is_luma
)*s
->mb_stride
]);
270 int top_damage
= top_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
271 int bottom_damage
= bottom_status
&(DC_ERROR
|AC_ERROR
|MV_ERROR
);
272 int offset
= b_x
*8 + b_y
*stride
*8;
273 int16_t *top_mv
= s
->current_picture
.motion_val
[0][s
->b8_stride
*( b_y
<<(1-is_luma
)) + (b_x
<<(1-is_luma
))];
274 int16_t *bottom_mv
= s
->current_picture
.motion_val
[0][s
->b8_stride
*((b_y
+1)<<(1-is_luma
)) + (b_x
<<(1-is_luma
))];
276 if(!(top_damage
||bottom_damage
)) continue; // both undamaged
278 if( (!top_intra
) && (!bottom_intra
)
279 && FFABS(top_mv
[0]-bottom_mv
[0]) + FFABS(top_mv
[1]+bottom_mv
[1]) < 2) continue;
284 a
= dst
[offset
+ x
+ 7*stride
] - dst
[offset
+ x
+ 6*stride
];
285 b
= dst
[offset
+ x
+ 8*stride
] - dst
[offset
+ x
+ 7*stride
];
286 c
= dst
[offset
+ x
+ 9*stride
] - dst
[offset
+ x
+ 8*stride
];
288 d
= FFABS(b
) - ((FFABS(a
) + FFABS(c
)+1)>>1);
294 if(!(top_damage
&& bottom_damage
))
298 dst
[offset
+ x
+ 7*stride
] = cm
[dst
[offset
+ x
+ 7*stride
] + ((d
*7)>>4)];
299 dst
[offset
+ x
+ 6*stride
] = cm
[dst
[offset
+ x
+ 6*stride
] + ((d
*5)>>4)];
300 dst
[offset
+ x
+ 5*stride
] = cm
[dst
[offset
+ x
+ 5*stride
] + ((d
*3)>>4)];
301 dst
[offset
+ x
+ 4*stride
] = cm
[dst
[offset
+ x
+ 4*stride
] + ((d
*1)>>4)];
304 dst
[offset
+ x
+ 8*stride
] = cm
[dst
[offset
+ x
+ 8*stride
] - ((d
*7)>>4)];
305 dst
[offset
+ x
+ 9*stride
] = cm
[dst
[offset
+ x
+ 9*stride
] - ((d
*5)>>4)];
306 dst
[offset
+ x
+ 10*stride
] = cm
[dst
[offset
+ x
+ 10*stride
] - ((d
*3)>>4)];
307 dst
[offset
+ x
+ 11*stride
] = cm
[dst
[offset
+ x
+ 11*stride
] - ((d
*1)>>4)];
314 static void guess_mv(MpegEncContext
*s
){
315 uint8_t fixed
[s
->mb_stride
* s
->mb_height
];
318 #define MV_UNCHANGED 1
319 const int mb_stride
= s
->mb_stride
;
320 const int mb_width
= s
->mb_width
;
321 const int mb_height
= s
->mb_height
;
322 int i
, depth
, num_avail
;
326 for(i
=0; i
<s
->mb_num
; i
++){
327 const int mb_xy
= s
->mb_index2xy
[ i
];
329 int error
= s
->error_status_table
[mb_xy
];
331 if(IS_INTRA(s
->current_picture
.mb_type
[mb_xy
])) f
=MV_FROZEN
; //intra //FIXME check
332 if(!(error
&MV_ERROR
)) f
=MV_FROZEN
; //inter with undamaged MV
339 if((!(s
->avctx
->error_concealment
&FF_EC_GUESS_MVS
)) || num_avail
<= mb_width
/2){
340 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
341 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
342 const int mb_xy
= mb_x
+ mb_y
*s
->mb_stride
;
344 if(IS_INTRA(s
->current_picture
.mb_type
[mb_xy
])) continue;
345 if(!(s
->error_status_table
[mb_xy
]&MV_ERROR
)) continue;
347 s
->mv_dir
= s
->last_picture
.data
[0] ? MV_DIR_FORWARD
: MV_DIR_BACKWARD
;
349 s
->mv_type
= MV_TYPE_16X16
;
352 s
->dsp
.clear_blocks(s
->block
[0]);
364 for(depth
=0;; depth
++){
365 int changed
, pass
, none_left
;
369 for(pass
=0; (changed
|| pass
<2) && pass
<10; pass
++){
374 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
375 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
376 const int mb_xy
= mb_x
+ mb_y
*s
->mb_stride
;
377 int mv_predictor
[8][2]={{0}};
380 int best_score
=256*256*256*64;
382 const int mot_stride
= s
->b8_stride
;
383 const int mot_index
= mb_x
*2 + mb_y
*2*mot_stride
;
384 int prev_x
= s
->current_picture
.motion_val
[0][mot_index
][0];
385 int prev_y
= s
->current_picture
.motion_val
[0][mot_index
][1];
387 if((mb_x
^mb_y
^pass
)&1) continue;
389 if(fixed
[mb_xy
]==MV_FROZEN
) continue;
390 assert(!IS_INTRA(s
->current_picture
.mb_type
[mb_xy
]));
391 assert(s
->last_picture_ptr
&& s
->last_picture_ptr
->data
[0]);
394 if(mb_x
>0 && fixed
[mb_xy
-1 ]==MV_FROZEN
) j
=1;
395 if(mb_x
+1<mb_width
&& fixed
[mb_xy
+1 ]==MV_FROZEN
) j
=1;
396 if(mb_y
>0 && fixed
[mb_xy
-mb_stride
]==MV_FROZEN
) j
=1;
397 if(mb_y
+1<mb_height
&& fixed
[mb_xy
+mb_stride
]==MV_FROZEN
) j
=1;
401 if(mb_x
>0 && fixed
[mb_xy
-1 ]==MV_CHANGED
) j
=1;
402 if(mb_x
+1<mb_width
&& fixed
[mb_xy
+1 ]==MV_CHANGED
) j
=1;
403 if(mb_y
>0 && fixed
[mb_xy
-mb_stride
]==MV_CHANGED
) j
=1;
404 if(mb_y
+1<mb_height
&& fixed
[mb_xy
+mb_stride
]==MV_CHANGED
) j
=1;
405 if(j
==0 && pass
>1) continue;
409 if(mb_x
>0 && fixed
[mb_xy
-1]){
410 mv_predictor
[pred_count
][0]= s
->current_picture
.motion_val
[0][mot_index
- 2][0];
411 mv_predictor
[pred_count
][1]= s
->current_picture
.motion_val
[0][mot_index
- 2][1];
414 if(mb_x
+1<mb_width
&& fixed
[mb_xy
+1]){
415 mv_predictor
[pred_count
][0]= s
->current_picture
.motion_val
[0][mot_index
+ 2][0];
416 mv_predictor
[pred_count
][1]= s
->current_picture
.motion_val
[0][mot_index
+ 2][1];
419 if(mb_y
>0 && fixed
[mb_xy
-mb_stride
]){
420 mv_predictor
[pred_count
][0]= s
->current_picture
.motion_val
[0][mot_index
- mot_stride
*2][0];
421 mv_predictor
[pred_count
][1]= s
->current_picture
.motion_val
[0][mot_index
- mot_stride
*2][1];
424 if(mb_y
+1<mb_height
&& fixed
[mb_xy
+mb_stride
]){
425 mv_predictor
[pred_count
][0]= s
->current_picture
.motion_val
[0][mot_index
+ mot_stride
*2][0];
426 mv_predictor
[pred_count
][1]= s
->current_picture
.motion_val
[0][mot_index
+ mot_stride
*2][1];
429 if(pred_count
==0) continue;
432 int sum_x
=0, sum_y
=0;
433 int max_x
, max_y
, min_x
, min_y
;
435 for(j
=0; j
<pred_count
; j
++){
436 sum_x
+= mv_predictor
[j
][0];
437 sum_y
+= mv_predictor
[j
][1];
441 mv_predictor
[pred_count
][0] = sum_x
/j
;
442 mv_predictor
[pred_count
][1] = sum_y
/j
;
449 min_x
=min_y
=max_x
=max_y
=0;
451 for(j
=0; j
<pred_count
; j
++){
452 max_x
= FFMAX(max_x
, mv_predictor
[j
][0]);
453 max_y
= FFMAX(max_y
, mv_predictor
[j
][1]);
454 min_x
= FFMIN(min_x
, mv_predictor
[j
][0]);
455 min_y
= FFMIN(min_y
, mv_predictor
[j
][1]);
457 mv_predictor
[pred_count
+1][0] = sum_x
- max_x
- min_x
;
458 mv_predictor
[pred_count
+1][1] = sum_y
- max_y
- min_y
;
461 mv_predictor
[pred_count
+1][0] /= 2;
462 mv_predictor
[pred_count
+1][1] /= 2;
471 mv_predictor
[pred_count
][0]= s
->current_picture
.motion_val
[0][mot_index
][0];
472 mv_predictor
[pred_count
][1]= s
->current_picture
.motion_val
[0][mot_index
][1];
475 s
->mv_dir
= MV_DIR_FORWARD
;
477 s
->mv_type
= MV_TYPE_16X16
;
480 s
->dsp
.clear_blocks(s
->block
[0]);
485 for(j
=0; j
<pred_count
; j
++){
487 uint8_t *src
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
489 s
->current_picture
.motion_val
[0][mot_index
][0]= s
->mv
[0][0][0]= mv_predictor
[j
][0];
490 s
->current_picture
.motion_val
[0][mot_index
][1]= s
->mv
[0][0][1]= mv_predictor
[j
][1];
494 if(mb_x
>0 && fixed
[mb_xy
-1]){
497 score
+= FFABS(src
[k
*s
->linesize
-1 ]-src
[k
*s
->linesize
]);
499 if(mb_x
+1<mb_width
&& fixed
[mb_xy
+1]){
502 score
+= FFABS(src
[k
*s
->linesize
+15]-src
[k
*s
->linesize
+16]);
504 if(mb_y
>0 && fixed
[mb_xy
-mb_stride
]){
507 score
+= FFABS(src
[k
-s
->linesize
]-src
[k
]);
509 if(mb_y
+1<mb_height
&& fixed
[mb_xy
+mb_stride
]){
512 score
+= FFABS(src
[k
+s
->linesize
*15]-src
[k
+s
->linesize
*16]);
515 if(score
<= best_score
){ // <= will favor the last MV
520 score_sum
+= best_score
;
521 //FIXME no need to set s->current_picture.motion_val[0][mot_index][0] explicit
522 s
->current_picture
.motion_val
[0][mot_index
][0]= s
->mv
[0][0][0]= mv_predictor
[best_pred
][0];
523 s
->current_picture
.motion_val
[0][mot_index
][1]= s
->mv
[0][0][1]= mv_predictor
[best_pred
][1];
528 if(s
->mv
[0][0][0] != prev_x
|| s
->mv
[0][0][1] != prev_y
){
529 fixed
[mb_xy
]=MV_CHANGED
;
532 fixed
[mb_xy
]=MV_UNCHANGED
;
536 // printf(".%d/%d", changed, score_sum); fflush(stdout);
542 for(i
=0; i
<s
->mb_num
; i
++){
543 int mb_xy
= s
->mb_index2xy
[i
];
545 fixed
[mb_xy
]=MV_FROZEN
;
547 // printf(":"); fflush(stdout);
551 static int is_intra_more_likely(MpegEncContext
*s
){
552 int is_intra_likely
, i
, j
, undamaged_count
, skip_amount
, mb_x
, mb_y
;
554 if(!s
->last_picture_ptr
|| !s
->last_picture_ptr
->data
[0]) return 1; //no previous frame available -> use spatial prediction
557 for(i
=0; i
<s
->mb_num
; i
++){
558 const int mb_xy
= s
->mb_index2xy
[i
];
559 const int error
= s
->error_status_table
[mb_xy
];
560 if(!((error
&DC_ERROR
) && (error
&MV_ERROR
)))
564 if(undamaged_count
< 5) return 0; //almost all MBs damaged -> use temporal prediction
566 //prevent dsp.sad() check, that requires access to the image
567 if(CONFIG_MPEG_XVMC_DECODER
&& s
->avctx
->xvmc_acceleration
&& s
->pict_type
== FF_I_TYPE
)
570 skip_amount
= FFMAX(undamaged_count
/50, 1); //check only upto 50 MBs
574 for(mb_y
= 0; mb_y
<s
->mb_height
-1; mb_y
++){
575 for(mb_x
= 0; mb_x
<s
->mb_width
; mb_x
++){
577 const int mb_xy
= mb_x
+ mb_y
*s
->mb_stride
;
579 error
= s
->error_status_table
[mb_xy
];
580 if((error
&DC_ERROR
) && (error
&MV_ERROR
))
581 continue; //skip damaged
584 if((j
%skip_amount
) != 0) continue; //skip a few to speed things up
586 if(s
->pict_type
==FF_I_TYPE
){
587 uint8_t *mb_ptr
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
588 uint8_t *last_mb_ptr
= s
->last_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
590 is_intra_likely
+= s
->dsp
.sad
[0](NULL
, last_mb_ptr
, mb_ptr
, s
->linesize
, 16);
591 is_intra_likely
-= s
->dsp
.sad
[0](NULL
, last_mb_ptr
, last_mb_ptr
+s
->linesize
*16, s
->linesize
, 16);
593 if(IS_INTRA(s
->current_picture
.mb_type
[mb_xy
]))
600 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
601 return is_intra_likely
> 0;
604 void ff_er_frame_start(MpegEncContext
*s
){
605 if(!s
->error_recognition
) return;
607 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));
608 s
->error_count
= 3*s
->mb_num
;
613 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
614 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
615 * error of the same type occurred
617 void ff_er_add_slice(MpegEncContext
*s
, int startx
, int starty
, int endx
, int endy
, int status
){
618 const int start_i
= av_clip(startx
+ starty
* s
->mb_width
, 0, s
->mb_num
-1);
619 const int end_i
= av_clip(endx
+ endy
* s
->mb_width
, 0, s
->mb_num
);
620 const int start_xy
= s
->mb_index2xy
[start_i
];
621 const int end_xy
= s
->mb_index2xy
[end_i
];
624 if(s
->avctx
->hwaccel
)
627 if(start_i
> end_i
|| start_xy
> end_xy
){
628 av_log(s
->avctx
, AV_LOG_ERROR
, "internal error, slice end before start\n");
632 if(!s
->error_recognition
) return;
635 if(status
& (AC_ERROR
|AC_END
)){
636 mask
&= ~(AC_ERROR
|AC_END
);
637 s
->error_count
-= end_i
- start_i
+ 1;
639 if(status
& (DC_ERROR
|DC_END
)){
640 mask
&= ~(DC_ERROR
|DC_END
);
641 s
->error_count
-= end_i
- start_i
+ 1;
643 if(status
& (MV_ERROR
|MV_END
)){
644 mask
&= ~(MV_ERROR
|MV_END
);
645 s
->error_count
-= end_i
- start_i
+ 1;
648 if(status
& (AC_ERROR
|DC_ERROR
|MV_ERROR
)) s
->error_count
= INT_MAX
;
651 memset(&s
->error_status_table
[start_xy
], 0, (end_xy
- start_xy
) * sizeof(uint8_t));
654 for(i
=start_xy
; i
<end_xy
; i
++){
655 s
->error_status_table
[ i
] &= mask
;
659 if(end_i
== s
->mb_num
)
660 s
->error_count
= INT_MAX
;
662 s
->error_status_table
[end_xy
] &= mask
;
663 s
->error_status_table
[end_xy
] |= status
;
666 s
->error_status_table
[start_xy
] |= VP_START
;
668 if(start_xy
> 0 && s
->avctx
->thread_count
<= 1 && s
->avctx
->skip_top
*s
->mb_width
< start_i
){
669 int prev_status
= s
->error_status_table
[ s
->mb_index2xy
[start_i
- 1] ];
671 prev_status
&= ~ VP_START
;
672 if(prev_status
!= (MV_END
|DC_END
|AC_END
)) s
->error_count
= INT_MAX
;
676 void ff_er_frame_end(MpegEncContext
*s
){
677 int i
, mb_x
, mb_y
, error
, error_type
, dc_error
, mv_error
, ac_error
;
679 int threshold_part
[4]= {100,100,100};
682 int size
= s
->b8_stride
* 2 * s
->mb_height
;
683 Picture
*pic
= s
->current_picture_ptr
;
685 if(!s
->error_recognition
|| s
->error_count
==0 || s
->avctx
->lowres
||
687 s
->avctx
->codec
->capabilities
&CODEC_CAP_HWACCEL_VDPAU
||
688 s
->error_count
==3*s
->mb_width
*(s
->avctx
->skip_top
+ s
->avctx
->skip_bottom
)) return;
690 if(s
->current_picture
.motion_val
[0] == NULL
){
691 av_log(s
->avctx
, AV_LOG_ERROR
, "Warning MVs not available\n");
694 pic
->ref_index
[i
]= av_mallocz(size
* sizeof(uint8_t));
695 pic
->motion_val_base
[i
]= av_mallocz((size
+4) * 2 * sizeof(uint16_t));
696 pic
->motion_val
[i
]= pic
->motion_val_base
[i
]+4;
698 pic
->motion_subsample_log2
= 3;
699 s
->current_picture
= *s
->current_picture_ptr
;
703 if(pic
->ref_index
[i
])
704 memset(pic
->ref_index
[i
], 0, size
* sizeof(uint8_t));
707 if(s
->avctx
->debug
&FF_DEBUG_ER
){
708 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
709 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
710 int status
= s
->error_status_table
[mb_x
+ mb_y
*s
->mb_stride
];
712 av_log(s
->avctx
, AV_LOG_DEBUG
, "%2X ", status
);
714 av_log(s
->avctx
, AV_LOG_DEBUG
, "\n");
719 /* handle overlapping slices */
720 for(error_type
=1; error_type
<=3; error_type
++){
723 for(i
=s
->mb_num
-1; i
>=0; i
--){
724 const int mb_xy
= s
->mb_index2xy
[i
];
725 int error
= s
->error_status_table
[mb_xy
];
727 if(error
&(1<<error_type
))
729 if(error
&(8<<error_type
))
733 s
->error_status_table
[mb_xy
]|= 1<<error_type
;
741 /* handle slices with partitions of different length */
742 if(s
->partitioned_frame
){
745 for(i
=s
->mb_num
-1; i
>=0; i
--){
746 const int mb_xy
= s
->mb_index2xy
[i
];
747 int error
= s
->error_status_table
[mb_xy
];
751 if((error
&MV_END
) || (error
&DC_END
) || (error
&AC_ERROR
))
755 s
->error_status_table
[mb_xy
]|= AC_ERROR
;
762 /* handle missing slices */
763 if(s
->error_recognition
>=4){
766 for(i
=s
->mb_num
-2; i
>=s
->mb_width
+100; i
--){ //FIXME +100 hack
767 const int mb_xy
= s
->mb_index2xy
[i
];
768 int error1
= s
->error_status_table
[mb_xy
];
769 int error2
= s
->error_status_table
[s
->mb_index2xy
[i
+1]];
774 if( error2
==(VP_START
|DC_ERROR
|AC_ERROR
|MV_ERROR
|AC_END
|DC_END
|MV_END
)
775 && error1
!=(VP_START
|DC_ERROR
|AC_ERROR
|MV_ERROR
|AC_END
|DC_END
|MV_END
)
776 && ((error1
&AC_END
) || (error1
&DC_END
) || (error1
&MV_END
))){ //end & uninit
781 s
->error_status_table
[mb_xy
]|= DC_ERROR
|AC_ERROR
|MV_ERROR
;
786 /* backward mark errors */
788 for(error_type
=1; error_type
<=3; error_type
++){
789 for(i
=s
->mb_num
-1; i
>=0; i
--){
790 const int mb_xy
= s
->mb_index2xy
[i
];
791 int error
= s
->error_status_table
[mb_xy
];
793 if(!s
->mbskip_table
[mb_xy
]) //FIXME partition specific
795 if(error
&(1<<error_type
))
798 if(s
->partitioned_frame
){
799 if(distance
< threshold_part
[error_type
-1])
800 s
->error_status_table
[mb_xy
]|= 1<<error_type
;
802 if(distance
< threshold
)
803 s
->error_status_table
[mb_xy
]|= 1<<error_type
;
812 /* forward mark errors */
814 for(i
=0; i
<s
->mb_num
; i
++){
815 const int mb_xy
= s
->mb_index2xy
[i
];
816 int old_error
= s
->error_status_table
[mb_xy
];
818 if(old_error
&VP_START
)
819 error
= old_error
& (DC_ERROR
|AC_ERROR
|MV_ERROR
);
821 error
|= old_error
& (DC_ERROR
|AC_ERROR
|MV_ERROR
);
822 s
->error_status_table
[mb_xy
]|= error
;
826 /* handle not partitioned case */
827 if(!s
->partitioned_frame
){
828 for(i
=0; i
<s
->mb_num
; i
++){
829 const int mb_xy
= s
->mb_index2xy
[i
];
830 error
= s
->error_status_table
[mb_xy
];
831 if(error
&(AC_ERROR
|DC_ERROR
|MV_ERROR
))
832 error
|= AC_ERROR
|DC_ERROR
|MV_ERROR
;
833 s
->error_status_table
[mb_xy
]= error
;
838 dc_error
= ac_error
= mv_error
=0;
839 for(i
=0; i
<s
->mb_num
; i
++){
840 const int mb_xy
= s
->mb_index2xy
[i
];
841 error
= s
->error_status_table
[mb_xy
];
842 if(error
&DC_ERROR
) dc_error
++;
843 if(error
&AC_ERROR
) ac_error
++;
844 if(error
&MV_ERROR
) mv_error
++;
846 av_log(s
->avctx
, AV_LOG_INFO
, "concealing %d DC, %d AC, %d MV errors\n", dc_error
, ac_error
, mv_error
);
848 is_intra_likely
= is_intra_more_likely(s
);
850 /* set unknown mb-type to most likely */
851 for(i
=0; i
<s
->mb_num
; i
++){
852 const int mb_xy
= s
->mb_index2xy
[i
];
853 error
= s
->error_status_table
[mb_xy
];
854 if(!((error
&DC_ERROR
) && (error
&MV_ERROR
)))
858 s
->current_picture
.mb_type
[mb_xy
]= MB_TYPE_INTRA4x4
;
860 s
->current_picture
.mb_type
[mb_xy
]= MB_TYPE_16x16
| MB_TYPE_L0
;
863 // change inter to intra blocks if no reference frames are available
864 if (!s
->last_picture
.data
[0] && !s
->next_picture
.data
[0])
865 for(i
=0; i
<s
->mb_num
; i
++){
866 const int mb_xy
= s
->mb_index2xy
[i
];
867 if(!IS_INTRA(s
->current_picture
.mb_type
[mb_xy
]))
868 s
->current_picture
.mb_type
[mb_xy
]= MB_TYPE_INTRA4x4
;
871 /* handle inter blocks with damaged AC */
872 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
873 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
874 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
875 const int mb_type
= s
->current_picture
.mb_type
[mb_xy
];
876 int dir
= !s
->last_picture
.data
[0];
877 error
= s
->error_status_table
[mb_xy
];
879 if(IS_INTRA(mb_type
)) continue; //intra
880 if(error
&MV_ERROR
) continue; //inter with damaged MV
881 if(!(error
&AC_ERROR
)) continue; //undamaged inter
883 s
->mv_dir
= dir
? MV_DIR_BACKWARD
: MV_DIR_FORWARD
;
887 int mb_index
= mb_x
*2 + mb_y
*2*s
->b8_stride
;
889 s
->mv_type
= MV_TYPE_8X8
;
891 s
->mv
[0][j
][0] = s
->current_picture
.motion_val
[dir
][ mb_index
+ (j
&1) + (j
>>1)*s
->b8_stride
][0];
892 s
->mv
[0][j
][1] = s
->current_picture
.motion_val
[dir
][ mb_index
+ (j
&1) + (j
>>1)*s
->b8_stride
][1];
895 s
->mv_type
= MV_TYPE_16X16
;
896 s
->mv
[0][0][0] = s
->current_picture
.motion_val
[dir
][ mb_x
*2 + mb_y
*2*s
->b8_stride
][0];
897 s
->mv
[0][0][1] = s
->current_picture
.motion_val
[dir
][ mb_x
*2 + mb_y
*2*s
->b8_stride
][1];
900 s
->dsp
.clear_blocks(s
->block
[0]);
909 if(s
->pict_type
==FF_B_TYPE
){
910 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
911 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
912 int xy
= mb_x
*2 + mb_y
*2*s
->b8_stride
;
913 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
914 const int mb_type
= s
->current_picture
.mb_type
[mb_xy
];
915 error
= s
->error_status_table
[mb_xy
];
917 if(IS_INTRA(mb_type
)) continue;
918 if(!(error
&MV_ERROR
)) continue; //inter with undamaged MV
919 if(!(error
&AC_ERROR
)) continue; //undamaged inter
921 s
->mv_dir
= MV_DIR_FORWARD
|MV_DIR_BACKWARD
;
922 if(!s
->last_picture
.data
[0]) s
->mv_dir
&= ~MV_DIR_FORWARD
;
923 if(!s
->next_picture
.data
[0]) s
->mv_dir
&= ~MV_DIR_BACKWARD
;
925 s
->mv_type
= MV_TYPE_16X16
;
929 int time_pp
= s
->pp_time
;
930 int time_pb
= s
->pb_time
;
932 s
->mv
[0][0][0] = s
->next_picture
.motion_val
[0][xy
][0]*time_pb
/time_pp
;
933 s
->mv
[0][0][1] = s
->next_picture
.motion_val
[0][xy
][1]*time_pb
/time_pp
;
934 s
->mv
[1][0][0] = s
->next_picture
.motion_val
[0][xy
][0]*(time_pb
- time_pp
)/time_pp
;
935 s
->mv
[1][0][1] = s
->next_picture
.motion_val
[0][xy
][1]*(time_pb
- time_pp
)/time_pp
;
943 s
->dsp
.clear_blocks(s
->block
[0]);
952 /* the filters below are not XvMC compatible, skip them */
953 if(CONFIG_MPEG_XVMC_DECODER
&& s
->avctx
->xvmc_acceleration
)
955 /* fill DC for inter blocks */
956 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
957 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
958 int dc
, dcu
, dcv
, y
, n
;
960 uint8_t *dest_y
, *dest_cb
, *dest_cr
;
961 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
962 const int mb_type
= s
->current_picture
.mb_type
[mb_xy
];
964 error
= s
->error_status_table
[mb_xy
];
966 if(IS_INTRA(mb_type
) && s
->partitioned_frame
) continue;
967 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
969 dest_y
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
970 dest_cb
= s
->current_picture
.data
[1] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
971 dest_cr
= s
->current_picture
.data
[2] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
973 dc_ptr
= &s
->dc_val
[0][mb_x
*2 + mb_y
*2*s
->b8_stride
];
979 dc
+= dest_y
[x
+ (n
&1)*8 + (y
+ (n
>>1)*8)*s
->linesize
];
982 dc_ptr
[(n
&1) + (n
>>1)*s
->b8_stride
]= (dc
+4)>>3;
989 dcu
+=dest_cb
[x
+ y
*(s
->uvlinesize
)];
990 dcv
+=dest_cr
[x
+ y
*(s
->uvlinesize
)];
993 s
->dc_val
[1][mb_x
+ mb_y
*s
->mb_stride
]= (dcu
+4)>>3;
994 s
->dc_val
[2][mb_x
+ mb_y
*s
->mb_stride
]= (dcv
+4)>>3;
998 /* guess DC for damaged blocks */
999 guess_dc(s
, s
->dc_val
[0], s
->mb_width
*2, s
->mb_height
*2, s
->b8_stride
, 1);
1000 guess_dc(s
, s
->dc_val
[1], s
->mb_width
, s
->mb_height
, s
->mb_stride
, 0);
1001 guess_dc(s
, s
->dc_val
[2], s
->mb_width
, s
->mb_height
, s
->mb_stride
, 0);
1003 /* filter luma DC */
1004 filter181(s
->dc_val
[0], s
->mb_width
*2, s
->mb_height
*2, s
->b8_stride
);
1007 /* render DC only intra */
1008 for(mb_y
=0; mb_y
<s
->mb_height
; mb_y
++){
1009 for(mb_x
=0; mb_x
<s
->mb_width
; mb_x
++){
1010 uint8_t *dest_y
, *dest_cb
, *dest_cr
;
1011 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
1012 const int mb_type
= s
->current_picture
.mb_type
[mb_xy
];
1014 error
= s
->error_status_table
[mb_xy
];
1016 if(IS_INTER(mb_type
)) continue;
1017 if(!(error
&AC_ERROR
)) continue; //undamaged
1019 dest_y
= s
->current_picture
.data
[0] + mb_x
*16 + mb_y
*16*s
->linesize
;
1020 dest_cb
= s
->current_picture
.data
[1] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
1021 dest_cr
= s
->current_picture
.data
[2] + mb_x
*8 + mb_y
*8 *s
->uvlinesize
;
1023 put_dc(s
, dest_y
, dest_cb
, dest_cr
, mb_x
, mb_y
);
1028 if(s
->avctx
->error_concealment
&FF_EC_DEBLOCK
){
1029 /* filter horizontal block boundaries */
1030 h_block_filter(s
, s
->current_picture
.data
[0], s
->mb_width
*2, s
->mb_height
*2, s
->linesize
, 1);
1031 h_block_filter(s
, s
->current_picture
.data
[1], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
1032 h_block_filter(s
, s
->current_picture
.data
[2], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
1034 /* filter vertical block boundaries */
1035 v_block_filter(s
, s
->current_picture
.data
[0], s
->mb_width
*2, s
->mb_height
*2, s
->linesize
, 1);
1036 v_block_filter(s
, s
->current_picture
.data
[1], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
1037 v_block_filter(s
, s
->current_picture
.data
[2], s
->mb_width
, s
->mb_height
, s
->uvlinesize
, 0);
1041 /* clean a few tables */
1042 for(i
=0; i
<s
->mb_num
; i
++){
1043 const int mb_xy
= s
->mb_index2xy
[i
];
1044 int error
= s
->error_status_table
[mb_xy
];
1046 if(s
->pict_type
!=FF_B_TYPE
&& (error
&(DC_ERROR
|MV_ERROR
|AC_ERROR
))){
1047 s
->mbskip_table
[mb_xy
]=0;
1049 s
->mbintra_table
[mb_xy
]=1;