1 /*
2 * Error resilience / concealment
3 *
4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * Error resilience / concealment.
26 */
27
29
40
41 /**
42 * @param stride the number of MVs to get to the next row
43 * @param mv_step the number of MVs per row or column in a macroblock
44 */
46 {
49 *mv_step = 4;
51 } else {
52 *mv_step = 2;
54 }
55 }
56
57 /**
58 * Replace the current MB with a flat dc-only version.
59 */
61 uint8_t *dest_cr, int mb_x, int mb_y)
62 {
63 int *linesize =
s->cur_pic.f->linesize;
64 int dc, dcu, dcv, y,
i;
65 for (
i = 0;
i < 4;
i++) {
66 dc =
s->dc_val[0][mb_x * 2 + (
i & 1) + (mb_y * 2 + (
i >> 1)) *
s->b8_stride];
71 for (y = 0; y < 8; y++) {
72 int x;
73 for (x = 0; x < 8; x++)
74 dest_y[x + (
i & 1) * 8 + (y + (
i >> 1) * 8) * linesize[0]] =
dc / 8;
75 }
76 }
77 dcu =
s->dc_val[1][mb_x + mb_y *
s->mb_stride];
78 dcv =
s->dc_val[2][mb_x + mb_y *
s->mb_stride];
79 if (dcu < 0)
80 dcu = 0;
81 else if (dcu > 2040)
82 dcu = 2040;
83 if (dcv < 0)
84 dcv = 0;
85 else if (dcv > 2040)
86 dcv = 2040;
87
88 if (dest_cr)
89 for (y = 0; y < 8; y++) {
90 int x;
91 for (x = 0; x < 8; x++) {
92 dest_cb[x + y * linesize[1]] = dcu / 8;
93 dest_cr[x + y * linesize[2]] = dcv / 8;
94 }
95 }
96 }
97
99 {
100 int x, y;
101
102 /* horizontal filter */
103 for (y = 1; y <
height - 1; y++) {
105
106 for (x = 1; x <
width - 1; x++) {
111 dc = (
av_clip(
dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16;
114 }
115 }
116
117 /* vertical filter */
118 for (x = 1; x <
width - 1; x++) {
119 int prev_dc =
data[x];
120
121 for (y = 1; y <
height - 1; y++) {
123
127 dc = (
av_clip(
dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16;
130 }
131 }
132 }
133
134 /**
135 * guess the dc of blocks which do not have an undamaged dc
136 * @param w width in 8 pixel blocks
137 * @param h height in 8 pixel blocks
138 */
140 int h, ptrdiff_t
stride,
int is_luma)
141 {
142 int b_x, b_y;
145
146 if(!col || !dist) {
149 }
150
151 for(b_y=0; b_y<
h; b_y++){
154 for(b_x=0; b_x<
w; b_x++){
155 int mb_index_j= (b_x>>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]);
161 }
164 }
167 for(b_x=
w-1; b_x>=0; b_x--){
168 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*
s->mb_stride;
169 int error_j=
s->error_status_table[mb_index_j];
170 int intra_j =
IS_INTRA(
s->cur_pic.mb_type[mb_index_j]);
174 }
177 }
178 }
179 for(b_x=0; b_x<
w; b_x++){
182 for(b_y=0; b_y<
h; b_y++){
183 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*
s->mb_stride;
184 int error_j=
s->error_status_table[mb_index_j];
185 int intra_j =
IS_INTRA(
s->cur_pic.mb_type[mb_index_j]);
189 }
192 }
195 for(b_y=
h-1; b_y>=0; b_y--){
196 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*
s->mb_stride;
197 int error_j=
s->error_status_table[mb_index_j];
198 int intra_j =
IS_INTRA(
s->cur_pic.mb_type[mb_index_j]);
202 }
205 }
206 }
207
208 for (b_y = 0; b_y <
h; b_y++) {
209 for (b_x = 0; b_x <
w; b_x++) {
210 int mb_index,
error, j;
212 mb_index = (b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride;
213 error =
s->error_status_table[mb_index];
214
215 if (
IS_INTER(
s->cur_pic.mb_type[mb_index]))
216 continue; // inter
218 continue; // dc-ok
219
220 weight_sum = 0;
221 guess = 0;
222 for (j = 0; j < 4; j++) {
226 }
227 guess = (guess + weight_sum / 2) / weight_sum;
229 }
230 }
231
235 }
236
237 /**
238 * simple horizontal deblocking filter used for error resilience
239 * @param w width in 8 pixel blocks
240 * @param h height in 8 pixel blocks
241 */
243 int h, ptrdiff_t
stride,
int is_luma)
244 {
245 int b_x, b_y;
246 ptrdiff_t mvx_stride, mvy_stride;
249 mvx_stride >>= is_luma;
250 mvy_stride *= mvx_stride;
251
252 for (b_y = 0; b_y <
h; b_y++) {
253 for (b_x = 0; b_x <
w - 1; b_x++) {
254 int y;
255 int left_status =
s->error_status_table[( b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride];
256 int right_status =
s->error_status_table[((b_x + 1) >> is_luma) + (b_y >> is_luma) *
s->mb_stride];
257 int left_intra =
IS_INTRA(
s->cur_pic.mb_type[( b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride]);
258 int right_intra =
IS_INTRA(
s->cur_pic.mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) *
s->mb_stride]);
262 int16_t *left_mv =
s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x];
263 int16_t *right_mv =
s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)];
264 if (!(left_damage || right_damage))
265 continue; // both undamaged
266 if ((!left_intra) && (!right_intra) &&
267 FFABS(left_mv[0] - right_mv[0]) +
268 FFABS(left_mv[1] + right_mv[1]) < 2)
269 continue;
270
271 for (y = 0; y < 8; y++) {
273
277
281 d = -d;
282
283 if (d == 0)
284 continue;
285
286 if (!(left_damage && right_damage))
287 d = d * 16 / 9;
288
289 if (left_damage) {
294 }
295 if (right_damage) {
300 }
301 }
302 }
303 }
304 }
305
306 /**
307 * simple vertical deblocking filter used for error resilience
308 * @param w width in 8 pixel blocks
309 * @param h height in 8 pixel blocks
310 */
312 ptrdiff_t
stride,
int is_luma)
313 {
314 int b_x, b_y;
315 ptrdiff_t mvx_stride, mvy_stride;
318 mvx_stride >>= is_luma;
319 mvy_stride *= mvx_stride;
320
321 for (b_y = 0; b_y <
h - 1; b_y++) {
322 for (b_x = 0; b_x <
w; b_x++) {
323 int x;
324 int top_status =
s->error_status_table[(b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride];
325 int bottom_status =
s->error_status_table[(b_x >> is_luma) + ((b_y + 1) >> is_luma) *
s->mb_stride];
326 int top_intra =
IS_INTRA(
s->cur_pic.mb_type[(b_x >> is_luma) + ( b_y >> is_luma) *
s->mb_stride]);
327 int bottom_intra =
IS_INTRA(
s->cur_pic.mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) *
s->mb_stride]);
331
332 int16_t *top_mv =
s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x];
333 int16_t *bottom_mv =
s->cur_pic.motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x];
334
335 if (!(top_damage || bottom_damage))
336 continue; // both undamaged
337
338 if ((!top_intra) && (!bottom_intra) &&
339 FFABS(top_mv[0] - bottom_mv[0]) +
340 FFABS(top_mv[1] + bottom_mv[1]) < 2)
341 continue;
342
343 for (x = 0; x < 8; x++) {
345
349
353 d = -d;
354
355 if (d == 0)
356 continue;
357
358 if (!(top_damage && bottom_damage))
359 d = d * 16 / 9;
360
361 if (top_damage) {
366 }
367 if (bottom_damage) {
372 }
373 }
374 }
375 }
376 }
377
380 #define MV_UNCHANGED 2
383 {
385 return;
387 blocklist[ *blocklist_length ][0] = mb_x;
388 blocklist[(*blocklist_length)++][1] = mb_y;
389 }
390
392 {
393 int (*blocklist)[2], (*next_blocklist)[2];
395 const ptrdiff_t mb_stride =
s->mb_stride;
396 const int mb_width =
s->mb_width;
397 int mb_height =
s->mb_height;
399 int mb_x, mb_y;
400 ptrdiff_t mot_step, mot_stride;
401 int blocklist_length, next_blocklist_length;
402
403 if (
s->last_pic.f &&
s->last_pic.f->data[0])
404 mb_height =
FFMIN(mb_height, (
s->last_pic.f->height+15)>>4);
405 if (
s->next_pic.f &&
s->next_pic.f->data[0])
406 mb_height =
FFMIN(mb_height, (
s->next_pic.f->height+15)>>4);
407
408 blocklist = (int (*)[2])
s->er_temp_buffer;
409 next_blocklist = blocklist +
s->mb_stride *
s->mb_height;
410 fixed = (uint8_t *)(next_blocklist +
s->mb_stride *
s->mb_height);
411
413
414 num_avail = 0;
415 if (
s->last_pic.motion_val[0]) {
418 else
420 }
421 for (
i = 0;
i < mb_width * mb_height;
i++) {
422 const int mb_xy =
s->mb_index2xy[
i];
424 int error =
s->error_status_table[mb_xy];
425
430
433 num_avail++;
434 else if(
s->last_pic.f->data[0] &&
s->last_pic.motion_val[0]){
435 const int mb_y= mb_xy /
s->mb_stride;
436 const int mb_x= mb_xy %
s->mb_stride;
437 const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
438 s->cur_pic.motion_val[0][mot_index][0]=
s->last_pic.motion_val[0][mot_index][0];
439 s->cur_pic.motion_val[0][mot_index][1]=
s->last_pic.motion_val[0][mot_index][1];
440 s->cur_pic.ref_index[0][4*mb_xy] =
s->last_pic.ref_index[0][4*mb_xy];
441 }
442 }
443
445 num_avail <=
FFMAX(mb_width, mb_height) / 2) {
446 for (mb_y = 0; mb_y < mb_height; mb_y++) {
447 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
448 const int mb_xy = mb_x + mb_y *
s->mb_stride;
450
452 continue;
454 continue;
455
459 mb_x, mb_y, 0, 0);
460 }
461 }
462 return;
463 }
464
465 blocklist_length = 0;
466 for (mb_y = 0; mb_y < mb_height; mb_y++) {
467 for (mb_x = 0; mb_x < mb_width; mb_x++) {
468 const int mb_xy = mb_x + mb_y * mb_stride;
470 if (mb_x)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x - 1, mb_y, mb_xy - 1);
471 if (mb_y)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x, mb_y - 1, mb_xy - mb_stride);
472 if (mb_x+1 < mb_width)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x + 1, mb_y, mb_xy + 1);
473 if (mb_y+1 < mb_height)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x, mb_y + 1, mb_xy + mb_stride);
474 }
475 }
476 }
477
478 for (;;) {
479 int changed, pass, none_left;
480 int blocklist_index;
481
482 none_left = 1;
483 changed = 1;
484 for (pass = 0; (changed || pass < 2) && pass < 10; pass++) {
485 changed = 0;
486 for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) {
487 const int mb_x = blocklist[blocklist_index][0];
488 const int mb_y = blocklist[blocklist_index][1];
489 const int mb_xy = mb_x + mb_y * mb_stride;
490 int mv_predictor[8][2];
492 int pred_count;
493 int j;
494 int best_score;
495 int best_pred;
496 int mot_index;
497 int prev_x, prev_y, prev_ref;
498
499 if ((mb_x ^ mb_y ^ pass) & 1)
500 continue;
502
503
506
507 j = 0;
508 if (mb_x > 0)
509 j |=
fixed[mb_xy - 1];
510 if (mb_x + 1 < mb_width)
511 j |=
fixed[mb_xy + 1];
512 if (mb_y > 0)
513 j |=
fixed[mb_xy - mb_stride];
514 if (mb_y + 1 < mb_height)
515 j |=
fixed[mb_xy + mb_stride];
516
518
520 continue;
521
522 none_left = 0;
523 pred_count = 0;
524 mot_index = (mb_x + mb_y * mot_stride) * mot_step;
525
526 if (mb_x > 0 &&
fixed[mb_xy - 1] > 1) {
527 mv_predictor[pred_count][0] =
528 s->cur_pic.motion_val[0][mot_index - mot_step][0];
529 mv_predictor[pred_count][1] =
530 s->cur_pic.motion_val[0][mot_index - mot_step][1];
532 s->cur_pic.ref_index[0][4 * (mb_xy - 1)];
533 pred_count++;
534 }
535 if (mb_x + 1 < mb_width &&
fixed[mb_xy + 1] > 1) {
536 mv_predictor[pred_count][0] =
537 s->cur_pic.motion_val[0][mot_index + mot_step][0];
538 mv_predictor[pred_count][1] =
539 s->cur_pic.motion_val[0][mot_index + mot_step][1];
541 s->cur_pic.ref_index[0][4 * (mb_xy + 1)];
542 pred_count++;
543 }
544 if (mb_y > 0 &&
fixed[mb_xy - mb_stride] > 1) {
545 mv_predictor[pred_count][0] =
546 s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][0];
547 mv_predictor[pred_count][1] =
548 s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][1];
550 s->cur_pic.ref_index[0][4 * (mb_xy -
s->mb_stride)];
551 pred_count++;
552 }
553 if (mb_y + 1<mb_height &&
fixed[mb_xy + mb_stride] > 1) {
554 mv_predictor[pred_count][0] =
555 s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][0];
556 mv_predictor[pred_count][1] =
557 s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][1];
559 s->cur_pic.ref_index[0][4 * (mb_xy +
s->mb_stride)];
560 pred_count++;
561 }
562 if (pred_count == 0)
563 continue;
564
565 if (pred_count > 1) {
566 int sum_x = 0, sum_y = 0, sum_r = 0;
567 int max_x, max_y, min_x, min_y, max_r, min_r;
568
569 for (j = 0; j < pred_count; j++) {
570 sum_x += mv_predictor[j][0];
571 sum_y += mv_predictor[j][1];
573 if (j &&
ref[j] !=
ref[j - 1])
574 goto skip_mean_and_median;
575 }
576
577 /* mean */
578 mv_predictor[pred_count][0] = sum_x / j;
579 mv_predictor[pred_count][1] = sum_y / j;
580 ref[pred_count] = sum_r / j;
581
582 /* median */
583 if (pred_count >= 3) {
584 min_y = min_x = min_r = 99999;
585 max_y = max_x = max_r = -99999;
586 } else {
587 min_x = min_y = max_x = max_y = min_r = max_r = 0;
588 }
589 for (j = 0; j < pred_count; j++) {
590 max_x =
FFMAX(max_x, mv_predictor[j][0]);
591 max_y =
FFMAX(max_y, mv_predictor[j][1]);
593 min_x =
FFMIN(min_x, mv_predictor[j][0]);
594 min_y =
FFMIN(min_y, mv_predictor[j][1]);
596 }
597 mv_predictor[pred_count + 1][0] = sum_x - max_x - min_x;
598 mv_predictor[pred_count + 1][1] = sum_y - max_y - min_y;
599 ref[pred_count + 1] = sum_r - max_r - min_r;
600
601 if (pred_count == 4) {
602 mv_predictor[pred_count + 1][0] /= 2;
603 mv_predictor[pred_count + 1][1] /= 2;
604 ref[pred_count + 1] /= 2;
605 }
606 pred_count += 2;
607 }
608
609 skip_mean_and_median:
610 /* zero MV */
611 mv_predictor[pred_count][0] =
612 mv_predictor[pred_count][1] =
614 pred_count++;
615
616 prev_x =
s->cur_pic.motion_val[0][mot_index][0];
617 prev_y =
s->cur_pic.motion_val[0][mot_index][1];
618 prev_ref =
s->cur_pic.ref_index[0][4 * mb_xy];
619
620 /* last MV */
621 mv_predictor[pred_count][0] = prev_x;
622 mv_predictor[pred_count][1] = prev_y;
623 ref[pred_count] = prev_ref;
624 pred_count++;
625
626 best_pred = 0;
627 best_score = 256 * 256 * 256 * 64;
628 for (j = 0; j < pred_count; j++) {
629 int *linesize =
s->cur_pic.f->linesize;
630 int score = 0;
631 uint8_t *
src =
s->cur_pic.f->data[0] +
632 mb_x * 16 + mb_y * 16 * linesize[0];
633
634 s->cur_pic.motion_val[0][mot_index][0] =
635 s->mv[0][0][0] = mv_predictor[j][0];
636 s->cur_pic.motion_val[0][mot_index][1] =
637 s->mv[0][0][1] = mv_predictor[j][1];
638
639 // predictor intra or otherwise not available
641 continue;
642
645
646 if (mb_x > 0 &&
fixed[mb_xy - 1] > 1) {
647 int k;
648 for (k = 0; k < 16; k++)
649 score +=
FFABS(
src[k * linesize[0] - 1] -
650 src[k * linesize[0]]);
651 }
652 if (mb_x + 1 < mb_width &&
fixed[mb_xy + 1] > 1) {
653 int k;
654 for (k = 0; k < 16; k++)
655 score +=
FFABS(
src[k * linesize[0] + 15] -
656 src[k * linesize[0] + 16]);
657 }
658 if (mb_y > 0 &&
fixed[mb_xy - mb_stride] > 1) {
659 int k;
660 for (k = 0; k < 16; k++)
662 }
663 if (mb_y + 1 < mb_height &&
fixed[mb_xy + mb_stride] > 1) {
664 int k;
665 for (k = 0; k < 16; k++)
666 score +=
FFABS(
src[k + linesize[0] * 15] -
667 src[k + linesize[0] * 16]);
668 }
669
670 if (score <= best_score) { // <= will favor the last MV
671 best_score = score;
672 best_pred = j;
673 }
674 }
675 s->mv[0][0][0] = mv_predictor[best_pred][0];
676 s->mv[0][0][1] = mv_predictor[best_pred][1];
677
678 for (
i = 0;
i < mot_step;
i++)
679 for (j = 0; j < mot_step; j++) {
680 s->cur_pic.motion_val[0][mot_index +
i + j * mot_stride][0] =
s->mv[0][0][0];
681 s->cur_pic.motion_val[0][mot_index +
i + j * mot_stride][1] =
s->mv[0][0][1];
682 }
683
686
687
688 if (
s->mv[0][0][0] != prev_x ||
s->mv[0][0][1] != prev_y) {
690 changed++;
691 } else
693 }
694 }
695
696 if (none_left)
697 return;
698
699 next_blocklist_length = 0;
700
701 for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) {
702 const int mb_x = blocklist[blocklist_index][0];
703 const int mb_y = blocklist[blocklist_index][1];
704 const int mb_xy = mb_x + mb_y * mb_stride;
705
708 if (mb_x > 0)
709 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x - 1, mb_y, mb_xy - 1);
710 if (mb_y > 0)
711 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x, mb_y - 1, mb_xy - mb_stride);
712 if (mb_x + 1 < mb_width)
713 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x + 1, mb_y, mb_xy + 1);
714 if (mb_y + 1 < mb_height)
715 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x, mb_y + 1, mb_xy + mb_stride);
716 }
717 }
718 av_assert0(next_blocklist_length <= mb_height * mb_width);
719 FFSWAP(
int , blocklist_length, next_blocklist_length);
720 FFSWAP(
void*, blocklist, next_blocklist);
721 }
722 }
723
725 {
726 int is_intra_likely,
i, j, undamaged_count, skip_amount, mb_x, mb_y;
727
728 if (!
s->last_pic.f || !
s->last_pic.f->data[0])
729 return 1; // no previous frame available -> use spatial prediction
730
732 return 0;
733
734 undamaged_count = 0;
735 for (
i = 0;
i <
s->mb_num;
i++) {
736 const int mb_xy =
s->mb_index2xy[
i];
737 const int error =
s->error_status_table[mb_xy];
739 undamaged_count++;
740 }
741
742 if (undamaged_count < 5)
743 return 0; // almost all MBs damaged -> use temporal prediction
744
745 skip_amount =
FFMAX(undamaged_count / 50, 1);
// check only up to 50 MBs
746 is_intra_likely = 0;
747
748 j = 0;
749 for (mb_y = 0; mb_y <
s->mb_height - 1; mb_y++) {
750 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
752 const int mb_xy = mb_x + mb_y *
s->mb_stride;
753
754 error =
s->error_status_table[mb_xy];
756 continue; // skip damaged
757
758 j++;
759 // skip a few to speed things up
760 if ((j % skip_amount) != 0)
761 continue;
762
764 int *linesize =
s->cur_pic.f->linesize;
765 uint8_t *mb_ptr =
s->cur_pic.f->data[0] +
766 mb_x * 16 + mb_y * 16 * linesize[0];
767 uint8_t *last_mb_ptr =
s->last_pic.f->data[0] +
768 mb_x * 16 + mb_y * 16 * linesize[0];
769
771 // FIXME
772 } else {
774 }
775 is_intra_likely +=
s->sad(
NULL, last_mb_ptr, mb_ptr,
776 linesize[0], 16);
777 // FIXME need await_progress() here
778 is_intra_likely -=
s->sad(
NULL, last_mb_ptr,
779 last_mb_ptr + linesize[0] * 16,
780 linesize[0], 16);
781 } else {
783 is_intra_likely++;
784 else
785 is_intra_likely--;
786 }
787 }
788 }
789 // av_log(NULL, AV_LOG_ERROR, "is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
790 return is_intra_likely > 0;
791 }
792
794 {
795 if (!
s->avctx->error_concealment)
796 return;
797
798 if (!
s->mecc_inited) {
801 s->sad = mecc.
sad[0];
803 }
804
806 s->mb_stride *
s->mb_height *
sizeof(uint8_t));
808 s->error_occurred = 0;
809 }
810
812 {
813 if (
s->avctx->hwaccel ||
815 s->cur_pic.field_picture
816 )
817 return 0;
818 return 1;
819 }
820
821 /**
822 * Add a slice.
823 * @param endx x component of the last macroblock, can be -1
824 * for the last of the previous line
825 * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is
826 * assumed that no earlier end or error of the same type occurred
827 */
829 int endx,
int endy,
int status)
830 {
831 const int start_i =
av_clip(startx + starty *
s->mb_width, 0,
s->mb_num - 1);
832 const int end_i =
av_clip(endx + endy *
s->mb_width, 0,
s->mb_num);
833 const int start_xy =
s->mb_index2xy[start_i];
834 const int end_xy =
s->mb_index2xy[end_i];
836
837 if (
s->avctx->hwaccel)
838 return;
839
840 if (start_i > end_i || start_xy > end_xy) {
842 "internal error, slice end before start\n");
843 return;
844 }
845
846 if (!
s->avctx->error_concealment)
847 return;
848
853 }
857 }
861 }
862
864 s->error_occurred = 1;
866 }
867
869 memset(&
s->error_status_table[start_xy], 0,
870 (end_xy - start_xy) * sizeof(uint8_t));
871 } else {
873 for (
i = start_xy;
i < end_xy;
i++)
874 s->error_status_table[
i] &=
mask;
875 }
876
877 if (end_i ==
s->mb_num)
879 else {
880 s->error_status_table[end_xy] &=
mask;
881 s->error_status_table[end_xy] |=
status;
882 }
883
884 s->error_status_table[start_xy] |=
VP_START;
885
888 int prev_status =
s->error_status_table[
s->mb_index2xy[start_i - 1]];
889
892 s->error_occurred = 1;
894 }
895 }
896 }
897
899 {
900 int *linesize =
NULL;
901 int i, mb_x, mb_y,
error, error_type, dc_error, mv_error, ac_error;
903 int threshold_part[4] = { 100, 100, 100 };
904 int threshold = 50;
905 int is_intra_likely;
906 int size =
s->b8_stride * 2 *
s->mb_height;
907 int guessed_mb_type;
908
909 /* We do not support ER of field pictures yet,
910 * though it should not crash if enabled. */
911 if (!
s->avctx->error_concealment || !
atomic_load(&
s->error_count) ||
915 (
s->avctx->skip_top +
s->avctx->skip_bottom)) {
916 return;
917 }
918 linesize =
s->cur_pic.f->linesize;
919
921 && (
FFALIGN(
s->avctx->height, 16)&16)
922 &&
atomic_load(&
s->error_count) == 3 *
s->mb_width * (
s->avctx->skip_top +
s->avctx->skip_bottom + 1)) {
923 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
924 int status =
s->error_status_table[mb_x + (
s->mb_height - 1) *
s->mb_stride];
926 break;
927 }
928
929 if (mb_x ==
s->mb_width) {
931 return;
932 }
933 }
934
936 if (
s->last_pic.f->width !=
s->cur_pic.f->width ||
937 s->last_pic.f->height !=
s->cur_pic.f->height ||
938 s->last_pic.f->format !=
s->cur_pic.f->format) {
940 memset(&
s->last_pic, 0,
sizeof(
s->last_pic));
941 }
942 }
944 if (
s->next_pic.f->width !=
s->cur_pic.f->width ||
945 s->next_pic.f->height !=
s->cur_pic.f->height ||
946 s->next_pic.f->format !=
s->cur_pic.f->format) {
948 memset(&
s->next_pic, 0,
sizeof(
s->next_pic));
949 }
950 }
951
952 if (!
s->cur_pic.motion_val[0] || !
s->cur_pic.ref_index[0]) {
954
955 for (
i = 0;
i < 2;
i++) {
956 s->ref_index[
i] =
av_calloc(
s->mb_stride *
s->mb_height, 4 *
sizeof(uint8_t));
958 if (!
s->ref_index[
i] || !
s->motion_val_base[
i])
960 s->cur_pic.ref_index[
i] =
s->ref_index[
i];
961 s->cur_pic.motion_val[
i] =
s->motion_val_base[
i] + 4;
962 }
963 }
964
966 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
967 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
968 int status =
s->error_status_table[mb_x + mb_y *
s->mb_stride];
969
971 }
973 }
974 }
975
976 #if 1
977 /* handle overlapping slices */
978 for (error_type = 1; error_type <= 3; error_type++) {
979 int end_ok = 0;
980
981 for (
i =
s->mb_num - 1;
i >= 0;
i--) {
982 const int mb_xy =
s->mb_index2xy[
i];
983 int error =
s->error_status_table[mb_xy];
984
985 if (
error & (1 << error_type))
986 end_ok = 1;
987 if (
error & (8 << error_type))
988 end_ok = 1;
989
990 if (!end_ok)
991 s->error_status_table[mb_xy] |= 1 << error_type;
992
994 end_ok = 0;
995 }
996 }
997 #endif
998 #if 1
999 /* handle slices with partitions of different length */
1000 if (
s->partitioned_frame) {
1001 int end_ok = 0;
1002
1003 for (
i =
s->mb_num - 1;
i >= 0;
i--) {
1004 const int mb_xy =
s->mb_index2xy[
i];
1005 int error =
s->error_status_table[mb_xy];
1006
1008 end_ok = 0;
1012 end_ok = 1;
1013
1014 if (!end_ok)
1016
1018 end_ok = 0;
1019 }
1020 }
1021 #endif
1022 /* handle missing slices */
1024 int end_ok = 1;
1025
1026 // FIXME + 100 hack
1027 for (
i =
s->mb_num - 2;
i >=
s->mb_width + 100;
i--) {
1028 const int mb_xy =
s->mb_index2xy[
i];
1029 int error1 =
s->error_status_table[mb_xy];
1030 int error2 =
s->error_status_table[
s->mb_index2xy[
i + 1]];
1031
1033 end_ok = 1;
1034
1039 // end & uninit
1040 end_ok = 0;
1041 }
1042
1043 if (!end_ok)
1045 }
1046 }
1047
1048 #if 1
1049 /* backward mark errors */
1051 for (error_type = 1; error_type <= 3; error_type++) {
1052 for (
i =
s->mb_num - 1;
i >= 0;
i--) {
1053 const int mb_xy =
s->mb_index2xy[
i];
1054 int error =
s->error_status_table[mb_xy];
1055
1056 if (!
s->mbskip_table || !
s->mbskip_table[mb_xy])
// FIXME partition specific
1058 if (
error & (1 << error_type))
1060
1061 if (
s->partitioned_frame) {
1062 if (
distance < threshold_part[error_type - 1])
1063 s->error_status_table[mb_xy] |= 1 << error_type;
1064 } else {
1066 s->error_status_table[mb_xy] |= 1 << error_type;
1067 }
1068
1071 }
1072 }
1073 #endif
1074
1075 /* forward mark errors */
1077 for (
i = 0;
i <
s->mb_num;
i++) {
1078 const int mb_xy =
s->mb_index2xy[
i];
1079 int old_error =
s->error_status_table[mb_xy];
1080
1083 } else {
1085 s->error_status_table[mb_xy] |=
error;
1086 }
1087 }
1088 #if 1
1089 /* handle not partitioned case */
1090 if (!
s->partitioned_frame) {
1091 for (
i = 0;
i <
s->mb_num;
i++) {
1092 const int mb_xy =
s->mb_index2xy[
i];
1093 int error =
s->error_status_table[mb_xy];
1096 s->error_status_table[mb_xy] =
error;
1097 }
1098 }
1099 #endif
1100
1101 dc_error = ac_error = mv_error = 0;
1102 for (
i = 0;
i <
s->mb_num;
i++) {
1103 const int mb_xy =
s->mb_index2xy[
i];
1104 int error =
s->error_status_table[mb_xy];
1106 dc_error++;
1108 ac_error++;
1110 mv_error++;
1111 }
1114
1115 if (decode_error_flags)
1117 else
1119
1121
1122 /* set unknown mb-type to most likely */
1125 for (
i = 0;
i <
s->mb_num;
i++) {
1126 const int mb_xy =
s->mb_index2xy[
i];
1127 int error =
s->error_status_table[mb_xy];
1129 continue;
1130
1131 s->cur_pic.mb_type[mb_xy] = guessed_mb_type;
1132 }
1133
1134 // change inter to intra blocks if no reference frames are available
1135 if (!(
s->last_pic.f &&
s->last_pic.f->data[0]) &&
1136 !(
s->next_pic.f &&
s->next_pic.f->data[0]))
1137 for (
i = 0;
i <
s->mb_num;
i++) {
1138 const int mb_xy =
s->mb_index2xy[
i];
1139 if (!
IS_INTRA(
s->cur_pic.mb_type[mb_xy]))
1141 }
1142
1143 /* handle inter blocks with damaged AC */
1144 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1145 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1146 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1147 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1148 const int dir = !(
s->last_pic.f &&
s->last_pic.f->data[0]);
1150 int mv_type;
1151
1152 int error =
s->error_status_table[mb_xy];
1153
1155 continue; // intra
1157 continue; // inter with damaged MV
1159 continue; // undamaged inter
1160
1162 int mb_index = mb_x * 2 + mb_y * 2 *
s->b8_stride;
1163 int j;
1165 for (j = 0; j < 4; j++) {
1166 s->mv[0][j][0] =
s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) *
s->b8_stride][0];
1167 s->mv[0][j][1] =
s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) *
s->b8_stride][1];
1168 }
1169 } else {
1171 s->mv[0][0][0] =
s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 *
s->b8_stride][0];
1172 s->mv[0][0][1] =
s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 *
s->b8_stride][1];
1173 }
1174
1175 s->decode_mb(
s->opaque, 0
/* FIXME H.264 partitioned slices need this set */,
1176 mv_dir, mv_type, &
s->mv, mb_x, mb_y, 0, 0);
1177 }
1178 }
1179
1180 /* guess MVs */
1182 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1183 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1184 int xy = mb_x * 2 + mb_y * 2 *
s->b8_stride;
1185 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1186 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1188
1189 int error =
s->error_status_table[mb_xy];
1190
1192 continue;
1194 continue; // inter with undamaged MV
1196 continue; // undamaged inter
1197
1198 if (!(
s->last_pic.f &&
s->last_pic.f->data[0]))
1200 if (!(
s->next_pic.f &&
s->next_pic.f->data[0]))
1202
1204 int time_pp =
s->pp_time;
1205 int time_pb =
s->pb_time;
1206
1209
1210 s->mv[0][0][0] =
s->next_pic.motion_val[0][xy][0] * time_pb / time_pp;
1211 s->mv[0][0][1] =
s->next_pic.motion_val[0][xy][1] * time_pb / time_pp;
1212 s->mv[1][0][0] =
s->next_pic.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp;
1213 s->mv[1][0][1] =
s->next_pic.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp;
1214 } else {
1219 }
1220
1222 mb_x, mb_y, 0, 0);
1223 }
1224 }
1225 } else
1227
1228 /* fill DC for inter blocks */
1229 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1230 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1231 int dc, dcu, dcv, y, n;
1232 int16_t *dc_ptr;
1233 uint8_t *dest_y, *dest_cb, *dest_cr;
1234 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1235 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1236
1237 // error = s->error_status_table[mb_xy];
1238
1239 if (
IS_INTRA(mb_type) &&
s->partitioned_frame)
1240 continue;
1241 // if (error & ER_MV_ERROR)
1242 // continue; // inter data damaged FIXME is this good?
1243
1244 dest_y =
s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0];
1245 dest_cb =
s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1];
1246 dest_cr =
s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2];
1247
1248 dc_ptr = &
s->dc_val[0][mb_x * 2 + mb_y * 2 *
s->b8_stride];
1249 for (n = 0; n < 4; n++) {
1251 for (y = 0; y < 8; y++) {
1252 int x;
1253 for (x = 0; x < 8; x++)
1254 dc += dest_y[x + (n & 1) * 8 +
1255 (y + (n >> 1) * 8) * linesize[0]];
1256 }
1257 dc_ptr[(n & 1) + (n >> 1) *
s->b8_stride] = (
dc + 4) >> 3;
1258 }
1259
1260 if (!
s->cur_pic.f->data[2])
1261 continue;
1262
1263 dcu = dcv = 0;
1264 for (y = 0; y < 8; y++) {
1265 int x;
1266 for (x = 0; x < 8; x++) {
1267 dcu += dest_cb[x + y * linesize[1]];
1268 dcv += dest_cr[x + y * linesize[2]];
1269 }
1270 }
1271 s->dc_val[1][mb_x + mb_y *
s->mb_stride] = (dcu + 4) >> 3;
1272 s->dc_val[2][mb_x + mb_y *
s->mb_stride] = (dcv + 4) >> 3;
1273 }
1274 }
1275 #if 1
1276 /* guess DC for damaged blocks */
1277 guess_dc(
s,
s->dc_val[0],
s->mb_width*2,
s->mb_height*2,
s->b8_stride, 1);
1278 guess_dc(
s,
s->dc_val[1],
s->mb_width ,
s->mb_height ,
s->mb_stride, 0);
1279 guess_dc(
s,
s->dc_val[2],
s->mb_width ,
s->mb_height ,
s->mb_stride, 0);
1280 #endif
1281
1282 /* filter luma DC */
1283 filter181(
s->dc_val[0],
s->mb_width * 2,
s->mb_height * 2,
s->b8_stride);
1284
1285 #if 1
1286 /* render DC only intra */
1287 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1288 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1289 uint8_t *dest_y, *dest_cb, *dest_cr;
1290 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1291 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1292
1293 int error =
s->error_status_table[mb_xy];
1294
1296 continue;
1298 continue; // undamaged
1299
1300 dest_y =
s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0];
1301 dest_cb =
s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1];
1302 dest_cr =
s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2];
1303 if (!
s->cur_pic.f->data[2])
1304 dest_cb = dest_cr =
NULL;
1305
1306 put_dc(
s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1307 }
1308 }
1309 #endif
1310
1312 /* filter horizontal block boundaries */
1314 s->mb_height * 2, linesize[0], 1);
1315
1316 /* filter vertical block boundaries */
1318 s->mb_height * 2, linesize[0], 1);
1319
1320 if (
s->cur_pic.f->data[2]) {
1322 s->mb_height, linesize[1], 0);
1324 s->mb_height, linesize[2], 0);
1326 s->mb_height, linesize[1], 0);
1328 s->mb_height, linesize[2], 0);
1329 }
1330 }
1331
1332 /* clean a few tables */
1333 for (
i = 0;
i <
s->mb_num;
i++) {
1334 const int mb_xy =
s->mb_index2xy[
i];
1335 int error =
s->error_status_table[mb_xy];
1336
1339 s->mbskip_table[mb_xy] = 0;
1340 }
1341 if (
s->mbintra_table)
1342 s->mbintra_table[mb_xy] = 1;
1343 }
1344
1348
1350 for (
i = 0;
i < 2;
i++) {
1353 s->cur_pic.ref_index[
i] =
NULL;
1354 s->cur_pic.motion_val[
i] =
NULL;
1355 }
1356 }