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
28 #include <limits.h>
29
36
37 /*
38 * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264)
39 * but error concealment must support both h264 and h263 thus we must undo this
40 */
41 #undef mb_intra
42
44 {
48
53
59 /* FIXME: It is possible albeit uncommon that slice references
60 * differ between slices. We take the easy approach and ignore
61 * it for now. If this turns out to have any relevance in
62 * practice then correct remapping should be added. */
64 ref = 0;
67 ref = 0;
68 }
71 return;
72 }
74 2, 2, 2, ref, 1);
81 } else {
82 assert(ref == 0);
84 }
85 }
86
87 /**
88 * @param stride the number of MVs to get to the next row
89 * @param mv_step the number of MVs per row or column in a macroblock
90 */
92 {
96 *mv_step = 4;
98 } else {
99 *mv_step = 2;
101 }
102 }
103
104 /**
105 * Replace the current MB with a flat dc-only version.
106 */
108 uint8_t *dest_cr,
int mb_x,
int mb_y)
109 {
110 int dc, dcu, dcv, y, i;
111 for (i = 0; i < 4; i++) {
112 dc = s->
dc_val[0][mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * s->
b8_stride];
114 dc = 0;
115 else if (dc > 2040)
116 dc = 2040;
117 for (y = 0; y < 8; y++) {
118 int x;
119 for (x = 0; x < 8; x++)
120 dest_y[x + (i & 1) * 8 + (y + (i >> 1) * 8) * s->
linesize] = dc / 8;
121 }
122 }
125 if (dcu < 0)
126 dcu = 0;
127 else if (dcu > 2040)
128 dcu = 2040;
129 if (dcv < 0)
130 dcv = 0;
131 else if (dcv > 2040)
132 dcv = 2040;
133 for (y = 0; y < 8; y++) {
134 int x;
135 for (x = 0; x < 8; x++) {
138 }
139 }
140 }
141
143 {
144 int x, y;
145
146 /* horizontal filter */
147 for (y = 1; y < height - 1; y++) {
148 int prev_dc = data[0 + y *
stride];
149
150 for (x = 1; x < width - 1; x++) {
151 int dc;
152 dc = -prev_dc +
153 data[x + y *
stride] * 8 -
155 dc = (dc * 10923 + 32768) >> 16;
156 prev_dc = data[x + y *
stride];
157 data[x + y *
stride] = dc;
158 }
159 }
160
161 /* vertical filter */
162 for (x = 1; x < width - 1; x++) {
163 int prev_dc = data[x];
164
165 for (y = 1; y < height - 1; y++) {
166 int dc;
167
168 dc = -prev_dc +
169 data[x + y *
stride] * 8 -
170 data[x + (y + 1) * stride];
171 dc = (dc * 10923 + 32768) >> 16;
172 prev_dc = data[x + y *
stride];
173 data[x + y *
stride] = dc;
174 }
175 }
176 }
177
178 /**
179 * guess the dc of blocks which do not have an undamaged dc
180 * @param w width in 8 pixel blocks
181 * @param h height in 8 pixel blocks
182 */
184 int h,
int stride,
int is_luma)
185 {
186 int b_x, b_y;
187 int16_t (*col )[4] =
av_malloc(stride*h*
sizeof( int16_t)*4);
188 uint32_t (*dist)[4] =
av_malloc(stride*h*
sizeof(uint32_t)*4);
189
190 if(!col || !dist) {
192 goto fail;
193 }
194
195 for(b_y=0; b_y<h; b_y++){
198 for(b_x=0; b_x<w; b_x++){
199 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->
mb_stride;
203 color= dc[b_x + b_y*
stride];
204 distance= b_x;
205 }
207 dist[b_x + b_y*
stride][1]= distance >= 0 ? b_x-distance : 9999;
208 }
209 color= 1024;
210 distance= -1;
211 for(b_x=w-1; b_x>=0; b_x--){
212 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->
mb_stride;
216 color= dc[b_x + b_y*
stride];
217 distance= b_x;
218 }
220 dist[b_x + b_y*
stride][0]= distance >= 0 ? distance-b_x : 9999;
221 }
222 }
223 for(b_x=0; b_x<w; b_x++){
226 for(b_y=0; b_y<h; b_y++){
227 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->
mb_stride;
231 color= dc[b_x + b_y*
stride];
232 distance= b_y;
233 }
235 dist[b_x + b_y*
stride][3]= distance >= 0 ? b_y-distance : 9999;
236 }
237 color= 1024;
238 distance= -1;
239 for(b_y=h-1; b_y>=0; b_y--){
240 int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->
mb_stride;
244 color= dc[b_x + b_y*
stride];
245 distance= b_y;
246 }
248 dist[b_x + b_y*
stride][2]= distance >= 0 ? distance-b_y : 9999;
249 }
250 }
251
252 for (b_y = 0; b_y < h; b_y++) {
253 for (b_x = 0; b_x < w; b_x++) {
254 int mb_index, error, j;
255 int64_t guess, weight_sum;
256 mb_index = (b_x >> is_luma) + (b_y >> is_luma) * s->
mb_stride;
258
260 continue; // inter
262 continue; // dc-ok
263
264 weight_sum = 0;
265 guess = 0;
266 for (j = 0; j < 4; j++) {
267 int64_t
weight = 256 * 256 * 256 * 16 /
FFMAX(dist[b_x + b_y*stride][j], 1);
268 guess += weight*(int64_t)col[b_x + b_y*stride][j];
270 }
271 guess = (guess + weight_sum / 2) / weight_sum;
272 dc[b_x + b_y *
stride] = guess;
273 }
274 }
275
276 fail:
279 }
280
281 /**
282 * simple horizontal deblocking filter used for error resilience
283 * @param w width in 8 pixel blocks
284 * @param h height in 8 pixel blocks
285 */
287 int h,
int stride,
int is_luma)
288 {
289 int b_x, b_y, mvx_stride, mvy_stride;
292 mvx_stride >>= is_luma;
293 mvy_stride *= mvx_stride;
294
295 for (b_y = 0; b_y < h; b_y++) {
296 for (b_x = 0; b_x < w - 1; b_x++) {
297 int y;
304 int offset = b_x * 8 + b_y * stride * 8;
307 if (!(left_damage || right_damage))
308 continue; // both undamaged
309 if ((!left_intra) && (!right_intra) &&
310 FFABS(left_mv[0] - right_mv[0]) +
311 FFABS(left_mv[1] + right_mv[1]) < 2)
312 continue;
313
314 for (y = 0; y < 8; y++) {
316
317 a = dst[offset + 7 + y *
stride] - dst[offset + 6 + y *
stride];
318 b = dst[offset + 8 + y *
stride] - dst[offset + 7 + y *
stride];
319 c = dst[offset + 9 + y *
stride] - dst[offset + 8 + y *
stride];
320
323 if (b < 0)
324 d = -d;
325
326 if (d == 0)
327 continue;
328
329 if (!(left_damage && right_damage))
330 d = d * 16 / 9;
331
332 if (left_damage) {
333 dst[offset + 7 + y *
stride] = cm[dst[offset + 7 + y *
stride] + ((d * 7) >> 4)];
334 dst[offset + 6 + y *
stride] = cm[dst[offset + 6 + y *
stride] + ((d * 5) >> 4)];
335 dst[offset + 5 + y *
stride] = cm[dst[offset + 5 + y *
stride] + ((d * 3) >> 4)];
336 dst[offset + 4 + y *
stride] = cm[dst[offset + 4 + y *
stride] + ((d * 1) >> 4)];
337 }
338 if (right_damage) {
339 dst[offset + 8 + y *
stride] = cm[dst[offset + 8 + y *
stride] - ((d * 7) >> 4)];
340 dst[offset + 9 + y *
stride] = cm[dst[offset + 9 + y *
stride] - ((d * 5) >> 4)];
341 dst[offset + 10+ y *
stride] = cm[dst[offset + 10 + y *
stride] - ((d * 3) >> 4)];
342 dst[offset + 11+ y *
stride] = cm[dst[offset + 11 + y *
stride] - ((d * 1) >> 4)];
343 }
344 }
345 }
346 }
347 }
348
349 /**
350 * simple vertical deblocking filter used for error resilience
351 * @param w width in 8 pixel blocks
352 * @param h height in 8 pixel blocks
353 */
356 {
357 int b_x, b_y, mvx_stride, mvy_stride;
360 mvx_stride >>= is_luma;
361 mvy_stride *= mvx_stride;
362
363 for (b_y = 0; b_y < h - 1; b_y++) {
364 for (b_x = 0; b_x < w; b_x++) {
365 int x;
372 int offset = b_x * 8 + b_y * stride * 8;
373
376
377 if (!(top_damage || bottom_damage))
378 continue; // both undamaged
379
380 if ((!top_intra) && (!bottom_intra) &&
381 FFABS(top_mv[0] - bottom_mv[0]) +
382 FFABS(top_mv[1] + bottom_mv[1]) < 2)
383 continue;
384
385 for (x = 0; x < 8; x++) {
387
388 a = dst[offset + x + 7 *
stride] - dst[offset + x + 6 *
stride];
389 b = dst[offset + x + 8 *
stride] - dst[offset + x + 7 *
stride];
390 c = dst[offset + x + 9 *
stride] - dst[offset + x + 8 *
stride];
391
394 if (b < 0)
395 d = -d;
396
397 if (d == 0)
398 continue;
399
400 if (!(top_damage && bottom_damage))
401 d = d * 16 / 9;
402
403 if (top_damage) {
404 dst[offset + x + 7 *
stride] = cm[dst[offset + x + 7 *
stride] + ((d * 7) >> 4)];
405 dst[offset + x + 6 *
stride] = cm[dst[offset + x + 6 *
stride] + ((d * 5) >> 4)];
406 dst[offset + x + 5 *
stride] = cm[dst[offset + x + 5 *
stride] + ((d * 3) >> 4)];
407 dst[offset + x + 4 *
stride] = cm[dst[offset + x + 4 *
stride] + ((d * 1) >> 4)];
408 }
409 if (bottom_damage) {
410 dst[offset + x + 8 *
stride] = cm[dst[offset + x + 8 *
stride] - ((d * 7) >> 4)];
411 dst[offset + x + 9 *
stride] = cm[dst[offset + x + 9 *
stride] - ((d * 5) >> 4)];
412 dst[offset + x + 10 *
stride] = cm[dst[offset + x + 10 *
stride] - ((d * 3) >> 4)];
413 dst[offset + x + 11 *
stride] = cm[dst[offset + x + 11 *
stride] - ((d * 1) >> 4)];
414 }
415 }
416 }
417 }
418 }
419
421 {
423 #define MV_FROZEN 3
424 #define MV_CHANGED 2
425 #define MV_UNCHANGED 1
429 int i,
depth, num_avail;
430 int mb_x, mb_y, mot_step, mot_stride;
431
433
434 num_avail = 0;
435 for (i = 0; i < s->
mb_num; i++) {
437 int f = 0;
439
443 f =
MV_FROZEN;
// inter with undamaged MV
444
445 fixed[mb_xy] = f;
447 num_avail++;
451 const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
455 }
456 }
457
459 num_avail <= mb_width / 2) {
460 for (mb_y = 0; mb_y < s->
mb_height; mb_y++) {
461 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
462 const int mb_xy = mb_x + mb_y * s->
mb_stride;
463
465 continue;
467 continue;
468
474
476
482 }
483 }
484 return;
485 }
486
487 for (depth = 0; ; depth++) {
488 int changed,
pass, none_left;
489
490 none_left = 1;
491 changed = 1;
492 for (pass = 0; (changed || pass < 2) && pass < 10; pass++) {
493 int mb_x, mb_y;
494 int score_sum = 0;
495
496 changed = 0;
497 for (mb_y = 0; mb_y < s->
mb_height; mb_y++) {
498 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
499 const int mb_xy = mb_x + mb_y * s->
mb_stride;
500 int mv_predictor[8][2] = { { 0 } };
501 int ref[8] = { 0 };
502 int pred_count = 0;
503 int j;
504 int best_score = 256 * 256 * 256 * 64;
505 int best_pred = 0;
506 const int mot_index = (mb_x + mb_y * mot_stride) * mot_step;
507 int prev_x, prev_y, prev_ref;
508
509 if ((mb_x ^ mb_y ^ pass) & 1)
510 continue;
511
513 continue;
516
517 j = 0;
518 if (mb_x > 0 && fixed[mb_xy - 1] ==
MV_FROZEN)
519 j = 1;
520 if (mb_x + 1 < mb_width && fixed[mb_xy + 1] ==
MV_FROZEN)
521 j = 1;
522 if (mb_y > 0 && fixed[mb_xy - mb_stride] ==
MV_FROZEN)
523 j = 1;
524 if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] ==
MV_FROZEN)
525 j = 1;
526 if (j == 0)
527 continue;
528
529 j = 0;
530 if (mb_x > 0 && fixed[mb_xy - 1 ] ==
MV_CHANGED)
531 j = 1;
532 if (mb_x + 1 < mb_width && fixed[mb_xy + 1 ] ==
MV_CHANGED)
533 j = 1;
534 if (mb_y > 0 && fixed[mb_xy - mb_stride] ==
MV_CHANGED)
535 j = 1;
536 if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] ==
MV_CHANGED)
537 j = 1;
538 if (j == 0 && pass > 1)
539 continue;
540
541 none_left = 0;
542
543 if (mb_x > 0 && fixed[mb_xy - 1]) {
544 mv_predictor[pred_count][0] =
546 mv_predictor[pred_count][1] =
548 ref[pred_count] =
550 pred_count++;
551 }
552 if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) {
553 mv_predictor[pred_count][0] =
555 mv_predictor[pred_count][1] =
557 ref[pred_count] =
559 pred_count++;
560 }
561 if (mb_y > 0 && fixed[mb_xy - mb_stride]) {
562 mv_predictor[pred_count][0] =
564 mv_predictor[pred_count][1] =
566 ref[pred_count] =
568 pred_count++;
569 }
570 if (mb_y + 1<mb_height && fixed[mb_xy + mb_stride]) {
571 mv_predictor[pred_count][0] =
573 mv_predictor[pred_count][1] =
575 ref[pred_count] =
577 pred_count++;
578 }
579 if (pred_count == 0)
580 continue;
581
582 if (pred_count > 1) {
583 int sum_x = 0, sum_y = 0, sum_r = 0;
584 int max_x, max_y, min_x, min_y, max_r, min_r;
585
586 for (j = 0; j < pred_count; j++) {
587 sum_x += mv_predictor[j][0];
588 sum_y += mv_predictor[j][1];
589 sum_r += ref[j];
590 if (j && ref[j] != ref[j - 1])
591 goto skip_mean_and_median;
592 }
593
594 /* mean */
595 mv_predictor[pred_count][0] = sum_x / j;
596 mv_predictor[pred_count][1] = sum_y / j;
597 ref[pred_count] = sum_r / j;
598
599 /* median */
600 if (pred_count >= 3) {
601 min_y = min_x = min_r = 99999;
602 max_y = max_x = max_r = -99999;
603 } else {
604 min_x = min_y = max_x = max_y = min_r = max_r = 0;
605 }
606 for (j = 0; j < pred_count; j++) {
607 max_x =
FFMAX(max_x, mv_predictor[j][0]);
608 max_y =
FFMAX(max_y, mv_predictor[j][1]);
609 max_r =
FFMAX(max_r, ref[j]);
610 min_x =
FFMIN(min_x, mv_predictor[j][0]);
611 min_y =
FFMIN(min_y, mv_predictor[j][1]);
612 min_r =
FFMIN(min_r, ref[j]);
613 }
614 mv_predictor[pred_count + 1][0] = sum_x - max_x - min_x;
615 mv_predictor[pred_count + 1][1] = sum_y - max_y - min_y;
616 ref[pred_count + 1] = sum_r - max_r - min_r;
617
618 if (pred_count == 4) {
619 mv_predictor[pred_count + 1][0] /= 2;
620 mv_predictor[pred_count + 1][1] /= 2;
621 ref[pred_count + 1] /= 2;
622 }
623 pred_count += 2;
624 }
625
626 skip_mean_and_median:
627 /* zero MV */
628 pred_count++;
629
630 if (!fixed[mb_xy] && 0) {
632 // FIXME
633 } else {
635 mb_y, 0);
636 }
639 goto skip_last_mv;
643 } else {
647 }
648
649 /* last MV */
650 mv_predictor[pred_count][0] = prev_x;
651 mv_predictor[pred_count][1] = prev_y;
652 ref[pred_count] = prev_ref;
653 pred_count++;
654
655 skip_last_mv:
660
662
665
666 for (j = 0; j < pred_count; j++) {
667 int score = 0;
669 mb_x * 16 + mb_y * 16 * s->
linesize;
670
672 s->
mv[0][0][0] = mv_predictor[j][0];
674 s->
mv[0][0][1] = mv_predictor[j][1];
675
676 // predictor intra or otherwise not available
677 if (ref[j] < 0)
678 continue;
679
681
682 if (mb_x > 0 && fixed[mb_xy - 1]) {
683 int k;
684 for (k = 0; k < 16; k++)
687 }
688 if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) {
689 int k;
690 for (k = 0; k < 16; k++)
693 }
694 if (mb_y > 0 && fixed[mb_xy - mb_stride]) {
695 int k;
696 for (k = 0; k < 16; k++)
698 }
699 if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride]) {
700 int k;
701 for (k = 0; k < 16; k++)
704 }
705
706 if (score <= best_score) { // <= will favor the last MV
707 best_score = score;
708 best_pred = j;
709 }
710 }
711 score_sum += best_score;
712 s->
mv[0][0][0] = mv_predictor[best_pred][0];
713 s->
mv[0][0][1] = mv_predictor[best_pred][1];
714
715 for (i = 0; i < mot_step; i++)
716 for (j = 0; j < mot_step; j++) {
719 }
720
722
723
724 if (s->
mv[0][0][0] != prev_x || s->
mv[0][0][1] != prev_y) {
726 changed++;
727 } else
729 }
730 }
731 }
732
733 if (none_left)
734 return;
735
736 for (i = 0; i < s->
mb_num; i++) {
738 if (fixed[mb_xy])
740 }
741 }
742 }
743
745 {
746 int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
747
749 return 1; // no previous frame available -> use spatial prediction
750
751 undamaged_count = 0;
752 for (i = 0; i < s->
mb_num; i++) {
756 undamaged_count++;
757 }
758
763 return 1;
764 }
765
766 if (undamaged_count < 5)
767 return 0; // almost all MBs damaged -> use temporal prediction
768
769 // prevent dsp.sad() check, that requires access to the image
770 if (CONFIG_MPEG_XVMC_DECODER &&
773 return 1;
774
775 skip_amount =
FFMAX(undamaged_count / 50, 1);
// check only up to 50 MBs
776 is_intra_likely = 0;
777
778 j = 0;
779 for (mb_y = 0; mb_y < s->
mb_height - 1; mb_y++) {
780 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
781 int error;
782 const int mb_xy = mb_x + mb_y * s->
mb_stride;
783
786 continue; // skip damaged
787
788 j++;
789 // skip a few to speed things up
790 if ((j % skip_amount) != 0)
791 continue;
792
795 mb_x * 16 + mb_y * 16 * s->
linesize;
797 mb_x * 16 + mb_y * 16 * s->
linesize;
798
800 // FIXME
801 } else {
803 mb_y, 0);
804 }
806 // FIXME need await_progress() here
808 } else {
810 is_intra_likely++;
811 else
812 is_intra_likely--;
813 }
814 }
815 }
816 // printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
817 return is_intra_likely > 0;
818 }
819
821 {
823 return;
824
829 }
830
831 /**
832 * Add a slice.
833 * @param endx x component of the last macroblock, can be -1
834 * for the last of the previous line
835 * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is
836 * assumed that no earlier end or error of the same type occurred
837 */
839 int endx,
int endy,
int status)
840 {
841 const int start_i = av_clip(startx + starty * s->
mb_width, 0, s->
mb_num - 1);
842 const int end_i = av_clip(endx + endy * s->
mb_width, 0, s->
mb_num);
846
848 return;
849
850 if (start_i > end_i || start_xy > end_xy) {
852 "internal error, slice end before start\n");
853 return;
854 }
855
857 return;
858
863 }
867 }
871 }
872
876 }
877
878 if (mask == ~0x7F) {
880 (end_xy - start_xy) *
sizeof(
uint8_t));
881 } else {
882 int i;
883 for (i = start_xy; i < end_xy; i++)
885 }
886
889 else {
892 }
893
895
899
903 }
904 }
905
907 {
908 int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
910 int threshold_part[4] = { 100, 100, 100 };
911 int threshold = 50;
912 int is_intra_likely;
915
916 /* We do not support ER of field pictures yet,
917 * though it should not crash if enabled. */
924 return;
925 };
926
930 return;
931 }
932
935
936 for (i = 0; i < 2; i++) {
940 }
943 }
944
946 for (mb_y = 0; mb_y < s->
mb_height; mb_y++) {
947 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
949
951 }
953 }
954 }
955
956 #if 1
957 /* handle overlapping slices */
958 for (error_type = 1; error_type <= 3; error_type++) {
959 int end_ok = 0;
960
961 for (i = s->
mb_num - 1; i >= 0; i--) {
964
965 if (error & (1 << error_type))
966 end_ok = 1;
967 if (error & (8 << error_type))
968 end_ok = 1;
969
970 if (!end_ok)
972
974 end_ok = 0;
975 }
976 }
977 #endif
978 #if 1
979 /* handle slices with partitions of different length */
981 int end_ok = 0;
982
983 for (i = s->
mb_num - 1; i >= 0; i--) {
986
988 end_ok = 0;
992 end_ok = 1;
993
994 if (!end_ok)
996
998 end_ok = 0;
999 }
1000 }
1001 #endif
1002 /* handle missing slices */
1004 int end_ok = 1;
1005
1006 // FIXME + 100 hack
1011
1013 end_ok = 1;
1014
1019 // end & uninit
1020 end_ok = 0;
1021 }
1022
1023 if (!end_ok)
1025 }
1026 }
1027
1028 #if 1
1029 /* backward mark errors */
1030 distance = 9999999;
1031 for (error_type = 1; error_type <= 3; error_type++) {
1032 for (i = s->
mb_num - 1; i >= 0; i--) {
1035
1036 if (!s->
mbskip_table[mb_xy])
// FIXME partition specific
1037 distance++;
1038 if (error & (1 << error_type))
1039 distance = 0;
1040
1042 if (distance < threshold_part[error_type - 1])
1044 } else {
1045 if (distance < threshold)
1047 }
1048
1050 distance = 9999999;
1051 }
1052 }
1053 #endif
1054
1055 /* forward mark errors */
1056 error = 0;
1057 for (i = 0; i < s->
mb_num; i++) {
1060
1063 } else {
1066 }
1067 }
1068 #if 1
1069 /* handle not partitioned case */
1071 for (i = 0; i < s->
mb_num; i++) {
1077 }
1078 }
1079 #endif
1080
1081 dc_error = ac_error = mv_error = 0;
1082 for (i = 0; i < s->
mb_num; i++) {
1086 dc_error++;
1088 ac_error++;
1090 mv_error++;
1091 }
1094
1096
1097 /* set unknown mb-type to most likely */
1098 for (i = 0; i < s->
mb_num; i++) {
1102 continue;
1103
1104 if (is_intra_likely)
1106 else
1108 }
1109
1110 // change inter to intra blocks if no reference frames are available
1112 for (i = 0; i < s->
mb_num; i++) {
1116 }
1117
1118 /* handle inter blocks with damaged AC */
1119 for (mb_y = 0; mb_y < s->
mb_height; mb_y++) {
1120 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
1121 const int mb_xy = mb_x + mb_y * s->
mb_stride;
1124
1126
1128 continue; // intra
1130 continue; // inter with damaged MV
1132 continue; // undamaged inter
1133
1138 int mb_index = mb_x * 2 + mb_y * 2 * s->
b8_stride;
1139 int j;
1141 for (j = 0; j < 4; j++) {
1144 }
1145 } else {
1149 }
1150
1152
1155 decode_mb(s, 0
/* FIXME h264 partitioned slices need this set */);
1156 }
1157 }
1158
1159 /* guess MVs */
1161 for (mb_y = 0; mb_y < s->
mb_height; mb_y++) {
1162 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
1163 int xy = mb_x * 2 + mb_y * 2 * s->
b8_stride;
1164 const int mb_xy = mb_x + mb_y * s->
mb_stride;
1166
1168
1170 continue;
1172 continue; // inter with undamaged MV
1174 continue; // undamaged inter
1175
1184
1188
1190 // FIXME
1191 } else {
1193 }
1198 } else {
1203 }
1204
1209 }
1210 }
1211 } else
1213
1214 /* the filters below are not XvMC compatible, skip them */
1216 goto ec_clean;
1217 /* fill DC for inter blocks */
1218 for (mb_y = 0; mb_y < s->
mb_height; mb_y++) {
1219 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
1220 int dc, dcu, dcv, y, n;
1221 int16_t *dc_ptr;
1222 uint8_t *dest_y, *dest_cb, *dest_cr;
1223 const int mb_xy = mb_x + mb_y * s->
mb_stride;
1225
1227
1229 continue;
1230 // if (error & ER_MV_ERROR)
1231 // continue; // inter data damaged FIXME is this good?
1232
1236
1238 for (n = 0; n < 4; n++) {
1239 dc = 0;
1240 for (y = 0; y < 8; y++) {
1241 int x;
1242 for (x = 0; x < 8; x++)
1243 dc += dest_y[x + (n & 1) * 8 +
1245 }
1246 dc_ptr[(n & 1) + (n >> 1) * s->
b8_stride] = (dc + 4) >> 3;
1247 }
1248
1249 dcu = dcv = 0;
1250 for (y = 0; y < 8; y++) {
1251 int x;
1252 for (x = 0; x < 8; x++) {
1255 }
1256 }
1259 }
1260 }
1261 #if 1
1262 /* guess DC for damaged blocks */
1266 #endif
1267
1268 /* filter luma DC */
1270
1271 #if 1
1272 /* render DC only intra */
1273 for (mb_y = 0; mb_y < s->
mb_height; mb_y++) {
1274 for (mb_x = 0; mb_x < s->
mb_width; mb_x++) {
1275 uint8_t *dest_y, *dest_cb, *dest_cr;
1276 const int mb_xy = mb_x + mb_y * s->
mb_stride;
1278
1280
1282 continue;
1284 continue; // undamaged
1285
1289
1290 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1291 }
1292 }
1293 #endif
1294
1296 /* filter horizontal block boundaries */
1303
1304 /* filter vertical block boundaries */
1311 }
1312
1313 ec_clean:
1314 /* clean a few tables */
1315 for (i = 0; i < s->
mb_num; i++) {
1318
1322 }
1324 }
1325 }