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
38
39 /**
40 * @param stride the number of MVs to get to the next row
41 * @param mv_step the number of MVs per row or column in a macroblock
42 */
44 {
47 *mv_step = 4;
49 } else {
50 *mv_step = 2;
52 }
53 }
54
55 /**
56 * Replace the current MB with a flat dc-only version.
57 */
59 uint8_t *dest_cr, int mb_x, int mb_y)
60 {
61 int *linesize =
s->cur_pic.f->linesize;
62 int dc, dcu, dcv, y,
i;
63 for (
i = 0;
i < 4;
i++) {
64 dc =
s->dc_val[0][mb_x * 2 + (
i & 1) + (mb_y * 2 + (
i >> 1)) *
s->b8_stride];
69 for (y = 0; y < 8; y++) {
70 int x;
71 for (x = 0; x < 8; x++)
72 dest_y[x + (
i & 1) * 8 + (y + (
i >> 1) * 8) * linesize[0]] =
dc / 8;
73 }
74 }
75 dcu =
s->dc_val[1][mb_x + mb_y *
s->mb_stride];
76 dcv =
s->dc_val[2][mb_x + mb_y *
s->mb_stride];
77 if (dcu < 0)
78 dcu = 0;
79 else if (dcu > 2040)
80 dcu = 2040;
81 if (dcv < 0)
82 dcv = 0;
83 else if (dcv > 2040)
84 dcv = 2040;
85
86 if (dest_cr)
87 for (y = 0; y < 8; y++) {
88 int x;
89 for (x = 0; x < 8; x++) {
90 dest_cb[x + y * linesize[1]] = dcu / 8;
91 dest_cr[x + y * linesize[2]] = dcv / 8;
92 }
93 }
94 }
95
97 {
98 int x, y;
99
100 /* horizontal filter */
101 for (y = 1; y <
height - 1; y++) {
103
104 for (x = 1; x <
width - 1; x++) {
109 dc = (
av_clip(
dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16;
112 }
113 }
114
115 /* vertical filter */
116 for (x = 1; x <
width - 1; x++) {
117 int prev_dc =
data[x];
118
119 for (y = 1; y <
height - 1; y++) {
121
125 dc = (
av_clip(
dc, INT_MIN/10923, INT_MAX/10923 - 32768) * 10923 + 32768) >> 16;
128 }
129 }
130 }
131
132 /**
133 * guess the dc of blocks which do not have an undamaged dc
134 * @param w width in 8 pixel blocks
135 * @param h height in 8 pixel blocks
136 */
138 int h, ptrdiff_t
stride,
int is_luma)
139 {
140 int b_x, b_y;
143
144 if(!col || !dist) {
147 }
148
149 for(b_y=0; b_y<
h; b_y++){
152 for(b_x=0; b_x<
w; b_x++){
153 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*
s->mb_stride;
154 int error_j=
s->error_status_table[mb_index_j];
155 int intra_j =
IS_INTRA(
s->cur_pic.mb_type[mb_index_j]);
159 }
162 }
165 for(b_x=
w-1; b_x>=0; b_x--){
166 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*
s->mb_stride;
167 int error_j=
s->error_status_table[mb_index_j];
168 int intra_j =
IS_INTRA(
s->cur_pic.mb_type[mb_index_j]);
172 }
175 }
176 }
177 for(b_x=0; b_x<
w; b_x++){
180 for(b_y=0; b_y<
h; b_y++){
181 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*
s->mb_stride;
182 int error_j=
s->error_status_table[mb_index_j];
183 int intra_j =
IS_INTRA(
s->cur_pic.mb_type[mb_index_j]);
187 }
190 }
193 for(b_y=
h-1; b_y>=0; b_y--){
194 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*
s->mb_stride;
195 int error_j=
s->error_status_table[mb_index_j];
196 int intra_j =
IS_INTRA(
s->cur_pic.mb_type[mb_index_j]);
200 }
203 }
204 }
205
206 for (b_y = 0; b_y <
h; b_y++) {
207 for (b_x = 0; b_x <
w; b_x++) {
208 int mb_index,
error, j;
210 mb_index = (b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride;
211 error =
s->error_status_table[mb_index];
212
213 if (
IS_INTER(
s->cur_pic.mb_type[mb_index]))
214 continue; // inter
216 continue; // dc-ok
217
218 weight_sum = 0;
219 guess = 0;
220 for (j = 0; j < 4; j++) {
224 }
225 guess = (guess + weight_sum / 2) / weight_sum;
227 }
228 }
229
233 }
234
235 /**
236 * simple horizontal deblocking filter used for error resilience
237 * @param w width in 8 pixel blocks
238 * @param h height in 8 pixel blocks
239 */
241 int h, ptrdiff_t
stride,
int is_luma)
242 {
243 int b_x, b_y;
244 ptrdiff_t mvx_stride, mvy_stride;
247 mvx_stride >>= is_luma;
248 mvy_stride *= mvx_stride;
249
250 for (b_y = 0; b_y <
h; b_y++) {
251 for (b_x = 0; b_x <
w - 1; b_x++) {
252 int y;
253 int left_status =
s->error_status_table[( b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride];
254 int right_status =
s->error_status_table[((b_x + 1) >> is_luma) + (b_y >> is_luma) *
s->mb_stride];
255 int left_intra =
IS_INTRA(
s->cur_pic.mb_type[( b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride]);
256 int right_intra =
IS_INTRA(
s->cur_pic.mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) *
s->mb_stride]);
260 int16_t *left_mv =
s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x];
261 int16_t *right_mv =
s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)];
262 if (!(left_damage || right_damage))
263 continue; // both undamaged
264 if ((!left_intra) && (!right_intra) &&
265 FFABS(left_mv[0] - right_mv[0]) +
266 FFABS(left_mv[1] + right_mv[1]) < 2)
267 continue;
268
269 for (y = 0; y < 8; y++) {
271
275
279 d = -d;
280
281 if (d == 0)
282 continue;
283
284 if (!(left_damage && right_damage))
285 d = d * 16 / 9;
286
287 if (left_damage) {
292 }
293 if (right_damage) {
298 }
299 }
300 }
301 }
302 }
303
304 /**
305 * simple vertical deblocking filter used for error resilience
306 * @param w width in 8 pixel blocks
307 * @param h height in 8 pixel blocks
308 */
310 ptrdiff_t
stride,
int is_luma)
311 {
312 int b_x, b_y;
313 ptrdiff_t mvx_stride, mvy_stride;
316 mvx_stride >>= is_luma;
317 mvy_stride *= mvx_stride;
318
319 for (b_y = 0; b_y <
h - 1; b_y++) {
320 for (b_x = 0; b_x <
w; b_x++) {
321 int x;
322 int top_status =
s->error_status_table[(b_x >> is_luma) + (b_y >> is_luma) *
s->mb_stride];
323 int bottom_status =
s->error_status_table[(b_x >> is_luma) + ((b_y + 1) >> is_luma) *
s->mb_stride];
324 int top_intra =
IS_INTRA(
s->cur_pic.mb_type[(b_x >> is_luma) + ( b_y >> is_luma) *
s->mb_stride]);
325 int bottom_intra =
IS_INTRA(
s->cur_pic.mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) *
s->mb_stride]);
329
330 int16_t *top_mv =
s->cur_pic.motion_val[0][mvy_stride * b_y + mvx_stride * b_x];
331 int16_t *bottom_mv =
s->cur_pic.motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x];
332
333 if (!(top_damage || bottom_damage))
334 continue; // both undamaged
335
336 if ((!top_intra) && (!bottom_intra) &&
337 FFABS(top_mv[0] - bottom_mv[0]) +
338 FFABS(top_mv[1] + bottom_mv[1]) < 2)
339 continue;
340
341 for (x = 0; x < 8; x++) {
343
347
351 d = -d;
352
353 if (d == 0)
354 continue;
355
356 if (!(top_damage && bottom_damage))
357 d = d * 16 / 9;
358
359 if (top_damage) {
364 }
365 if (bottom_damage) {
370 }
371 }
372 }
373 }
374 }
375
378 #define MV_UNCHANGED 2
381 {
383 return;
385 blocklist[ *blocklist_length ][0] = mb_x;
386 blocklist[(*blocklist_length)++][1] = mb_y;
387 }
388
390 {
391 int (*blocklist)[2], (*next_blocklist)[2];
393 const ptrdiff_t mb_stride =
s->mb_stride;
394 const int mb_width =
s->mb_width;
395 int mb_height =
s->mb_height;
397 int mb_x, mb_y;
398 ptrdiff_t mot_step, mot_stride;
399 int blocklist_length, next_blocklist_length;
400
401 if (
s->last_pic.f &&
s->last_pic.f->data[0])
402 mb_height =
FFMIN(mb_height, (
s->last_pic.f->height+15)>>4);
403 if (
s->next_pic.f &&
s->next_pic.f->data[0])
404 mb_height =
FFMIN(mb_height, (
s->next_pic.f->height+15)>>4);
405
406 blocklist = (int (*)[2])
s->er_temp_buffer;
407 next_blocklist = blocklist +
s->mb_stride *
s->mb_height;
408 fixed = (uint8_t *)(next_blocklist +
s->mb_stride *
s->mb_height);
409
411
412 num_avail = 0;
413 if (
s->last_pic.motion_val[0]) {
416 else
418 }
419 for (
i = 0;
i < mb_width * mb_height;
i++) {
420 const int mb_xy =
s->mb_index2xy[
i];
422 int error =
s->error_status_table[mb_xy];
423
428
431 num_avail++;
432 else if(
s->last_pic.f->data[0] &&
s->last_pic.motion_val[0]){
433 const int mb_y= mb_xy /
s->mb_stride;
434 const int mb_x= mb_xy %
s->mb_stride;
435 const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
436 s->cur_pic.motion_val[0][mot_index][0]=
s->last_pic.motion_val[0][mot_index][0];
437 s->cur_pic.motion_val[0][mot_index][1]=
s->last_pic.motion_val[0][mot_index][1];
438 s->cur_pic.ref_index[0][4*mb_xy] =
s->last_pic.ref_index[0][4*mb_xy];
439 }
440 }
441
443 num_avail <=
FFMAX(mb_width, mb_height) / 2) {
444 for (mb_y = 0; mb_y < mb_height; mb_y++) {
445 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
446 const int mb_xy = mb_x + mb_y *
s->mb_stride;
448
450 continue;
452 continue;
453
457 mb_x, mb_y, 0, 0);
458 }
459 }
460 return;
461 }
462
463 blocklist_length = 0;
464 for (mb_y = 0; mb_y < mb_height; mb_y++) {
465 for (mb_x = 0; mb_x < mb_width; mb_x++) {
466 const int mb_xy = mb_x + mb_y * mb_stride;
468 if (mb_x)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x - 1, mb_y, mb_xy - 1);
469 if (mb_y)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x, mb_y - 1, mb_xy - mb_stride);
470 if (mb_x+1 < mb_width)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x + 1, mb_y, mb_xy + 1);
471 if (mb_y+1 < mb_height)
add_blocklist(blocklist, &blocklist_length,
fixed, mb_x, mb_y + 1, mb_xy + mb_stride);
472 }
473 }
474 }
475
476 for (;;) {
477 int changed, pass, none_left;
478 int blocklist_index;
479
480 none_left = 1;
481 changed = 1;
482 for (pass = 0; (changed || pass < 2) && pass < 10; pass++) {
483 changed = 0;
484 for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) {
485 const int mb_x = blocklist[blocklist_index][0];
486 const int mb_y = blocklist[blocklist_index][1];
487 const int mb_xy = mb_x + mb_y * mb_stride;
488 int mv_predictor[8][2];
490 int pred_count;
491 int j;
492 int best_score;
493 int best_pred;
494 int mot_index;
495 int prev_x, prev_y, prev_ref;
496
497 if ((mb_x ^ mb_y ^ pass) & 1)
498 continue;
500
501
504
505 j = 0;
506 if (mb_x > 0)
507 j |=
fixed[mb_xy - 1];
508 if (mb_x + 1 < mb_width)
509 j |=
fixed[mb_xy + 1];
510 if (mb_y > 0)
511 j |=
fixed[mb_xy - mb_stride];
512 if (mb_y + 1 < mb_height)
513 j |=
fixed[mb_xy + mb_stride];
514
516
518 continue;
519
520 none_left = 0;
521 pred_count = 0;
522 mot_index = (mb_x + mb_y * mot_stride) * mot_step;
523
524 if (mb_x > 0 &&
fixed[mb_xy - 1] > 1) {
525 mv_predictor[pred_count][0] =
526 s->cur_pic.motion_val[0][mot_index - mot_step][0];
527 mv_predictor[pred_count][1] =
528 s->cur_pic.motion_val[0][mot_index - mot_step][1];
530 s->cur_pic.ref_index[0][4 * (mb_xy - 1)];
531 pred_count++;
532 }
533 if (mb_x + 1 < mb_width &&
fixed[mb_xy + 1] > 1) {
534 mv_predictor[pred_count][0] =
535 s->cur_pic.motion_val[0][mot_index + mot_step][0];
536 mv_predictor[pred_count][1] =
537 s->cur_pic.motion_val[0][mot_index + mot_step][1];
539 s->cur_pic.ref_index[0][4 * (mb_xy + 1)];
540 pred_count++;
541 }
542 if (mb_y > 0 &&
fixed[mb_xy - mb_stride] > 1) {
543 mv_predictor[pred_count][0] =
544 s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][0];
545 mv_predictor[pred_count][1] =
546 s->cur_pic.motion_val[0][mot_index - mot_stride * mot_step][1];
548 s->cur_pic.ref_index[0][4 * (mb_xy -
s->mb_stride)];
549 pred_count++;
550 }
551 if (mb_y + 1<mb_height &&
fixed[mb_xy + mb_stride] > 1) {
552 mv_predictor[pred_count][0] =
553 s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][0];
554 mv_predictor[pred_count][1] =
555 s->cur_pic.motion_val[0][mot_index + mot_stride * mot_step][1];
557 s->cur_pic.ref_index[0][4 * (mb_xy +
s->mb_stride)];
558 pred_count++;
559 }
560 if (pred_count == 0)
561 continue;
562
563 if (pred_count > 1) {
564 int sum_x = 0, sum_y = 0, sum_r = 0;
565 int max_x, max_y, min_x, min_y, max_r, min_r;
566
567 for (j = 0; j < pred_count; j++) {
568 sum_x += mv_predictor[j][0];
569 sum_y += mv_predictor[j][1];
571 if (j &&
ref[j] !=
ref[j - 1])
572 goto skip_mean_and_median;
573 }
574
575 /* mean */
576 mv_predictor[pred_count][0] = sum_x / j;
577 mv_predictor[pred_count][1] = sum_y / j;
578 ref[pred_count] = sum_r / j;
579
580 /* median */
581 if (pred_count >= 3) {
582 min_y = min_x = min_r = 99999;
583 max_y = max_x = max_r = -99999;
584 } else {
585 min_x = min_y = max_x = max_y = min_r = max_r = 0;
586 }
587 for (j = 0; j < pred_count; j++) {
588 max_x =
FFMAX(max_x, mv_predictor[j][0]);
589 max_y =
FFMAX(max_y, mv_predictor[j][1]);
591 min_x =
FFMIN(min_x, mv_predictor[j][0]);
592 min_y =
FFMIN(min_y, mv_predictor[j][1]);
594 }
595 mv_predictor[pred_count + 1][0] = sum_x - max_x - min_x;
596 mv_predictor[pred_count + 1][1] = sum_y - max_y - min_y;
597 ref[pred_count + 1] = sum_r - max_r - min_r;
598
599 if (pred_count == 4) {
600 mv_predictor[pred_count + 1][0] /= 2;
601 mv_predictor[pred_count + 1][1] /= 2;
602 ref[pred_count + 1] /= 2;
603 }
604 pred_count += 2;
605 }
606
607 skip_mean_and_median:
608 /* zero MV */
609 mv_predictor[pred_count][0] =
610 mv_predictor[pred_count][1] =
612 pred_count++;
613
614 prev_x =
s->cur_pic.motion_val[0][mot_index][0];
615 prev_y =
s->cur_pic.motion_val[0][mot_index][1];
616 prev_ref =
s->cur_pic.ref_index[0][4 * mb_xy];
617
618 /* last MV */
619 mv_predictor[pred_count][0] = prev_x;
620 mv_predictor[pred_count][1] = prev_y;
621 ref[pred_count] = prev_ref;
622 pred_count++;
623
624 best_pred = 0;
625 best_score = 256 * 256 * 256 * 64;
626 for (j = 0; j < pred_count; j++) {
627 int *linesize =
s->cur_pic.f->linesize;
628 int score = 0;
629 uint8_t *
src =
s->cur_pic.f->data[0] +
630 mb_x * 16 + mb_y * 16 * linesize[0];
631
632 s->cur_pic.motion_val[0][mot_index][0] =
633 s->mv[0][0][0] = mv_predictor[j][0];
634 s->cur_pic.motion_val[0][mot_index][1] =
635 s->mv[0][0][1] = mv_predictor[j][1];
636
637 // predictor intra or otherwise not available
639 continue;
640
643
644 if (mb_x > 0 &&
fixed[mb_xy - 1] > 1) {
645 int k;
646 for (k = 0; k < 16; k++)
647 score +=
FFABS(
src[k * linesize[0] - 1] -
648 src[k * linesize[0]]);
649 }
650 if (mb_x + 1 < mb_width &&
fixed[mb_xy + 1] > 1) {
651 int k;
652 for (k = 0; k < 16; k++)
653 score +=
FFABS(
src[k * linesize[0] + 15] -
654 src[k * linesize[0] + 16]);
655 }
656 if (mb_y > 0 &&
fixed[mb_xy - mb_stride] > 1) {
657 int k;
658 for (k = 0; k < 16; k++)
660 }
661 if (mb_y + 1 < mb_height &&
fixed[mb_xy + mb_stride] > 1) {
662 int k;
663 for (k = 0; k < 16; k++)
664 score +=
FFABS(
src[k + linesize[0] * 15] -
665 src[k + linesize[0] * 16]);
666 }
667
668 if (score <= best_score) { // <= will favor the last MV
669 best_score = score;
670 best_pred = j;
671 }
672 }
673 s->mv[0][0][0] = mv_predictor[best_pred][0];
674 s->mv[0][0][1] = mv_predictor[best_pred][1];
675
676 for (
i = 0;
i < mot_step;
i++)
677 for (j = 0; j < mot_step; j++) {
678 s->cur_pic.motion_val[0][mot_index +
i + j * mot_stride][0] =
s->mv[0][0][0];
679 s->cur_pic.motion_val[0][mot_index +
i + j * mot_stride][1] =
s->mv[0][0][1];
680 }
681
684
685
686 if (
s->mv[0][0][0] != prev_x ||
s->mv[0][0][1] != prev_y) {
688 changed++;
689 } else
691 }
692 }
693
694 if (none_left)
695 return;
696
697 next_blocklist_length = 0;
698
699 for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) {
700 const int mb_x = blocklist[blocklist_index][0];
701 const int mb_y = blocklist[blocklist_index][1];
702 const int mb_xy = mb_x + mb_y * mb_stride;
703
706 if (mb_x > 0)
707 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x - 1, mb_y, mb_xy - 1);
708 if (mb_y > 0)
709 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x, mb_y - 1, mb_xy - mb_stride);
710 if (mb_x + 1 < mb_width)
711 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x + 1, mb_y, mb_xy + 1);
712 if (mb_y + 1 < mb_height)
713 add_blocklist(next_blocklist, &next_blocklist_length,
fixed, mb_x, mb_y + 1, mb_xy + mb_stride);
714 }
715 }
716 av_assert0(next_blocklist_length <= mb_height * mb_width);
717 FFSWAP(
int , blocklist_length, next_blocklist_length);
718 FFSWAP(
void*, blocklist, next_blocklist);
719 }
720 }
721
723 {
724 int is_intra_likely,
i, j, undamaged_count, skip_amount, mb_x, mb_y;
725
726 if (!
s->last_pic.f || !
s->last_pic.f->data[0])
727 return 1; // no previous frame available -> use spatial prediction
728
730 return 0;
731
732 undamaged_count = 0;
733 for (
i = 0;
i <
s->mb_num;
i++) {
734 const int mb_xy =
s->mb_index2xy[
i];
735 const int error =
s->error_status_table[mb_xy];
737 undamaged_count++;
738 }
739
740 if (undamaged_count < 5)
741 return 0; // almost all MBs damaged -> use temporal prediction
742
743 skip_amount =
FFMAX(undamaged_count / 50, 1);
// check only up to 50 MBs
744 is_intra_likely = 0;
745
746 j = 0;
747 for (mb_y = 0; mb_y <
s->mb_height - 1; mb_y++) {
748 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
750 const int mb_xy = mb_x + mb_y *
s->mb_stride;
751
752 error =
s->error_status_table[mb_xy];
754 continue; // skip damaged
755
756 j++;
757 // skip a few to speed things up
758 if ((j % skip_amount) != 0)
759 continue;
760
762 int *linesize =
s->cur_pic.f->linesize;
763 uint8_t *mb_ptr =
s->cur_pic.f->data[0] +
764 mb_x * 16 + mb_y * 16 * linesize[0];
765 uint8_t *last_mb_ptr =
s->last_pic.f->data[0] +
766 mb_x * 16 + mb_y * 16 * linesize[0];
767
769 // FIXME
770 } else {
772 }
773 is_intra_likely +=
s->sad(
NULL, last_mb_ptr, mb_ptr,
774 linesize[0], 16);
775 // FIXME need await_progress() here
776 is_intra_likely -=
s->sad(
NULL, last_mb_ptr,
777 last_mb_ptr + linesize[0] * 16,
778 linesize[0], 16);
779 } else {
781 is_intra_likely++;
782 else
783 is_intra_likely--;
784 }
785 }
786 }
787 // av_log(NULL, AV_LOG_ERROR, "is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
788 return is_intra_likely > 0;
789 }
790
792 {
793 if (!
s->avctx->error_concealment)
794 return;
795
796 if (!
s->mecc_inited) {
799 s->sad = mecc.
sad[0];
801 }
802
804 s->mb_stride *
s->mb_height *
sizeof(uint8_t));
806 s->error_occurred = 0;
807 }
808
810 {
811 if (
s->avctx->hwaccel ||
813 s->cur_pic.field_picture
814 )
815 return 0;
816 return 1;
817 }
818
819 /**
820 * Add a slice.
821 * @param endx x component of the last macroblock, can be -1
822 * for the last of the previous line
823 * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is
824 * assumed that no earlier end or error of the same type occurred
825 */
827 int endx,
int endy,
int status)
828 {
829 const int start_i =
av_clip(startx + starty *
s->mb_width, 0,
s->mb_num - 1);
830 const int end_i =
av_clip(endx + endy *
s->mb_width, 0,
s->mb_num);
831 const int start_xy =
s->mb_index2xy[start_i];
832 const int end_xy =
s->mb_index2xy[end_i];
834
835 if (
s->avctx->hwaccel)
836 return;
837
838 if (start_i > end_i || start_xy > end_xy) {
840 "internal error, slice end before start\n");
841 return;
842 }
843
844 if (!
s->avctx->error_concealment)
845 return;
846
851 }
855 }
859 }
860
862 s->error_occurred = 1;
864 }
865
867 memset(&
s->error_status_table[start_xy], 0,
868 (end_xy - start_xy) * sizeof(uint8_t));
869 } else {
871 for (
i = start_xy;
i < end_xy;
i++)
872 s->error_status_table[
i] &=
mask;
873 }
874
875 if (end_i ==
s->mb_num)
877 else {
878 s->error_status_table[end_xy] &=
mask;
879 s->error_status_table[end_xy] |=
status;
880 }
881
882 s->error_status_table[start_xy] |=
VP_START;
883
886 int prev_status =
s->error_status_table[
s->mb_index2xy[start_i - 1]];
887
890 s->error_occurred = 1;
892 }
893 }
894 }
895
897 {
898 int *linesize =
NULL;
899 int i, mb_x, mb_y,
error, error_type, dc_error, mv_error, ac_error;
901 int threshold_part[4] = { 100, 100, 100 };
902 int threshold = 50;
903 int is_intra_likely;
904 int size =
s->b8_stride * 2 *
s->mb_height;
905 int guessed_mb_type;
906
907 /* We do not support ER of field pictures yet,
908 * though it should not crash if enabled. */
909 if (!
s->avctx->error_concealment || !
atomic_load(&
s->error_count) ||
913 (
s->avctx->skip_top +
s->avctx->skip_bottom)) {
914 return;
915 }
916 linesize =
s->cur_pic.f->linesize;
917
919 && (
FFALIGN(
s->avctx->height, 16)&16)
920 &&
atomic_load(&
s->error_count) == 3 *
s->mb_width * (
s->avctx->skip_top +
s->avctx->skip_bottom + 1)) {
921 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
922 int status =
s->error_status_table[mb_x + (
s->mb_height - 1) *
s->mb_stride];
924 break;
925 }
926
927 if (mb_x ==
s->mb_width) {
929 return;
930 }
931 }
932
934 if (
s->last_pic.f->width !=
s->cur_pic.f->width ||
935 s->last_pic.f->height !=
s->cur_pic.f->height ||
936 s->last_pic.f->format !=
s->cur_pic.f->format) {
938 memset(&
s->last_pic, 0,
sizeof(
s->last_pic));
939 }
940 }
942 if (
s->next_pic.f->width !=
s->cur_pic.f->width ||
943 s->next_pic.f->height !=
s->cur_pic.f->height ||
944 s->next_pic.f->format !=
s->cur_pic.f->format) {
946 memset(&
s->next_pic, 0,
sizeof(
s->next_pic));
947 }
948 }
949
950 if (!
s->cur_pic.motion_val[0] || !
s->cur_pic.ref_index[0]) {
952
953 for (
i = 0;
i < 2;
i++) {
954 s->ref_index[
i] =
av_calloc(
s->mb_stride *
s->mb_height, 4 *
sizeof(uint8_t));
956 if (!
s->ref_index[
i] || !
s->motion_val_base[
i])
958 s->cur_pic.ref_index[
i] =
s->ref_index[
i];
959 s->cur_pic.motion_val[
i] =
s->motion_val_base[
i] + 4;
960 }
961 }
962
964 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
965 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
966 int status =
s->error_status_table[mb_x + mb_y *
s->mb_stride];
967
969 }
971 }
972 }
973
974 #if 1
975 /* handle overlapping slices */
976 for (error_type = 1; error_type <= 3; error_type++) {
977 int end_ok = 0;
978
979 for (
i =
s->mb_num - 1;
i >= 0;
i--) {
980 const int mb_xy =
s->mb_index2xy[
i];
981 int error =
s->error_status_table[mb_xy];
982
983 if (
error & (1 << error_type))
984 end_ok = 1;
985 if (
error & (8 << error_type))
986 end_ok = 1;
987
988 if (!end_ok)
989 s->error_status_table[mb_xy] |= 1 << error_type;
990
992 end_ok = 0;
993 }
994 }
995 #endif
996 #if 1
997 /* handle slices with partitions of different length */
998 if (
s->partitioned_frame) {
999 int end_ok = 0;
1000
1001 for (
i =
s->mb_num - 1;
i >= 0;
i--) {
1002 const int mb_xy =
s->mb_index2xy[
i];
1003 int error =
s->error_status_table[mb_xy];
1004
1006 end_ok = 0;
1010 end_ok = 1;
1011
1012 if (!end_ok)
1014
1016 end_ok = 0;
1017 }
1018 }
1019 #endif
1020 /* handle missing slices */
1022 int end_ok = 1;
1023
1024 // FIXME + 100 hack
1025 for (
i =
s->mb_num - 2;
i >=
s->mb_width + 100;
i--) {
1026 const int mb_xy =
s->mb_index2xy[
i];
1027 int error1 =
s->error_status_table[mb_xy];
1028 int error2 =
s->error_status_table[
s->mb_index2xy[
i + 1]];
1029
1031 end_ok = 1;
1032
1037 // end & uninit
1038 end_ok = 0;
1039 }
1040
1041 if (!end_ok)
1043 }
1044 }
1045
1046 #if 1
1047 /* backward mark errors */
1049 for (error_type = 1; error_type <= 3; error_type++) {
1050 for (
i =
s->mb_num - 1;
i >= 0;
i--) {
1051 const int mb_xy =
s->mb_index2xy[
i];
1052 int error =
s->error_status_table[mb_xy];
1053
1054 if (!
s->mbskip_table || !
s->mbskip_table[mb_xy])
// FIXME partition specific
1056 if (
error & (1 << error_type))
1058
1059 if (
s->partitioned_frame) {
1060 if (
distance < threshold_part[error_type - 1])
1061 s->error_status_table[mb_xy] |= 1 << error_type;
1062 } else {
1064 s->error_status_table[mb_xy] |= 1 << error_type;
1065 }
1066
1069 }
1070 }
1071 #endif
1072
1073 /* forward mark errors */
1075 for (
i = 0;
i <
s->mb_num;
i++) {
1076 const int mb_xy =
s->mb_index2xy[
i];
1077 int old_error =
s->error_status_table[mb_xy];
1078
1081 } else {
1083 s->error_status_table[mb_xy] |=
error;
1084 }
1085 }
1086 #if 1
1087 /* handle not partitioned case */
1088 if (!
s->partitioned_frame) {
1089 for (
i = 0;
i <
s->mb_num;
i++) {
1090 const int mb_xy =
s->mb_index2xy[
i];
1091 int error =
s->error_status_table[mb_xy];
1094 s->error_status_table[mb_xy] =
error;
1095 }
1096 }
1097 #endif
1098
1099 dc_error = ac_error = mv_error = 0;
1100 for (
i = 0;
i <
s->mb_num;
i++) {
1101 const int mb_xy =
s->mb_index2xy[
i];
1102 int error =
s->error_status_table[mb_xy];
1104 dc_error++;
1106 ac_error++;
1108 mv_error++;
1109 }
1112
1113 if (decode_error_flags)
1115 else
1117
1119
1120 /* set unknown mb-type to most likely */
1123 for (
i = 0;
i <
s->mb_num;
i++) {
1124 const int mb_xy =
s->mb_index2xy[
i];
1125 int error =
s->error_status_table[mb_xy];
1127 continue;
1128
1129 s->cur_pic.mb_type[mb_xy] = guessed_mb_type;
1130 }
1131
1132 // change inter to intra blocks if no reference frames are available
1133 if (!(
s->last_pic.f &&
s->last_pic.f->data[0]) &&
1134 !(
s->next_pic.f &&
s->next_pic.f->data[0]))
1135 for (
i = 0;
i <
s->mb_num;
i++) {
1136 const int mb_xy =
s->mb_index2xy[
i];
1137 if (!
IS_INTRA(
s->cur_pic.mb_type[mb_xy]))
1139 }
1140
1141 /* handle inter blocks with damaged AC */
1142 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1143 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1144 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1145 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1146 const int dir = !(
s->last_pic.f &&
s->last_pic.f->data[0]);
1148 int mv_type;
1149
1150 int error =
s->error_status_table[mb_xy];
1151
1153 continue; // intra
1155 continue; // inter with damaged MV
1157 continue; // undamaged inter
1158
1160 int mb_index = mb_x * 2 + mb_y * 2 *
s->b8_stride;
1161 int j;
1163 for (j = 0; j < 4; j++) {
1164 s->mv[0][j][0] =
s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) *
s->b8_stride][0];
1165 s->mv[0][j][1] =
s->cur_pic.motion_val[dir][mb_index + (j & 1) + (j >> 1) *
s->b8_stride][1];
1166 }
1167 } else {
1169 s->mv[0][0][0] =
s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 *
s->b8_stride][0];
1170 s->mv[0][0][1] =
s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 *
s->b8_stride][1];
1171 }
1172
1173 s->decode_mb(
s->opaque, 0
/* FIXME H.264 partitioned slices need this set */,
1174 mv_dir, mv_type, &
s->mv, mb_x, mb_y, 0, 0);
1175 }
1176 }
1177
1178 /* guess MVs */
1180 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1181 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1182 int xy = mb_x * 2 + mb_y * 2 *
s->b8_stride;
1183 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1184 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1186
1187 int error =
s->error_status_table[mb_xy];
1188
1190 continue;
1192 continue; // inter with undamaged MV
1194 continue; // undamaged inter
1195
1196 if (!(
s->last_pic.f &&
s->last_pic.f->data[0]))
1198 if (!(
s->next_pic.f &&
s->next_pic.f->data[0]))
1200
1202 int time_pp =
s->pp_time;
1203 int time_pb =
s->pb_time;
1204
1207
1208 s->mv[0][0][0] =
s->next_pic.motion_val[0][xy][0] * time_pb / time_pp;
1209 s->mv[0][0][1] =
s->next_pic.motion_val[0][xy][1] * time_pb / time_pp;
1210 s->mv[1][0][0] =
s->next_pic.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp;
1211 s->mv[1][0][1] =
s->next_pic.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp;
1212 } else {
1217 }
1218
1220 mb_x, mb_y, 0, 0);
1221 }
1222 }
1223 } else
1225
1226 /* fill DC for inter blocks */
1227 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1228 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1229 int dc, dcu, dcv, y, n;
1230 int16_t *dc_ptr;
1231 uint8_t *dest_y, *dest_cb, *dest_cr;
1232 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1233 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1234
1235 // error = s->error_status_table[mb_xy];
1236
1237 if (
IS_INTRA(mb_type) &&
s->partitioned_frame)
1238 continue;
1239 // if (error & ER_MV_ERROR)
1240 // continue; // inter data damaged FIXME is this good?
1241
1242 dest_y =
s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0];
1243 dest_cb =
s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1];
1244 dest_cr =
s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2];
1245
1246 dc_ptr = &
s->dc_val[0][mb_x * 2 + mb_y * 2 *
s->b8_stride];
1247 for (n = 0; n < 4; n++) {
1249 for (y = 0; y < 8; y++) {
1250 int x;
1251 for (x = 0; x < 8; x++)
1252 dc += dest_y[x + (n & 1) * 8 +
1253 (y + (n >> 1) * 8) * linesize[0]];
1254 }
1255 dc_ptr[(n & 1) + (n >> 1) *
s->b8_stride] = (
dc + 4) >> 3;
1256 }
1257
1258 if (!
s->cur_pic.f->data[2])
1259 continue;
1260
1261 dcu = dcv = 0;
1262 for (y = 0; y < 8; y++) {
1263 int x;
1264 for (x = 0; x < 8; x++) {
1265 dcu += dest_cb[x + y * linesize[1]];
1266 dcv += dest_cr[x + y * linesize[2]];
1267 }
1268 }
1269 s->dc_val[1][mb_x + mb_y *
s->mb_stride] = (dcu + 4) >> 3;
1270 s->dc_val[2][mb_x + mb_y *
s->mb_stride] = (dcv + 4) >> 3;
1271 }
1272 }
1273 #if 1
1274 /* guess DC for damaged blocks */
1275 guess_dc(
s,
s->dc_val[0],
s->mb_width*2,
s->mb_height*2,
s->b8_stride, 1);
1276 guess_dc(
s,
s->dc_val[1],
s->mb_width ,
s->mb_height ,
s->mb_stride, 0);
1277 guess_dc(
s,
s->dc_val[2],
s->mb_width ,
s->mb_height ,
s->mb_stride, 0);
1278 #endif
1279
1280 /* filter luma DC */
1281 filter181(
s->dc_val[0],
s->mb_width * 2,
s->mb_height * 2,
s->b8_stride);
1282
1283 #if 1
1284 /* render DC only intra */
1285 for (mb_y = 0; mb_y <
s->mb_height; mb_y++) {
1286 for (mb_x = 0; mb_x <
s->mb_width; mb_x++) {
1287 uint8_t *dest_y, *dest_cb, *dest_cr;
1288 const int mb_xy = mb_x + mb_y *
s->mb_stride;
1289 const int mb_type =
s->cur_pic.mb_type[mb_xy];
1290
1291 int error =
s->error_status_table[mb_xy];
1292
1294 continue;
1296 continue; // undamaged
1297
1298 dest_y =
s->cur_pic.f->data[0] + mb_x * 16 + mb_y * 16 * linesize[0];
1299 dest_cb =
s->cur_pic.f->data[1] + mb_x * 8 + mb_y * 8 * linesize[1];
1300 dest_cr =
s->cur_pic.f->data[2] + mb_x * 8 + mb_y * 8 * linesize[2];
1301 if (!
s->cur_pic.f->data[2])
1302 dest_cb = dest_cr =
NULL;
1303
1304 put_dc(
s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1305 }
1306 }
1307 #endif
1308
1310 /* filter horizontal block boundaries */
1312 s->mb_height * 2, linesize[0], 1);
1313
1314 /* filter vertical block boundaries */
1316 s->mb_height * 2, linesize[0], 1);
1317
1318 if (
s->cur_pic.f->data[2]) {
1320 s->mb_height, linesize[1], 0);
1322 s->mb_height, linesize[2], 0);
1324 s->mb_height, linesize[1], 0);
1326 s->mb_height, linesize[2], 0);
1327 }
1328 }
1329
1330 /* clean a few tables */
1331 for (
i = 0;
i <
s->mb_num;
i++) {
1332 const int mb_xy =
s->mb_index2xy[
i];
1333 int error =
s->error_status_table[mb_xy];
1334
1337 s->mbskip_table[mb_xy] = 0;
1338 }
1339 if (
s->mbintra_table)
1340 s->mbintra_table[mb_xy] = 1;
1341 }
1342
1346
1348 for (
i = 0;
i < 2;
i++) {
1351 s->cur_pic.ref_index[
i] =
NULL;
1352 s->cur_pic.motion_val[
i] =
NULL;
1353 }
1354 }