Libav
error_resilience.c
Go to the documentation of this file.
1 /*
2  * Error resilience / concealment
3  *
4  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5  *
6  * This file is part of Libav.
7  *
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.
12  *
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.
17  *
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
21  */
22 
28 #include <limits.h>
29 
30 #include "libavutil/internal.h"
31 #include "avcodec.h"
32 #include "error_resilience.h"
33 #include "mpegvideo.h"
34 #include "rectangle.h"
35 #include "thread.h"
36 #include "version.h"
37 
42 static void set_mv_strides(ERContext *s, int *mv_step, int *stride)
43 {
44  if (s->avctx->codec_id == AV_CODEC_ID_H264) {
45  assert(s->quarter_sample);
46  *mv_step = 4;
47  *stride = s->mb_width * 4;
48  } else {
49  *mv_step = 2;
50  *stride = s->b8_stride;
51  }
52 }
53 
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)
59 {
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];
64  if (dc < 0)
65  dc = 0;
66  else if (dc > 2040)
67  dc = 2040;
68  for (y = 0; y < 8; y++) {
69  int x;
70  for (x = 0; x < 8; x++)
71  dest_y[x + (i & 1) * 8 + (y + (i >> 1) * 8) * linesize[0]] = dc / 8;
72  }
73  }
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];
76  if (dcu < 0)
77  dcu = 0;
78  else if (dcu > 2040)
79  dcu = 2040;
80  if (dcv < 0)
81  dcv = 0;
82  else if (dcv > 2040)
83  dcv = 2040;
84  for (y = 0; y < 8; y++) {
85  int x;
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;
89  }
90  }
91 }
92 
93 static void filter181(int16_t *data, int width, int height, int stride)
94 {
95  int x, y;
96 
97  /* horizontal filter */
98  for (y = 1; y < height - 1; y++) {
99  int prev_dc = data[0 + y * stride];
100 
101  for (x = 1; x < width - 1; x++) {
102  int dc;
103  dc = -prev_dc +
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;
109  }
110  }
111 
112  /* vertical filter */
113  for (x = 1; x < width - 1; x++) {
114  int prev_dc = data[x];
115 
116  for (y = 1; y < height - 1; y++) {
117  int dc;
118 
119  dc = -prev_dc +
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;
125  }
126  }
127 }
128 
134 static void guess_dc(ERContext *s, int16_t *dc, int w,
135  int h, int stride, int is_luma)
136 {
137  int b_x, b_y;
138 
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];
147 
148  if (IS_INTER(s->cur_pic->mb_type[mb_index]))
149  continue; // inter
150  if (!(error & ER_DC_ERROR))
151  continue; // dc-ok
152 
153  /* right block */
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;
161  break;
162  }
163  }
164 
165  /* left block */
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;
173  break;
174  }
175  }
176 
177  /* bottom block */
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]);
182 
183  if (intra_j == 0 || !(error_j & ER_DC_ERROR)) {
184  color[2] = dc[b_x + j * stride];
185  distance[2] = j - b_y;
186  break;
187  }
188  }
189 
190  /* top block */
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;
198  break;
199  }
200  }
201 
202  weight_sum = 0;
203  guess = 0;
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;
208  }
209  guess = (guess + weight_sum / 2) / weight_sum;
210  dc[b_x + b_y * stride] = guess;
211  }
212  }
213 }
214 
220 static void h_block_filter(ERContext *s, uint8_t *dst, int w,
221  int h, int stride, int is_luma)
222 {
223  int b_x, b_y, mvx_stride, mvy_stride;
224  const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
225  set_mv_strides(s, &mvx_stride, &mvy_stride);
226  mvx_stride >>= is_luma;
227  mvy_stride *= mvx_stride;
228 
229  for (b_y = 0; b_y < h; b_y++) {
230  for (b_x = 0; b_x < w - 1; b_x++) {
231  int y;
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)
246  continue;
247 
248  for (y = 0; y < 8; y++) {
249  int a, b, c, d;
250 
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];
254 
255  d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1);
256  d = FFMAX(d, 0);
257  if (b < 0)
258  d = -d;
259 
260  if (d == 0)
261  continue;
262 
263  if (!(left_damage && right_damage))
264  d = d * 16 / 9;
265 
266  if (left_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)];
271  }
272  if (right_damage) {
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)];
277  }
278  }
279  }
280  }
281 }
282 
288 static void v_block_filter(ERContext *s, uint8_t *dst, int w, int h,
289  int stride, int is_luma)
290 {
291  int b_x, b_y, mvx_stride, mvy_stride;
292  const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
293  set_mv_strides(s, &mvx_stride, &mvy_stride);
294  mvx_stride >>= is_luma;
295  mvy_stride *= mvx_stride;
296 
297  for (b_y = 0; b_y < h - 1; b_y++) {
298  for (b_x = 0; b_x < w; b_x++) {
299  int 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;
307 
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];
310 
311  if (!(top_damage || bottom_damage))
312  continue; // both undamaged
313 
314  if ((!top_intra) && (!bottom_intra) &&
315  FFABS(top_mv[0] - bottom_mv[0]) +
316  FFABS(top_mv[1] + bottom_mv[1]) < 2)
317  continue;
318 
319  for (x = 0; x < 8; x++) {
320  int a, b, c, d;
321 
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];
325 
326  d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1);
327  d = FFMAX(d, 0);
328  if (b < 0)
329  d = -d;
330 
331  if (d == 0)
332  continue;
333 
334  if (!(top_damage && bottom_damage))
335  d = d * 16 / 9;
336 
337  if (top_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)];
342  }
343  if (bottom_damage) {
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)];
348  }
349  }
350  }
351  }
352 }
353 
354 static void guess_mv(ERContext *s)
355 {
356  uint8_t *fixed = s->er_temp_buffer;
357 #define MV_FROZEN 3
358 #define MV_CHANGED 2
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;
365 
366  set_mv_strides(s, &mot_step, &mot_stride);
367 
368  num_avail = 0;
369  for (i = 0; i < s->mb_num; i++) {
370  const int mb_xy = s->mb_index2xy[i];
371  int f = 0;
372  int error = s->error_status_table[mb_xy];
373 
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
378 
379  fixed[mb_xy] = f;
380  if (f == MV_FROZEN)
381  num_avail++;
382  }
383 
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;
390 
391  if (IS_INTRA(s->cur_pic->mb_type[mb_xy]))
392  continue;
393  if (!(s->error_status_table[mb_xy] & ER_MV_ERROR))
394  continue;
395 
396  s->mv[0][0][0] = 0;
397  s->mv[0][0][1] = 0;
398  s->decode_mb(s->opaque, 0, mv_dir, MV_TYPE_16X16, &s->mv,
399  mb_x, mb_y, 0, 0);
400  }
401  }
402  return;
403  }
404 
405  for (depth = 0; ; depth++) {
406  int changed, pass, none_left;
407 
408  none_left = 1;
409  changed = 1;
410  for (pass = 0; (changed || pass < 2) && pass < 10; pass++) {
411  int mb_x, mb_y;
412  int score_sum = 0;
413 
414  changed = 0;
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 } };
419  int ref[8] = { 0 };
420  int pred_count = 0;
421  int j;
422  int best_score = 256 * 256 * 256 * 64;
423  int best_pred = 0;
424  const int mot_index = (mb_x + mb_y * mot_stride) * mot_step;
425  int prev_x, prev_y, prev_ref;
426 
427  if ((mb_x ^ mb_y ^ pass) & 1)
428  continue;
429 
430  if (fixed[mb_xy] == MV_FROZEN)
431  continue;
432  assert(!IS_INTRA(s->cur_pic->mb_type[mb_xy]));
433  assert(s->last_pic && s->last_pic->f.data[0]);
434 
435  j = 0;
436  if (mb_x > 0 && fixed[mb_xy - 1] == MV_FROZEN)
437  j = 1;
438  if (mb_x + 1 < mb_width && fixed[mb_xy + 1] == MV_FROZEN)
439  j = 1;
440  if (mb_y > 0 && fixed[mb_xy - mb_stride] == MV_FROZEN)
441  j = 1;
442  if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] == MV_FROZEN)
443  j = 1;
444  if (j == 0)
445  continue;
446 
447  j = 0;
448  if (mb_x > 0 && fixed[mb_xy - 1 ] == MV_CHANGED)
449  j = 1;
450  if (mb_x + 1 < mb_width && fixed[mb_xy + 1 ] == MV_CHANGED)
451  j = 1;
452  if (mb_y > 0 && fixed[mb_xy - mb_stride] == MV_CHANGED)
453  j = 1;
454  if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] == MV_CHANGED)
455  j = 1;
456  if (j == 0 && pass > 1)
457  continue;
458 
459  none_left = 0;
460 
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];
466  ref[pred_count] =
467  s->cur_pic->ref_index[0][4 * (mb_xy - 1)];
468  pred_count++;
469  }
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];
475  ref[pred_count] =
476  s->cur_pic->ref_index[0][4 * (mb_xy + 1)];
477  pred_count++;
478  }
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];
484  ref[pred_count] =
485  s->cur_pic->ref_index[0][4 * (mb_xy - s->mb_stride)];
486  pred_count++;
487  }
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];
493  ref[pred_count] =
494  s->cur_pic->ref_index[0][4 * (mb_xy + s->mb_stride)];
495  pred_count++;
496  }
497  if (pred_count == 0)
498  continue;
499 
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;
503 
504  for (j = 0; j < pred_count; j++) {
505  sum_x += mv_predictor[j][0];
506  sum_y += mv_predictor[j][1];
507  sum_r += ref[j];
508  if (j && ref[j] != ref[j - 1])
509  goto skip_mean_and_median;
510  }
511 
512  /* mean */
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;
516 
517  /* median */
518  if (pred_count >= 3) {
519  min_y = min_x = min_r = 99999;
520  max_y = max_x = max_r = -99999;
521  } else {
522  min_x = min_y = max_x = max_y = min_r = max_r = 0;
523  }
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]);
531  }
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;
535 
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;
540  }
541  pred_count += 2;
542  }
543 
544 skip_mean_and_median:
545  /* zero MV */
546  pred_count++;
547 
548  if (!fixed[mb_xy]) {
549  if (s->avctx->codec_id == AV_CODEC_ID_H264) {
550  // FIXME
551  } else {
553  mb_y, 0);
554  }
555  if (!s->last_pic->motion_val[0] ||
556  !s->last_pic->ref_index[0])
557  goto skip_last_mv;
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];
561  } else {
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];
565  }
566 
567  /* last MV */
568  mv_predictor[pred_count][0] = prev_x;
569  mv_predictor[pred_count][1] = prev_y;
570  ref[pred_count] = prev_ref;
571  pred_count++;
572 
573 skip_last_mv:
574 
575  for (j = 0; j < pred_count; j++) {
576  int *linesize = s->cur_pic->f.linesize;
577  int score = 0;
578  uint8_t *src = s->cur_pic->f.data[0] +
579  mb_x * 16 + mb_y * 16 * linesize[0];
580 
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];
585 
586  // predictor intra or otherwise not available
587  if (ref[j] < 0)
588  continue;
589 
590  s->decode_mb(s->opaque, ref[j], MV_DIR_FORWARD,
591  MV_TYPE_16X16, &s->mv, mb_x, mb_y, 0, 0);
592 
593  if (mb_x > 0 && fixed[mb_xy - 1]) {
594  int k;
595  for (k = 0; k < 16; k++)
596  score += FFABS(src[k * linesize[0] - 1] -
597  src[k * linesize[0]]);
598  }
599  if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) {
600  int k;
601  for (k = 0; k < 16; k++)
602  score += FFABS(src[k * linesize[0] + 15] -
603  src[k * linesize[0] + 16]);
604  }
605  if (mb_y > 0 && fixed[mb_xy - mb_stride]) {
606  int k;
607  for (k = 0; k < 16; k++)
608  score += FFABS(src[k - linesize[0]] - src[k]);
609  }
610  if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride]) {
611  int k;
612  for (k = 0; k < 16; k++)
613  score += FFABS(src[k + linesize[0] * 15] -
614  src[k + linesize[0] * 16]);
615  }
616 
617  if (score <= best_score) { // <= will favor the last MV
618  best_score = score;
619  best_pred = j;
620  }
621  }
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];
625 
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];
630  }
631 
632  s->decode_mb(s->opaque, ref[best_pred], MV_DIR_FORWARD,
633  MV_TYPE_16X16, &s->mv, mb_x, mb_y, 0, 0);
634 
635 
636  if (s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y) {
637  fixed[mb_xy] = MV_CHANGED;
638  changed++;
639  } else
640  fixed[mb_xy] = MV_UNCHANGED;
641  }
642  }
643  }
644 
645  if (none_left)
646  return;
647 
648  for (i = 0; i < s->mb_num; i++) {
649  int mb_xy = s->mb_index2xy[i];
650  if (fixed[mb_xy])
651  fixed[mb_xy] = MV_FROZEN;
652  }
653  }
654 }
655 
657 {
658  int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
659 
660  if (!s->last_pic || !s->last_pic->f.data[0])
661  return 1; // no previous frame available -> use spatial prediction
662 
663  undamaged_count = 0;
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)))
668  undamaged_count++;
669  }
670 
671  if (s->avctx->codec_id == AV_CODEC_ID_H264 && s->ref_count <= 0)
672  return 1;
673 
674  if (undamaged_count < 5)
675  return 0; // almost all MBs damaged -> use temporal prediction
676 
677 #if FF_API_XVMC
679  // prevent dsp.sad() check, that requires access to the image
681  s->avctx->xvmc_acceleration &&
683  return 1;
685 #endif /* FF_API_XVMC */
686 
687  skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs
688  is_intra_likely = 0;
689 
690  j = 0;
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++) {
693  int error;
694  const int mb_xy = mb_x + mb_y * s->mb_stride;
695 
696  error = s->error_status_table[mb_xy];
697  if ((error & ER_DC_ERROR) && (error & ER_MV_ERROR))
698  continue; // skip damaged
699 
700  j++;
701  // skip a few to speed things up
702  if ((j % skip_amount) != 0)
703  continue;
704 
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];
711 
712  if (s->avctx->codec_id == AV_CODEC_ID_H264) {
713  // FIXME
714  } else {
715  ff_thread_await_progress(&s->last_pic->tf, mb_y, 0);
716  }
717  is_intra_likely += s->dsp->sad[0](NULL, last_mb_ptr, mb_ptr,
718  linesize[0], 16);
719  is_intra_likely -= s->dsp->sad[0](NULL, last_mb_ptr,
720  last_mb_ptr + linesize[0] * 16,
721  linesize[0], 16);
722  } else {
723  if (IS_INTRA(s->cur_pic->mb_type[mb_xy]))
724  is_intra_likely++;
725  else
726  is_intra_likely--;
727  }
728  }
729  }
730  return is_intra_likely > 0;
731 }
732 
734 {
735  if (!s->avctx->error_concealment)
736  return;
737 
739  s->mb_stride * s->mb_height * sizeof(uint8_t));
740  s->error_count = 3 * s->mb_num;
741  s->error_occurred = 0;
742 }
743 
751 void ff_er_add_slice(ERContext *s, int startx, int starty,
752  int endx, int endy, int status)
753 {
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];
758  int mask = -1;
759 
760  if (s->avctx->hwaccel)
761  return;
762 
763  if (start_i > end_i || start_xy > end_xy) {
765  "internal error, slice end before start\n");
766  return;
767  }
768 
769  if (!s->avctx->error_concealment)
770  return;
771 
772  mask &= ~VP_START;
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;
776  }
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;
780  }
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;
784  }
785 
786  if (status & ER_MB_ERROR) {
787  s->error_occurred = 1;
788  s->error_count = INT_MAX;
789  }
790 
791  if (mask == ~0x7F) {
792  memset(&s->error_status_table[start_xy], 0,
793  (end_xy - start_xy) * sizeof(uint8_t));
794  } else {
795  int i;
796  for (i = start_xy; i < end_xy; i++)
797  s->error_status_table[i] &= mask;
798  }
799 
800  if (end_i == s->mb_num)
801  s->error_count = INT_MAX;
802  else {
803  s->error_status_table[end_xy] &= mask;
804  s->error_status_table[end_xy] |= status;
805  }
806 
807  s->error_status_table[start_xy] |= VP_START;
808 
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]];
812 
813  prev_status &= ~ VP_START;
814  if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END))
815  s->error_count = INT_MAX;
816  }
817 }
818 
820 {
821  int *linesize = s->cur_pic->f.linesize;
822  int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
823  int distance;
824  int threshold_part[4] = { 100, 100, 100 };
825  int threshold = 50;
826  int is_intra_likely;
827  int size = s->b8_stride * 2 * s->mb_height;
828 
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 ||
832  s->avctx->hwaccel ||
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)) {
836  return;
837  };
838 
839  if (s->cur_pic->motion_val[0] == NULL) {
840  av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
841 
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])
846  break;
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;
849  }
850  if (i < 2) {
851  for (i = 0; i < 2; i++) {
854  s->cur_pic->ref_index[i] = NULL;
855  s->cur_pic->motion_val[i] = NULL;
856  }
857  return;
858  }
859  }
860 
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];
865 
866  av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
867  }
868  av_log(s->avctx, AV_LOG_DEBUG, "\n");
869  }
870  }
871 
872  /* handle overlapping slices */
873  for (error_type = 1; error_type <= 3; error_type++) {
874  int end_ok = 0;
875 
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];
879 
880  if (error & (1 << error_type))
881  end_ok = 1;
882  if (error & (8 << error_type))
883  end_ok = 1;
884 
885  if (!end_ok)
886  s->error_status_table[mb_xy] |= 1 << error_type;
887 
888  if (error & VP_START)
889  end_ok = 0;
890  }
891  }
892 
893  /* handle slices with partitions of different length */
894  if (s->partitioned_frame) {
895  int end_ok = 0;
896 
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];
900 
901  if (error & ER_AC_END)
902  end_ok = 0;
903  if ((error & ER_MV_END) ||
904  (error & ER_DC_END) ||
905  (error & ER_AC_ERROR))
906  end_ok = 1;
907 
908  if (!end_ok)
909  s->error_status_table[mb_xy]|= ER_AC_ERROR;
910 
911  if (error & VP_START)
912  end_ok = 0;
913  }
914  }
915 
916  /* handle missing slices */
917  if (s->avctx->err_recognition & AV_EF_EXPLODE) {
918  int end_ok = 1;
919 
920  // FIXME + 100 hack
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]];
925 
926  if (error1 & VP_START)
927  end_ok = 1;
928 
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))) {
933  // end & uninit
934  end_ok = 0;
935  }
936 
937  if (!end_ok)
938  s->error_status_table[mb_xy] |= ER_MB_ERROR;
939  }
940  }
941 
942  /* backward mark errors */
943  distance = 9999999;
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];
948 
949  if (!s->mbskip_table[mb_xy]) // FIXME partition specific
950  distance++;
951  if (error & (1 << error_type))
952  distance = 0;
953 
954  if (s->partitioned_frame) {
955  if (distance < threshold_part[error_type - 1])
956  s->error_status_table[mb_xy] |= 1 << error_type;
957  } else {
958  if (distance < threshold)
959  s->error_status_table[mb_xy] |= 1 << error_type;
960  }
961 
962  if (error & VP_START)
963  distance = 9999999;
964  }
965  }
966 
967  /* forward mark errors */
968  error = 0;
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];
972 
973  if (old_error & VP_START) {
974  error = old_error & ER_MB_ERROR;
975  } else {
976  error |= old_error & ER_MB_ERROR;
977  s->error_status_table[mb_xy] |= error;
978  }
979  }
980 
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;
989  }
990  }
991 
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)
997  dc_error++;
998  if (error & ER_AC_ERROR)
999  ac_error++;
1000  if (error & ER_MV_ERROR)
1001  mv_error++;
1002  }
1003  av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n",
1004  dc_error, ac_error, mv_error);
1005 
1006  is_intra_likely = is_intra_more_likely(s);
1007 
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)))
1013  continue;
1014 
1015  if (is_intra_likely)
1016  s->cur_pic->mb_type[mb_xy] = MB_TYPE_INTRA4x4;
1017  else
1018  s->cur_pic->mb_type[mb_xy] = MB_TYPE_16x16 | MB_TYPE_L0;
1019  }
1020 
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;
1028  }
1029 
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;
1037  int mv_type;
1038 
1039  error = s->error_status_table[mb_xy];
1040 
1041  if (IS_INTRA(mb_type))
1042  continue; // intra
1043  if (error & ER_MV_ERROR)
1044  continue; // inter with damaged MV
1045  if (!(error & ER_AC_ERROR))
1046  continue; // undamaged inter
1047 
1048  if (IS_8X8(mb_type)) {
1049  int mb_index = mb_x * 2 + mb_y * 2 * s->b8_stride;
1050  int j;
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];
1055  }
1056  } else {
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];
1060  }
1061 
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);
1064  }
1065  }
1066 
1067  /* guess MVs */
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;
1075 
1076  error = s->error_status_table[mb_xy];
1077 
1078  if (IS_INTRA(mb_type))
1079  continue;
1080  if (!(error & ER_MV_ERROR))
1081  continue; // inter with undamaged MV
1082  if (!(error & ER_AC_ERROR))
1083  continue; // undamaged inter
1084 
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;
1089 
1090  if (s->pp_time) {
1091  int time_pp = s->pp_time;
1092  int time_pb = s->pb_time;
1093 
1094  ff_thread_await_progress(&s->next_pic->tf, mb_y, 0);
1095 
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;
1100  } else {
1101  s->mv[0][0][0] = 0;
1102  s->mv[0][0][1] = 0;
1103  s->mv[1][0][0] = 0;
1104  s->mv[1][0][1] = 0;
1105  }
1106 
1107  s->decode_mb(s->opaque, 0, mv_dir, MV_TYPE_16X16, &s->mv,
1108  mb_x, mb_y, 0, 0);
1109  }
1110  }
1111  } else
1112  guess_mv(s);
1113 
1114 #if FF_API_XVMC
1116  /* the filters below are not XvMC compatible, skip them */
1117  if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1118  goto ec_clean;
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;
1125  int16_t *dc_ptr;
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];
1129 
1130  error = s->error_status_table[mb_xy];
1131 
1132  if (IS_INTRA(mb_type) && s->partitioned_frame)
1133  continue;
1134  // if (error & ER_MV_ERROR)
1135  // continue; // inter data damaged FIXME is this good?
1136 
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];
1140 
1141  dc_ptr = &s->dc_val[0][mb_x * 2 + mb_y * 2 * s->b8_stride];
1142  for (n = 0; n < 4; n++) {
1143  dc = 0;
1144  for (y = 0; y < 8; y++) {
1145  int x;
1146  for (x = 0; x < 8; x++)
1147  dc += dest_y[x + (n & 1) * 8 +
1148  (y + (n >> 1) * 8) * linesize[0]];
1149  }
1150  dc_ptr[(n & 1) + (n >> 1) * s->b8_stride] = (dc + 4) >> 3;
1151  }
1152 
1153  dcu = dcv = 0;
1154  for (y = 0; y < 8; y++) {
1155  int x;
1156  for (x = 0; x < 8; x++) {
1157  dcu += dest_cb[x + y * linesize[1]];
1158  dcv += dest_cr[x + y * linesize[2]];
1159  }
1160  }
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;
1163  }
1164  }
1165 
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);
1170 
1171  /* filter luma DC */
1172  filter181(s->dc_val[0], s->mb_width * 2, s->mb_height * 2, s->b8_stride);
1173 
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];
1180 
1181  error = s->error_status_table[mb_xy];
1182 
1183  if (IS_INTER(mb_type))
1184  continue;
1185  if (!(error & ER_AC_ERROR))
1186  continue; // undamaged
1187 
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];
1191 
1192  put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1193  }
1194  }
1195 
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);
1204 
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);
1212  }
1213 
1214 ec_clean:
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];
1219 
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;
1223  }
1224  s->mbintra_table[mb_xy] = 1;
1225  }
1226  s->cur_pic = NULL;
1227  s->next_pic = NULL;
1228  s->last_pic = NULL;
1229 }