2 * Error resilience / concealment
4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 * This file is part of Libav.
8 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Error resilience / concealment.
30 #include "libavutil/internal.h"
32 #include "error_resilience.h"
33 #include "mpegvideo.h"
34 #include "rectangle.h"
39 * @param stride the number of MVs to get to the next row
40 * @param mv_step the number of MVs per row or column in a macroblock
42 static void set_mv_strides(ERContext
*s
, int *mv_step
, int *stride
)
44 if (s
->avctx
->codec_id
== AV_CODEC_ID_H264
) {
45 assert(s
->quarter_sample
);
47 *stride
= s
->mb_width
* 4;
50 *stride
= s
->b8_stride
;
55 * Replace the current MB with a flat dc-only version.
57 static void put_dc(ERContext
*s
, uint8_t *dest_y
, uint8_t *dest_cb
,
58 uint8_t *dest_cr
, int mb_x
, int mb_y
)
60 int *linesize
= s
->cur_pic
->f
.linesize
;
61 int dc
, dcu
, dcv
, y
, i
;
62 for (i
= 0; i
< 4; i
++) {
63 dc
= s
->dc_val
[0][mb_x
* 2 + (i
& 1) + (mb_y
* 2 + (i
>> 1)) * s
->b8_stride
];
68 for (y
= 0; y
< 8; y
++) {
70 for (x
= 0; x
< 8; x
++)
71 dest_y
[x
+ (i
& 1) * 8 + (y
+ (i
>> 1) * 8) * linesize
[0]] = dc
/ 8;
74 dcu
= s
->dc_val
[1][mb_x
+ mb_y
* s
->mb_stride
];
75 dcv
= s
->dc_val
[2][mb_x
+ mb_y
* s
->mb_stride
];
84 for (y
= 0; y
< 8; y
++) {
86 for (x
= 0; x
< 8; x
++) {
87 dest_cb
[x
+ y
* linesize
[1]] = dcu
/ 8;
88 dest_cr
[x
+ y
* linesize
[2]] = dcv
/ 8;
93 static void filter181(int16_t *data
, int width
, int height
, int stride
)
97 /* horizontal filter */
98 for (y
= 1; y
< height
- 1; y
++) {
99 int prev_dc
= data
[0 + y
* stride
];
101 for (x
= 1; x
< width
- 1; x
++) {
104 data
[x
+ y
* stride
] * 8 -
105 data
[x
+ 1 + y
* stride
];
106 dc
= (dc
* 10923 + 32768) >> 16;
107 prev_dc
= data
[x
+ y
* stride
];
108 data
[x
+ y
* stride
] = dc
;
112 /* vertical filter */
113 for (x
= 1; x
< width
- 1; x
++) {
114 int prev_dc
= data
[x
];
116 for (y
= 1; y
< height
- 1; y
++) {
120 data
[x
+ y
* stride
] * 8 -
121 data
[x
+ (y
+ 1) * stride
];
122 dc
= (dc
* 10923 + 32768) >> 16;
123 prev_dc
= data
[x
+ y
* stride
];
124 data
[x
+ y
* stride
] = dc
;
130 * guess the dc of blocks which do not have an undamaged dc
131 * @param w width in 8 pixel blocks
132 * @param h height in 8 pixel blocks
134 static void guess_dc(ERContext
*s
, int16_t *dc
, int w
,
135 int h
, int stride
, int is_luma
)
139 for (b_y
= 0; b_y
< h
; b_y
++) {
140 for (b_x
= 0; b_x
< w
; b_x
++) {
141 int color
[4] = { 1024, 1024, 1024, 1024 };
142 int distance
[4] = { 9999, 9999, 9999, 9999 };
143 int mb_index
, error
, j
;
144 int64_t guess
, weight_sum
;
145 mb_index
= (b_x
>> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
;
146 error
= s
->error_status_table
[mb_index
];
148 if (IS_INTER(s
->cur_pic
->mb_type
[mb_index
]))
150 if (!(error
& ER_DC_ERROR
))
154 for (j
= b_x
+ 1; j
< w
; j
++) {
155 int mb_index_j
= (j
>> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
;
156 int error_j
= s
->error_status_table
[mb_index_j
];
157 int intra_j
= IS_INTRA(s
->cur_pic
->mb_type
[mb_index_j
]);
158 if (intra_j
== 0 || !(error_j
& ER_DC_ERROR
)) {
159 color
[0] = dc
[j
+ b_y
* stride
];
160 distance
[0] = j
- b_x
;
166 for (j
= b_x
- 1; j
>= 0; j
--) {
167 int mb_index_j
= (j
>> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
;
168 int error_j
= s
->error_status_table
[mb_index_j
];
169 int intra_j
= IS_INTRA(s
->cur_pic
->mb_type
[mb_index_j
]);
170 if (intra_j
== 0 || !(error_j
& ER_DC_ERROR
)) {
171 color
[1] = dc
[j
+ b_y
* stride
];
172 distance
[1] = b_x
- j
;
178 for (j
= b_y
+ 1; j
< h
; j
++) {
179 int mb_index_j
= (b_x
>> is_luma
) + (j
>> is_luma
) * s
->mb_stride
;
180 int error_j
= s
->error_status_table
[mb_index_j
];
181 int intra_j
= IS_INTRA(s
->cur_pic
->mb_type
[mb_index_j
]);
183 if (intra_j
== 0 || !(error_j
& ER_DC_ERROR
)) {
184 color
[2] = dc
[b_x
+ j
* stride
];
185 distance
[2] = j
- b_y
;
191 for (j
= b_y
- 1; j
>= 0; j
--) {
192 int mb_index_j
= (b_x
>> is_luma
) + (j
>> is_luma
) * s
->mb_stride
;
193 int error_j
= s
->error_status_table
[mb_index_j
];
194 int intra_j
= IS_INTRA(s
->cur_pic
->mb_type
[mb_index_j
]);
195 if (intra_j
== 0 || !(error_j
& ER_DC_ERROR
)) {
196 color
[3] = dc
[b_x
+ j
* stride
];
197 distance
[3] = b_y
- j
;
204 for (j
= 0; j
< 4; j
++) {
205 int64_t weight
= 256 * 256 * 256 * 16 / distance
[j
];
206 guess
+= weight
* (int64_t) color
[j
];
207 weight_sum
+= weight
;
209 guess
= (guess
+ weight_sum
/ 2) / weight_sum
;
210 dc
[b_x
+ b_y
* stride
] = guess
;
216 * simple horizontal deblocking filter used for error resilience
217 * @param w width in 8 pixel blocks
218 * @param h height in 8 pixel blocks
220 static void h_block_filter(ERContext
*s
, uint8_t *dst
, int w
,
221 int h
, int stride
, int is_luma
)
223 int b_x
, b_y
, mvx_stride
, mvy_stride
;
224 const uint8_t *cm
= ff_crop_tab
+ MAX_NEG_CROP
;
225 set_mv_strides(s
, &mvx_stride
, &mvy_stride
);
226 mvx_stride
>>= is_luma
;
227 mvy_stride
*= mvx_stride
;
229 for (b_y
= 0; b_y
< h
; b_y
++) {
230 for (b_x
= 0; b_x
< w
- 1; b_x
++) {
232 int left_status
= s
->error_status_table
[( b_x
>> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
];
233 int right_status
= s
->error_status_table
[((b_x
+ 1) >> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
];
234 int left_intra
= IS_INTRA(s
->cur_pic
->mb_type
[( b_x
>> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
]);
235 int right_intra
= IS_INTRA(s
->cur_pic
->mb_type
[((b_x
+ 1) >> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
]);
236 int left_damage
= left_status
& ER_MB_ERROR
;
237 int right_damage
= right_status
& ER_MB_ERROR
;
238 int offset
= b_x
* 8 + b_y
* stride
* 8;
239 int16_t *left_mv
= s
->cur_pic
->motion_val
[0][mvy_stride
* b_y
+ mvx_stride
* b_x
];
240 int16_t *right_mv
= s
->cur_pic
->motion_val
[0][mvy_stride
* b_y
+ mvx_stride
* (b_x
+ 1)];
241 if (!(left_damage
|| right_damage
))
242 continue; // both undamaged
243 if ((!left_intra
) && (!right_intra
) &&
244 FFABS(left_mv
[0] - right_mv
[0]) +
245 FFABS(left_mv
[1] + right_mv
[1]) < 2)
248 for (y
= 0; y
< 8; y
++) {
251 a
= dst
[offset
+ 7 + y
* stride
] - dst
[offset
+ 6 + y
* stride
];
252 b
= dst
[offset
+ 8 + y
* stride
] - dst
[offset
+ 7 + y
* stride
];
253 c
= dst
[offset
+ 9 + y
* stride
] - dst
[offset
+ 8 + y
* stride
];
255 d
= FFABS(b
) - ((FFABS(a
) + FFABS(c
) + 1) >> 1);
263 if (!(left_damage
&& right_damage
))
267 dst
[offset
+ 7 + y
* stride
] = cm
[dst
[offset
+ 7 + y
* stride
] + ((d
* 7) >> 4)];
268 dst
[offset
+ 6 + y
* stride
] = cm
[dst
[offset
+ 6 + y
* stride
] + ((d
* 5) >> 4)];
269 dst
[offset
+ 5 + y
* stride
] = cm
[dst
[offset
+ 5 + y
* stride
] + ((d
* 3) >> 4)];
270 dst
[offset
+ 4 + y
* stride
] = cm
[dst
[offset
+ 4 + y
* stride
] + ((d
* 1) >> 4)];
273 dst
[offset
+ 8 + y
* stride
] = cm
[dst
[offset
+ 8 + y
* stride
] - ((d
* 7) >> 4)];
274 dst
[offset
+ 9 + y
* stride
] = cm
[dst
[offset
+ 9 + y
* stride
] - ((d
* 5) >> 4)];
275 dst
[offset
+ 10+ y
* stride
] = cm
[dst
[offset
+ 10 + y
* stride
] - ((d
* 3) >> 4)];
276 dst
[offset
+ 11+ y
* stride
] = cm
[dst
[offset
+ 11 + y
* stride
] - ((d
* 1) >> 4)];
284 * simple vertical deblocking filter used for error resilience
285 * @param w width in 8 pixel blocks
286 * @param h height in 8 pixel blocks
288 static void v_block_filter(ERContext
*s
, uint8_t *dst
, int w
, int h
,
289 int stride
, int is_luma
)
291 int b_x
, b_y
, mvx_stride
, mvy_stride
;
292 const uint8_t *cm
= ff_crop_tab
+ MAX_NEG_CROP
;
293 set_mv_strides(s
, &mvx_stride
, &mvy_stride
);
294 mvx_stride
>>= is_luma
;
295 mvy_stride
*= mvx_stride
;
297 for (b_y
= 0; b_y
< h
- 1; b_y
++) {
298 for (b_x
= 0; b_x
< w
; b_x
++) {
300 int top_status
= s
->error_status_table
[(b_x
>> is_luma
) + (b_y
>> is_luma
) * s
->mb_stride
];
301 int bottom_status
= s
->error_status_table
[(b_x
>> is_luma
) + ((b_y
+ 1) >> is_luma
) * s
->mb_stride
];
302 int top_intra
= IS_INTRA(s
->cur_pic
->mb_type
[(b_x
>> is_luma
) + ( b_y
>> is_luma
) * s
->mb_stride
]);
303 int bottom_intra
= IS_INTRA(s
->cur_pic
->mb_type
[(b_x
>> is_luma
) + ((b_y
+ 1) >> is_luma
) * s
->mb_stride
]);
304 int top_damage
= top_status
& ER_MB_ERROR
;
305 int bottom_damage
= bottom_status
& ER_MB_ERROR
;
306 int offset
= b_x
* 8 + b_y
* stride
* 8;
308 int16_t *top_mv
= s
->cur_pic
->motion_val
[0][mvy_stride
* b_y
+ mvx_stride
* b_x
];
309 int16_t *bottom_mv
= s
->cur_pic
->motion_val
[0][mvy_stride
* (b_y
+ 1) + mvx_stride
* b_x
];
311 if (!(top_damage
|| bottom_damage
))
312 continue; // both undamaged
314 if ((!top_intra
) && (!bottom_intra
) &&
315 FFABS(top_mv
[0] - bottom_mv
[0]) +
316 FFABS(top_mv
[1] + bottom_mv
[1]) < 2)
319 for (x
= 0; x
< 8; x
++) {
322 a
= dst
[offset
+ x
+ 7 * stride
] - dst
[offset
+ x
+ 6 * stride
];
323 b
= dst
[offset
+ x
+ 8 * stride
] - dst
[offset
+ x
+ 7 * stride
];
324 c
= dst
[offset
+ x
+ 9 * stride
] - dst
[offset
+ x
+ 8 * stride
];
326 d
= FFABS(b
) - ((FFABS(a
) + FFABS(c
) + 1) >> 1);
334 if (!(top_damage
&& bottom_damage
))
338 dst
[offset
+ x
+ 7 * stride
] = cm
[dst
[offset
+ x
+ 7 * stride
] + ((d
* 7) >> 4)];
339 dst
[offset
+ x
+ 6 * stride
] = cm
[dst
[offset
+ x
+ 6 * stride
] + ((d
* 5) >> 4)];
340 dst
[offset
+ x
+ 5 * stride
] = cm
[dst
[offset
+ x
+ 5 * stride
] + ((d
* 3) >> 4)];
341 dst
[offset
+ x
+ 4 * stride
] = cm
[dst
[offset
+ x
+ 4 * stride
] + ((d
* 1) >> 4)];
344 dst
[offset
+ x
+ 8 * stride
] = cm
[dst
[offset
+ x
+ 8 * stride
] - ((d
* 7) >> 4)];
345 dst
[offset
+ x
+ 9 * stride
] = cm
[dst
[offset
+ x
+ 9 * stride
] - ((d
* 5) >> 4)];
346 dst
[offset
+ x
+ 10 * stride
] = cm
[dst
[offset
+ x
+ 10 * stride
] - ((d
* 3) >> 4)];
347 dst
[offset
+ x
+ 11 * stride
] = cm
[dst
[offset
+ x
+ 11 * stride
] - ((d
* 1) >> 4)];
354 static void guess_mv(ERContext
*s
)
356 uint8_t *fixed
= s
->er_temp_buffer
;
359 #define MV_UNCHANGED 1
360 const int mb_stride
= s
->mb_stride
;
361 const int mb_width
= s
->mb_width
;
362 const int mb_height
= s
->mb_height
;
363 int i
, depth
, num_avail
;
364 int mb_x
, mb_y
, mot_step
, mot_stride
;
366 set_mv_strides(s
, &mot_step
, &mot_stride
);
369 for (i
= 0; i
< s
->mb_num
; i
++) {
370 const int mb_xy
= s
->mb_index2xy
[i
];
372 int error
= s
->error_status_table
[mb_xy
];
374 if (IS_INTRA(s
->cur_pic
->mb_type
[mb_xy
]))
375 f
= MV_FROZEN
; // intra // FIXME check
376 if (!(error
& ER_MV_ERROR
))
377 f
= MV_FROZEN
; // inter with undamaged MV
384 if ((!(s
->avctx
->error_concealment
&FF_EC_GUESS_MVS
)) ||
385 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 int mv_dir
= (s
->last_pic
&& s
->last_pic
->f
.data
[0]) ? MV_DIR_FORWARD
: MV_DIR_BACKWARD
;
391 if (IS_INTRA(s
->cur_pic
->mb_type
[mb_xy
]))
393 if (!(s
->error_status_table
[mb_xy
] & ER_MV_ERROR
))
398 s
->decode_mb(s
->opaque
, 0, mv_dir
, MV_TYPE_16X16
, &s
->mv
,
405 for (depth
= 0; ; depth
++) {
406 int changed
, pass
, none_left
;
410 for (pass
= 0; (changed
|| pass
< 2) && pass
< 10; pass
++) {
415 for (mb_y
= 0; mb_y
< s
->mb_height
; mb_y
++) {
416 for (mb_x
= 0; mb_x
< s
->mb_width
; mb_x
++) {
417 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
418 int mv_predictor
[8][2] = { { 0 } };
422 int best_score
= 256 * 256 * 256 * 64;
424 const int mot_index
= (mb_x
+ mb_y
* mot_stride
) * mot_step
;
425 int prev_x
, prev_y
, prev_ref
;
427 if ((mb_x
^ mb_y
^ pass
) & 1)
430 if (fixed
[mb_xy
] == MV_FROZEN
)
432 assert(!IS_INTRA(s
->cur_pic
->mb_type
[mb_xy
]));
433 assert(s
->last_pic
&& s
->last_pic
->f
.data
[0]);
436 if (mb_x
> 0 && fixed
[mb_xy
- 1] == MV_FROZEN
)
438 if (mb_x
+ 1 < mb_width
&& fixed
[mb_xy
+ 1] == MV_FROZEN
)
440 if (mb_y
> 0 && fixed
[mb_xy
- mb_stride
] == MV_FROZEN
)
442 if (mb_y
+ 1 < mb_height
&& fixed
[mb_xy
+ mb_stride
] == MV_FROZEN
)
448 if (mb_x
> 0 && fixed
[mb_xy
- 1 ] == MV_CHANGED
)
450 if (mb_x
+ 1 < mb_width
&& fixed
[mb_xy
+ 1 ] == MV_CHANGED
)
452 if (mb_y
> 0 && fixed
[mb_xy
- mb_stride
] == MV_CHANGED
)
454 if (mb_y
+ 1 < mb_height
&& fixed
[mb_xy
+ mb_stride
] == MV_CHANGED
)
456 if (j
== 0 && pass
> 1)
461 if (mb_x
> 0 && fixed
[mb_xy
- 1]) {
462 mv_predictor
[pred_count
][0] =
463 s
->cur_pic
->motion_val
[0][mot_index
- mot_step
][0];
464 mv_predictor
[pred_count
][1] =
465 s
->cur_pic
->motion_val
[0][mot_index
- mot_step
][1];
467 s
->cur_pic
->ref_index
[0][4 * (mb_xy
- 1)];
470 if (mb_x
+ 1 < mb_width
&& fixed
[mb_xy
+ 1]) {
471 mv_predictor
[pred_count
][0] =
472 s
->cur_pic
->motion_val
[0][mot_index
+ mot_step
][0];
473 mv_predictor
[pred_count
][1] =
474 s
->cur_pic
->motion_val
[0][mot_index
+ mot_step
][1];
476 s
->cur_pic
->ref_index
[0][4 * (mb_xy
+ 1)];
479 if (mb_y
> 0 && fixed
[mb_xy
- mb_stride
]) {
480 mv_predictor
[pred_count
][0] =
481 s
->cur_pic
->motion_val
[0][mot_index
- mot_stride
* mot_step
][0];
482 mv_predictor
[pred_count
][1] =
483 s
->cur_pic
->motion_val
[0][mot_index
- mot_stride
* mot_step
][1];
485 s
->cur_pic
->ref_index
[0][4 * (mb_xy
- s
->mb_stride
)];
488 if (mb_y
+ 1<mb_height
&& fixed
[mb_xy
+ mb_stride
]) {
489 mv_predictor
[pred_count
][0] =
490 s
->cur_pic
->motion_val
[0][mot_index
+ mot_stride
* mot_step
][0];
491 mv_predictor
[pred_count
][1] =
492 s
->cur_pic
->motion_val
[0][mot_index
+ mot_stride
* mot_step
][1];
494 s
->cur_pic
->ref_index
[0][4 * (mb_xy
+ s
->mb_stride
)];
500 if (pred_count
> 1) {
501 int sum_x
= 0, sum_y
= 0, sum_r
= 0;
502 int max_x
, max_y
, min_x
, min_y
, max_r
, min_r
;
504 for (j
= 0; j
< pred_count
; j
++) {
505 sum_x
+= mv_predictor
[j
][0];
506 sum_y
+= mv_predictor
[j
][1];
508 if (j
&& ref
[j
] != ref
[j
- 1])
509 goto skip_mean_and_median
;
513 mv_predictor
[pred_count
][0] = sum_x
/ j
;
514 mv_predictor
[pred_count
][1] = sum_y
/ j
;
515 ref
[pred_count
] = sum_r
/ j
;
518 if (pred_count
>= 3) {
519 min_y
= min_x
= min_r
= 99999;
520 max_y
= max_x
= max_r
= -99999;
522 min_x
= min_y
= max_x
= max_y
= min_r
= max_r
= 0;
524 for (j
= 0; j
< pred_count
; j
++) {
525 max_x
= FFMAX(max_x
, mv_predictor
[j
][0]);
526 max_y
= FFMAX(max_y
, mv_predictor
[j
][1]);
527 max_r
= FFMAX(max_r
, ref
[j
]);
528 min_x
= FFMIN(min_x
, mv_predictor
[j
][0]);
529 min_y
= FFMIN(min_y
, mv_predictor
[j
][1]);
530 min_r
= FFMIN(min_r
, ref
[j
]);
532 mv_predictor
[pred_count
+ 1][0] = sum_x
- max_x
- min_x
;
533 mv_predictor
[pred_count
+ 1][1] = sum_y
- max_y
- min_y
;
534 ref
[pred_count
+ 1] = sum_r
- max_r
- min_r
;
536 if (pred_count
== 4) {
537 mv_predictor
[pred_count
+ 1][0] /= 2;
538 mv_predictor
[pred_count
+ 1][1] /= 2;
539 ref
[pred_count
+ 1] /= 2;
544 skip_mean_and_median
:
549 if (s
->avctx
->codec_id
== AV_CODEC_ID_H264
) {
552 ff_thread_await_progress(&s
->last_pic
->tf
,
555 if (!s
->last_pic
->motion_val
[0] ||
556 !s
->last_pic
->ref_index
[0])
558 prev_x
= s
->last_pic
->motion_val
[0][mot_index
][0];
559 prev_y
= s
->last_pic
->motion_val
[0][mot_index
][1];
560 prev_ref
= s
->last_pic
->ref_index
[0][4 * mb_xy
];
562 prev_x
= s
->cur_pic
->motion_val
[0][mot_index
][0];
563 prev_y
= s
->cur_pic
->motion_val
[0][mot_index
][1];
564 prev_ref
= s
->cur_pic
->ref_index
[0][4 * mb_xy
];
568 mv_predictor
[pred_count
][0] = prev_x
;
569 mv_predictor
[pred_count
][1] = prev_y
;
570 ref
[pred_count
] = prev_ref
;
575 for (j
= 0; j
< pred_count
; j
++) {
576 int *linesize
= s
->cur_pic
->f
.linesize
;
578 uint8_t *src
= s
->cur_pic
->f
.data
[0] +
579 mb_x
* 16 + mb_y
* 16 * linesize
[0];
581 s
->cur_pic
->motion_val
[0][mot_index
][0] =
582 s
->mv
[0][0][0] = mv_predictor
[j
][0];
583 s
->cur_pic
->motion_val
[0][mot_index
][1] =
584 s
->mv
[0][0][1] = mv_predictor
[j
][1];
586 // predictor intra or otherwise not available
590 s
->decode_mb(s
->opaque
, ref
[j
], MV_DIR_FORWARD
,
591 MV_TYPE_16X16
, &s
->mv
, mb_x
, mb_y
, 0, 0);
593 if (mb_x
> 0 && fixed
[mb_xy
- 1]) {
595 for (k
= 0; k
< 16; k
++)
596 score
+= FFABS(src
[k
* linesize
[0] - 1] -
597 src
[k
* linesize
[0]]);
599 if (mb_x
+ 1 < mb_width
&& fixed
[mb_xy
+ 1]) {
601 for (k
= 0; k
< 16; k
++)
602 score
+= FFABS(src
[k
* linesize
[0] + 15] -
603 src
[k
* linesize
[0] + 16]);
605 if (mb_y
> 0 && fixed
[mb_xy
- mb_stride
]) {
607 for (k
= 0; k
< 16; k
++)
608 score
+= FFABS(src
[k
- linesize
[0]] - src
[k
]);
610 if (mb_y
+ 1 < mb_height
&& fixed
[mb_xy
+ mb_stride
]) {
612 for (k
= 0; k
< 16; k
++)
613 score
+= FFABS(src
[k
+ linesize
[0] * 15] -
614 src
[k
+ linesize
[0] * 16]);
617 if (score
<= best_score
) { // <= will favor the last MV
622 score_sum
+= best_score
;
623 s
->mv
[0][0][0] = mv_predictor
[best_pred
][0];
624 s
->mv
[0][0][1] = mv_predictor
[best_pred
][1];
626 for (i
= 0; i
< mot_step
; i
++)
627 for (j
= 0; j
< mot_step
; j
++) {
628 s
->cur_pic
->motion_val
[0][mot_index
+ i
+ j
* mot_stride
][0] = s
->mv
[0][0][0];
629 s
->cur_pic
->motion_val
[0][mot_index
+ i
+ j
* mot_stride
][1] = s
->mv
[0][0][1];
632 s
->decode_mb(s
->opaque
, ref
[best_pred
], MV_DIR_FORWARD
,
633 MV_TYPE_16X16
, &s
->mv
, mb_x
, mb_y
, 0, 0);
636 if (s
->mv
[0][0][0] != prev_x
|| s
->mv
[0][0][1] != prev_y
) {
637 fixed
[mb_xy
] = MV_CHANGED
;
640 fixed
[mb_xy
] = MV_UNCHANGED
;
648 for (i
= 0; i
< s
->mb_num
; i
++) {
649 int mb_xy
= s
->mb_index2xy
[i
];
651 fixed
[mb_xy
] = MV_FROZEN
;
656 static int is_intra_more_likely(ERContext
*s
)
658 int is_intra_likely
, i
, j
, undamaged_count
, skip_amount
, mb_x
, mb_y
;
660 if (!s
->last_pic
|| !s
->last_pic
->f
.data
[0])
661 return 1; // no previous frame available -> use spatial prediction
664 for (i
= 0; i
< s
->mb_num
; i
++) {
665 const int mb_xy
= s
->mb_index2xy
[i
];
666 const int error
= s
->error_status_table
[mb_xy
];
667 if (!((error
& ER_DC_ERROR
) && (error
& ER_MV_ERROR
)))
671 if (s
->avctx
->codec_id
== AV_CODEC_ID_H264
&& s
->ref_count
<= 0)
674 if (undamaged_count
< 5)
675 return 0; // almost all MBs damaged -> use temporal prediction
678 FF_DISABLE_DEPRECATION_WARNINGS
679 // prevent dsp.sad() check, that requires access to the image
680 if (CONFIG_MPEG_XVMC_DECODER
&&
681 s
->avctx
->xvmc_acceleration
&&
682 s
->cur_pic
->f
.pict_type
== AV_PICTURE_TYPE_I
)
684 FF_ENABLE_DEPRECATION_WARNINGS
685 #endif /* FF_API_XVMC */
687 skip_amount
= FFMAX(undamaged_count
/ 50, 1); // check only up to 50 MBs
691 for (mb_y
= 0; mb_y
< s
->mb_height
- 1; mb_y
++) {
692 for (mb_x
= 0; mb_x
< s
->mb_width
; mb_x
++) {
694 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
696 error
= s
->error_status_table
[mb_xy
];
697 if ((error
& ER_DC_ERROR
) && (error
& ER_MV_ERROR
))
698 continue; // skip damaged
701 // skip a few to speed things up
702 if ((j
% skip_amount
) != 0)
705 if (s
->cur_pic
->f
.pict_type
== AV_PICTURE_TYPE_I
) {
706 int *linesize
= s
->cur_pic
->f
.linesize
;
707 uint8_t *mb_ptr
= s
->cur_pic
->f
.data
[0] +
708 mb_x
* 16 + mb_y
* 16 * linesize
[0];
709 uint8_t *last_mb_ptr
= s
->last_pic
->f
.data
[0] +
710 mb_x
* 16 + mb_y
* 16 * linesize
[0];
712 if (s
->avctx
->codec_id
== AV_CODEC_ID_H264
) {
715 ff_thread_await_progress(&s
->last_pic
->tf
, mb_y
, 0);
717 is_intra_likely
+= s
->dsp
->sad
[0](NULL
, last_mb_ptr
, mb_ptr
,
719 is_intra_likely
-= s
->dsp
->sad
[0](NULL
, last_mb_ptr
,
720 last_mb_ptr
+ linesize
[0] * 16,
723 if (IS_INTRA(s
->cur_pic
->mb_type
[mb_xy
]))
730 return is_intra_likely
> 0;
733 void ff_er_frame_start(ERContext
*s
)
735 if (!s
->avctx
->error_concealment
)
738 memset(s
->error_status_table
, ER_MB_ERROR
| VP_START
| ER_MB_END
,
739 s
->mb_stride
* s
->mb_height
* sizeof(uint8_t));
740 s
->error_count
= 3 * s
->mb_num
;
741 s
->error_occurred
= 0;
746 * @param endx x component of the last macroblock, can be -1
747 * for the last of the previous line
748 * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is
749 * assumed that no earlier end or error of the same type occurred
751 void ff_er_add_slice(ERContext
*s
, int startx
, int starty
,
752 int endx
, int endy
, int status
)
754 const int start_i
= av_clip(startx
+ starty
* s
->mb_width
, 0, s
->mb_num
- 1);
755 const int end_i
= av_clip(endx
+ endy
* s
->mb_width
, 0, s
->mb_num
);
756 const int start_xy
= s
->mb_index2xy
[start_i
];
757 const int end_xy
= s
->mb_index2xy
[end_i
];
760 if (s
->avctx
->hwaccel
)
763 if (start_i
> end_i
|| start_xy
> end_xy
) {
764 av_log(s
->avctx
, AV_LOG_ERROR
,
765 "internal error, slice end before start\n");
769 if (!s
->avctx
->error_concealment
)
773 if (status
& (ER_AC_ERROR
| ER_AC_END
)) {
774 mask
&= ~(ER_AC_ERROR
| ER_AC_END
);
775 s
->error_count
-= end_i
- start_i
+ 1;
777 if (status
& (ER_DC_ERROR
| ER_DC_END
)) {
778 mask
&= ~(ER_DC_ERROR
| ER_DC_END
);
779 s
->error_count
-= end_i
- start_i
+ 1;
781 if (status
& (ER_MV_ERROR
| ER_MV_END
)) {
782 mask
&= ~(ER_MV_ERROR
| ER_MV_END
);
783 s
->error_count
-= end_i
- start_i
+ 1;
786 if (status
& ER_MB_ERROR
) {
787 s
->error_occurred
= 1;
788 s
->error_count
= INT_MAX
;
792 memset(&s
->error_status_table
[start_xy
], 0,
793 (end_xy
- start_xy
) * sizeof(uint8_t));
796 for (i
= start_xy
; i
< end_xy
; i
++)
797 s
->error_status_table
[i
] &= mask
;
800 if (end_i
== s
->mb_num
)
801 s
->error_count
= INT_MAX
;
803 s
->error_status_table
[end_xy
] &= mask
;
804 s
->error_status_table
[end_xy
] |= status
;
807 s
->error_status_table
[start_xy
] |= VP_START
;
809 if (start_xy
> 0 && s
->avctx
->thread_count
<= 1 &&
810 s
->avctx
->skip_top
* s
->mb_width
< start_i
) {
811 int prev_status
= s
->error_status_table
[s
->mb_index2xy
[start_i
- 1]];
813 prev_status
&= ~ VP_START
;
814 if (prev_status
!= (ER_MV_END
| ER_DC_END
| ER_AC_END
))
815 s
->error_count
= INT_MAX
;
819 void ff_er_frame_end(ERContext
*s
)
821 int *linesize
= s
->cur_pic
->f
.linesize
;
822 int i
, mb_x
, mb_y
, error
, error_type
, dc_error
, mv_error
, ac_error
;
824 int threshold_part
[4] = { 100, 100, 100 };
827 int size
= s
->b8_stride
* 2 * s
->mb_height
;
829 /* We do not support ER of field pictures yet,
830 * though it should not crash if enabled. */
831 if (!s
->avctx
->error_concealment
|| s
->error_count
== 0 ||
833 !s
->cur_pic
|| s
->cur_pic
->field_picture
||
834 s
->error_count
== 3 * s
->mb_width
*
835 (s
->avctx
->skip_top
+ s
->avctx
->skip_bottom
)) {
839 if (s
->cur_pic
->motion_val
[0] == NULL
) {
840 av_log(s
->avctx
, AV_LOG_ERROR
, "Warning MVs not available\n");
842 for (i
= 0; i
< 2; i
++) {
843 s
->cur_pic
->ref_index_buf
[i
] = av_buffer_allocz(s
->mb_stride
* s
->mb_height
* 4 * sizeof(uint8_t));
844 s
->cur_pic
->motion_val_buf
[i
] = av_buffer_allocz((size
+ 4) * 2 * sizeof(uint16_t));
845 if (!s
->cur_pic
->ref_index_buf
[i
] || !s
->cur_pic
->motion_val_buf
[i
])
847 s
->cur_pic
->ref_index
[i
] = s
->cur_pic
->ref_index_buf
[i
]->data
;
848 s
->cur_pic
->motion_val
[i
] = (int16_t (*)[2])s
->cur_pic
->motion_val_buf
[i
]->data
+ 4;
851 for (i
= 0; i
< 2; i
++) {
852 av_buffer_unref(&s
->cur_pic
->ref_index_buf
[i
]);
853 av_buffer_unref(&s
->cur_pic
->motion_val_buf
[i
]);
854 s
->cur_pic
->ref_index
[i
] = NULL
;
855 s
->cur_pic
->motion_val
[i
] = NULL
;
861 if (s
->avctx
->debug
& FF_DEBUG_ER
) {
862 for (mb_y
= 0; mb_y
< s
->mb_height
; mb_y
++) {
863 for (mb_x
= 0; mb_x
< s
->mb_width
; mb_x
++) {
864 int status
= s
->error_status_table
[mb_x
+ mb_y
* s
->mb_stride
];
866 av_log(s
->avctx
, AV_LOG_DEBUG
, "%2X ", status
);
868 av_log(s
->avctx
, AV_LOG_DEBUG
, "\n");
872 /* handle overlapping slices */
873 for (error_type
= 1; error_type
<= 3; error_type
++) {
876 for (i
= s
->mb_num
- 1; i
>= 0; i
--) {
877 const int mb_xy
= s
->mb_index2xy
[i
];
878 int error
= s
->error_status_table
[mb_xy
];
880 if (error
& (1 << error_type
))
882 if (error
& (8 << error_type
))
886 s
->error_status_table
[mb_xy
] |= 1 << error_type
;
888 if (error
& VP_START
)
893 /* handle slices with partitions of different length */
894 if (s
->partitioned_frame
) {
897 for (i
= s
->mb_num
- 1; i
>= 0; i
--) {
898 const int mb_xy
= s
->mb_index2xy
[i
];
899 int error
= s
->error_status_table
[mb_xy
];
901 if (error
& ER_AC_END
)
903 if ((error
& ER_MV_END
) ||
904 (error
& ER_DC_END
) ||
905 (error
& ER_AC_ERROR
))
909 s
->error_status_table
[mb_xy
]|= ER_AC_ERROR
;
911 if (error
& VP_START
)
916 /* handle missing slices */
917 if (s
->avctx
->err_recognition
& AV_EF_EXPLODE
) {
921 for (i
= s
->mb_num
- 2; i
>= s
->mb_width
+ 100; i
--) {
922 const int mb_xy
= s
->mb_index2xy
[i
];
923 int error1
= s
->error_status_table
[mb_xy
];
924 int error2
= s
->error_status_table
[s
->mb_index2xy
[i
+ 1]];
926 if (error1
& VP_START
)
929 if (error2
== (VP_START
| ER_MB_ERROR
| ER_MB_END
) &&
930 error1
!= (VP_START
| ER_MB_ERROR
| ER_MB_END
) &&
931 ((error1
& ER_AC_END
) || (error1
& ER_DC_END
) ||
932 (error1
& ER_MV_END
))) {
938 s
->error_status_table
[mb_xy
] |= ER_MB_ERROR
;
942 /* backward mark errors */
944 for (error_type
= 1; error_type
<= 3; error_type
++) {
945 for (i
= s
->mb_num
- 1; i
>= 0; i
--) {
946 const int mb_xy
= s
->mb_index2xy
[i
];
947 int error
= s
->error_status_table
[mb_xy
];
949 if (!s
->mbskip_table
[mb_xy
]) // FIXME partition specific
951 if (error
& (1 << error_type
))
954 if (s
->partitioned_frame
) {
955 if (distance
< threshold_part
[error_type
- 1])
956 s
->error_status_table
[mb_xy
] |= 1 << error_type
;
958 if (distance
< threshold
)
959 s
->error_status_table
[mb_xy
] |= 1 << error_type
;
962 if (error
& VP_START
)
967 /* forward mark errors */
969 for (i
= 0; i
< s
->mb_num
; i
++) {
970 const int mb_xy
= s
->mb_index2xy
[i
];
971 int old_error
= s
->error_status_table
[mb_xy
];
973 if (old_error
& VP_START
) {
974 error
= old_error
& ER_MB_ERROR
;
976 error
|= old_error
& ER_MB_ERROR
;
977 s
->error_status_table
[mb_xy
] |= error
;
981 /* handle not partitioned case */
982 if (!s
->partitioned_frame
) {
983 for (i
= 0; i
< s
->mb_num
; i
++) {
984 const int mb_xy
= s
->mb_index2xy
[i
];
985 error
= s
->error_status_table
[mb_xy
];
986 if (error
& ER_MB_ERROR
)
987 error
|= ER_MB_ERROR
;
988 s
->error_status_table
[mb_xy
] = error
;
992 dc_error
= ac_error
= mv_error
= 0;
993 for (i
= 0; i
< s
->mb_num
; i
++) {
994 const int mb_xy
= s
->mb_index2xy
[i
];
995 error
= s
->error_status_table
[mb_xy
];
996 if (error
& ER_DC_ERROR
)
998 if (error
& ER_AC_ERROR
)
1000 if (error
& ER_MV_ERROR
)
1003 av_log(s
->avctx
, AV_LOG_INFO
, "concealing %d DC, %d AC, %d MV errors\n",
1004 dc_error
, ac_error
, mv_error
);
1006 is_intra_likely
= is_intra_more_likely(s
);
1008 /* set unknown mb-type to most likely */
1009 for (i
= 0; i
< s
->mb_num
; i
++) {
1010 const int mb_xy
= s
->mb_index2xy
[i
];
1011 error
= s
->error_status_table
[mb_xy
];
1012 if (!((error
& ER_DC_ERROR
) && (error
& ER_MV_ERROR
)))
1015 if (is_intra_likely
)
1016 s
->cur_pic
->mb_type
[mb_xy
] = MB_TYPE_INTRA4x4
;
1018 s
->cur_pic
->mb_type
[mb_xy
] = MB_TYPE_16x16
| MB_TYPE_L0
;
1021 // change inter to intra blocks if no reference frames are available
1022 if (!(s
->last_pic
&& s
->last_pic
->f
.data
[0]) &&
1023 !(s
->next_pic
&& s
->next_pic
->f
.data
[0]))
1024 for (i
= 0; i
< s
->mb_num
; i
++) {
1025 const int mb_xy
= s
->mb_index2xy
[i
];
1026 if (!IS_INTRA(s
->cur_pic
->mb_type
[mb_xy
]))
1027 s
->cur_pic
->mb_type
[mb_xy
] = MB_TYPE_INTRA4x4
;
1030 /* handle inter blocks with damaged AC */
1031 for (mb_y
= 0; mb_y
< s
->mb_height
; mb_y
++) {
1032 for (mb_x
= 0; mb_x
< s
->mb_width
; mb_x
++) {
1033 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
1034 const int mb_type
= s
->cur_pic
->mb_type
[mb_xy
];
1035 const int dir
= !(s
->last_pic
&& s
->last_pic
->f
.data
[0]);
1036 const int mv_dir
= dir ? MV_DIR_BACKWARD
: MV_DIR_FORWARD
;
1039 error
= s
->error_status_table
[mb_xy
];
1041 if (IS_INTRA(mb_type
))
1043 if (error
& ER_MV_ERROR
)
1044 continue; // inter with damaged MV
1045 if (!(error
& ER_AC_ERROR
))
1046 continue; // undamaged inter
1048 if (IS_8X8(mb_type
)) {
1049 int mb_index
= mb_x
* 2 + mb_y
* 2 * s
->b8_stride
;
1051 mv_type
= MV_TYPE_8X8
;
1052 for (j
= 0; j
< 4; j
++) {
1053 s
->mv
[0][j
][0] = s
->cur_pic
->motion_val
[dir
][mb_index
+ (j
& 1) + (j
>> 1) * s
->b8_stride
][0];
1054 s
->mv
[0][j
][1] = s
->cur_pic
->motion_val
[dir
][mb_index
+ (j
& 1) + (j
>> 1) * s
->b8_stride
][1];
1057 mv_type
= MV_TYPE_16X16
;
1058 s
->mv
[0][0][0] = s
->cur_pic
->motion_val
[dir
][mb_x
* 2 + mb_y
* 2 * s
->b8_stride
][0];
1059 s
->mv
[0][0][1] = s
->cur_pic
->motion_val
[dir
][mb_x
* 2 + mb_y
* 2 * s
->b8_stride
][1];
1062 s
->decode_mb(s
->opaque
, 0 /* FIXME h264 partitioned slices need this set */,
1063 mv_dir
, mv_type
, &s
->mv
, mb_x
, mb_y
, 0, 0);
1068 if (s
->cur_pic
->f
.pict_type
== AV_PICTURE_TYPE_B
) {
1069 for (mb_y
= 0; mb_y
< s
->mb_height
; mb_y
++) {
1070 for (mb_x
= 0; mb_x
< s
->mb_width
; mb_x
++) {
1071 int xy
= mb_x
* 2 + mb_y
* 2 * s
->b8_stride
;
1072 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
1073 const int mb_type
= s
->cur_pic
->mb_type
[mb_xy
];
1074 int mv_dir
= MV_DIR_FORWARD
| MV_DIR_BACKWARD
;
1076 error
= s
->error_status_table
[mb_xy
];
1078 if (IS_INTRA(mb_type
))
1080 if (!(error
& ER_MV_ERROR
))
1081 continue; // inter with undamaged MV
1082 if (!(error
& ER_AC_ERROR
))
1083 continue; // undamaged inter
1085 if (!(s
->last_pic
&& s
->last_pic
->f
.data
[0]))
1086 mv_dir
&= ~MV_DIR_FORWARD
;
1087 if (!(s
->next_pic
&& s
->next_pic
->f
.data
[0]))
1088 mv_dir
&= ~MV_DIR_BACKWARD
;
1091 int time_pp
= s
->pp_time
;
1092 int time_pb
= s
->pb_time
;
1094 ff_thread_await_progress(&s
->next_pic
->tf
, mb_y
, 0);
1096 s
->mv
[0][0][0] = s
->next_pic
->motion_val
[0][xy
][0] * time_pb
/ time_pp
;
1097 s
->mv
[0][0][1] = s
->next_pic
->motion_val
[0][xy
][1] * time_pb
/ time_pp
;
1098 s
->mv
[1][0][0] = s
->next_pic
->motion_val
[0][xy
][0] * (time_pb
- time_pp
) / time_pp
;
1099 s
->mv
[1][0][1] = s
->next_pic
->motion_val
[0][xy
][1] * (time_pb
- time_pp
) / time_pp
;
1107 s
->decode_mb(s
->opaque
, 0, mv_dir
, MV_TYPE_16X16
, &s
->mv
,
1115 FF_DISABLE_DEPRECATION_WARNINGS
1116 /* the filters below are not XvMC compatible, skip them */
1117 if (CONFIG_MPEG_XVMC_DECODER
&& s
->avctx
->xvmc_acceleration
)
1119 FF_ENABLE_DEPRECATION_WARNINGS
1120 #endif /* FF_API_XVMC */
1121 /* fill DC for inter blocks */
1122 for (mb_y
= 0; mb_y
< s
->mb_height
; mb_y
++) {
1123 for (mb_x
= 0; mb_x
< s
->mb_width
; mb_x
++) {
1124 int dc
, dcu
, dcv
, y
, n
;
1126 uint8_t *dest_y
, *dest_cb
, *dest_cr
;
1127 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
1128 const int mb_type
= s
->cur_pic
->mb_type
[mb_xy
];
1130 error
= s
->error_status_table
[mb_xy
];
1132 if (IS_INTRA(mb_type
) && s
->partitioned_frame
)
1134 // if (error & ER_MV_ERROR)
1135 // continue; // inter data damaged FIXME is this good?
1137 dest_y
= s
->cur_pic
->f
.data
[0] + mb_x
* 16 + mb_y
* 16 * linesize
[0];
1138 dest_cb
= s
->cur_pic
->f
.data
[1] + mb_x
* 8 + mb_y
* 8 * linesize
[1];
1139 dest_cr
= s
->cur_pic
->f
.data
[2] + mb_x
* 8 + mb_y
* 8 * linesize
[2];
1141 dc_ptr
= &s
->dc_val
[0][mb_x
* 2 + mb_y
* 2 * s
->b8_stride
];
1142 for (n
= 0; n
< 4; n
++) {
1144 for (y
= 0; y
< 8; y
++) {
1146 for (x
= 0; x
< 8; x
++)
1147 dc
+= dest_y
[x
+ (n
& 1) * 8 +
1148 (y
+ (n
>> 1) * 8) * linesize
[0]];
1150 dc_ptr
[(n
& 1) + (n
>> 1) * s
->b8_stride
] = (dc
+ 4) >> 3;
1154 for (y
= 0; y
< 8; y
++) {
1156 for (x
= 0; x
< 8; x
++) {
1157 dcu
+= dest_cb
[x
+ y
* linesize
[1]];
1158 dcv
+= dest_cr
[x
+ y
* linesize
[2]];
1161 s
->dc_val
[1][mb_x
+ mb_y
* s
->mb_stride
] = (dcu
+ 4) >> 3;
1162 s
->dc_val
[2][mb_x
+ mb_y
* s
->mb_stride
] = (dcv
+ 4) >> 3;
1166 /* guess DC for damaged blocks */
1167 guess_dc(s
, s
->dc_val
[0], s
->mb_width
* 2, s
->mb_height
* 2, s
->b8_stride
, 1);
1168 guess_dc(s
, s
->dc_val
[1], s
->mb_width
, s
->mb_height
, s
->mb_stride
, 0);
1169 guess_dc(s
, s
->dc_val
[2], s
->mb_width
, s
->mb_height
, s
->mb_stride
, 0);
1171 /* filter luma DC */
1172 filter181(s
->dc_val
[0], s
->mb_width
* 2, s
->mb_height
* 2, s
->b8_stride
);
1174 /* render DC only intra */
1175 for (mb_y
= 0; mb_y
< s
->mb_height
; mb_y
++) {
1176 for (mb_x
= 0; mb_x
< s
->mb_width
; mb_x
++) {
1177 uint8_t *dest_y
, *dest_cb
, *dest_cr
;
1178 const int mb_xy
= mb_x
+ mb_y
* s
->mb_stride
;
1179 const int mb_type
= s
->cur_pic
->mb_type
[mb_xy
];
1181 error
= s
->error_status_table
[mb_xy
];
1183 if (IS_INTER(mb_type
))
1185 if (!(error
& ER_AC_ERROR
))
1186 continue; // undamaged
1188 dest_y
= s
->cur_pic
->f
.data
[0] + mb_x
* 16 + mb_y
* 16 * linesize
[0];
1189 dest_cb
= s
->cur_pic
->f
.data
[1] + mb_x
* 8 + mb_y
* 8 * linesize
[1];
1190 dest_cr
= s
->cur_pic
->f
.data
[2] + mb_x
* 8 + mb_y
* 8 * linesize
[2];
1192 put_dc(s
, dest_y
, dest_cb
, dest_cr
, mb_x
, mb_y
);
1196 if (s
->avctx
->error_concealment
& FF_EC_DEBLOCK
) {
1197 /* filter horizontal block boundaries */
1198 h_block_filter(s
, s
->cur_pic
->f
.data
[0], s
->mb_width
* 2,
1199 s
->mb_height
* 2, linesize
[0], 1);
1200 h_block_filter(s
, s
->cur_pic
->f
.data
[1], s
->mb_width
,
1201 s
->mb_height
, linesize
[1], 0);
1202 h_block_filter(s
, s
->cur_pic
->f
.data
[2], s
->mb_width
,
1203 s
->mb_height
, linesize
[2], 0);
1205 /* filter vertical block boundaries */
1206 v_block_filter(s
, s
->cur_pic
->f
.data
[0], s
->mb_width
* 2,
1207 s
->mb_height
* 2, linesize
[0], 1);
1208 v_block_filter(s
, s
->cur_pic
->f
.data
[1], s
->mb_width
,
1209 s
->mb_height
, linesize
[1], 0);
1210 v_block_filter(s
, s
->cur_pic
->f
.data
[2], s
->mb_width
,
1211 s
->mb_height
, linesize
[2], 0);
1215 /* clean a few tables */
1216 for (i
= 0; i
< s
->mb_num
; i
++) {
1217 const int mb_xy
= s
->mb_index2xy
[i
];
1218 int error
= s
->error_status_table
[mb_xy
];
1220 if (s
->cur_pic
->f
.pict_type
!= AV_PICTURE_TYPE_B
&&
1221 (error
& (ER_DC_ERROR
| ER_MV_ERROR
| ER_AC_ERROR
))) {
1222 s
->mbskip_table
[mb_xy
] = 0;
1224 s
->mbintra_table
[mb_xy
] = 1;