c6eea3811ef84fb32601b471dd2d827dd5498993
[libav.git] / libavcodec / error_resilience.c
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 libavcodec/error_resilience.c
25 * Error resilience / concealment.
26 */
27
28 #include <limits.h>
29
30 #include "avcodec.h"
31 #include "dsputil.h"
32 #include "mpegvideo.h"
33 #include "h264.h"
34
35 /*
36 * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264)
37 * but error concealment must support both h264 and h263 thus we must undo this
38 */
39 #undef mb_intra
40
41 static void decode_mb(MpegEncContext *s, int ref){
42 s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16;
43 s->dest[1] = s->current_picture.data[1] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift);
44 s->dest[2] = s->current_picture.data[2] + (s->mb_y * (16>>s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16>>s->chroma_x_shift);
45
46 if(s->codec_id == CODEC_ID_H264){
47 H264Context *h= (void*)s;
48 h->mb_xy= s->mb_x + s->mb_y*s->mb_stride;
49 memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
50 assert(ref>=0);
51 if(ref >= h->ref_count[0]) //FIXME it is posible albeit uncommon that slice references differ between slices, we take the easy approuch and ignore it for now. If this turns out to have any relevance in practice then correct remapping should be added
52 ref=0;
53 fill_rectangle(&s->current_picture.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1);
54 fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
55 fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4);
56 assert(!FRAME_MBAFF);
57 ff_h264_hl_decode_mb(h);
58 }else{
59 assert(ref==0);
60 MPV_decode_mb(s, s->block);
61 }
62 }
63
64 /**
65 * @param stride the number of MVs to get to the next row
66 * @param mv_step the number of MVs per row or column in a macroblock
67 */
68 static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){
69 if(s->codec_id == CODEC_ID_H264){
70 H264Context *h= (void*)s;
71 assert(s->quarter_sample);
72 *mv_step= 4;
73 *stride= h->b_stride;
74 }else{
75 *mv_step= 2;
76 *stride= s->b8_stride;
77 }
78 }
79
80 /**
81 * replaces the current MB with a flat dc only version.
82 */
83 static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y)
84 {
85 int dc, dcu, dcv, y, i;
86 for(i=0; i<4; i++){
87 dc= s->dc_val[0][mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*s->b8_stride];
88 if(dc<0) dc=0;
89 else if(dc>2040) dc=2040;
90 for(y=0; y<8; y++){
91 int x;
92 for(x=0; x<8; x++){
93 dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8;
94 }
95 }
96 }
97 dcu = s->dc_val[1][mb_x + mb_y*s->mb_stride];
98 dcv = s->dc_val[2][mb_x + mb_y*s->mb_stride];
99 if (dcu<0 ) dcu=0;
100 else if(dcu>2040) dcu=2040;
101 if (dcv<0 ) dcv=0;
102 else if(dcv>2040) dcv=2040;
103 for(y=0; y<8; y++){
104 int x;
105 for(x=0; x<8; x++){
106 dest_cb[x + y*(s->uvlinesize)]= dcu/8;
107 dest_cr[x + y*(s->uvlinesize)]= dcv/8;
108 }
109 }
110 }
111
112 static void filter181(int16_t *data, int width, int height, int stride){
113 int x,y;
114
115 /* horizontal filter */
116 for(y=1; y<height-1; y++){
117 int prev_dc= data[0 + y*stride];
118
119 for(x=1; x<width-1; x++){
120 int dc;
121
122 dc= - prev_dc
123 + data[x + y*stride]*8
124 - data[x + 1 + y*stride];
125 dc= (dc*10923 + 32768)>>16;
126 prev_dc= data[x + y*stride];
127 data[x + y*stride]= dc;
128 }
129 }
130
131 /* vertical filter */
132 for(x=1; x<width-1; x++){
133 int prev_dc= data[x];
134
135 for(y=1; y<height-1; y++){
136 int dc;
137
138 dc= - prev_dc
139 + data[x + y *stride]*8
140 - data[x + (y+1)*stride];
141 dc= (dc*10923 + 32768)>>16;
142 prev_dc= data[x + y*stride];
143 data[x + y*stride]= dc;
144 }
145 }
146 }
147
148 /**
149 * guess the dc of blocks which do not have an undamaged dc
150 * @param w width in 8 pixel blocks
151 * @param h height in 8 pixel blocks
152 */
153 static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
154 int b_x, b_y;
155
156 for(b_y=0; b_y<h; b_y++){
157 for(b_x=0; b_x<w; b_x++){
158 int color[4]={1024,1024,1024,1024};
159 int distance[4]={9999,9999,9999,9999};
160 int mb_index, error, j;
161 int64_t guess, weight_sum;
162
163 mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
164
165 error= s->error_status_table[mb_index];
166
167 if(IS_INTER(s->current_picture.mb_type[mb_index])) continue; //inter
168 if(!(error&DC_ERROR)) continue; //dc-ok
169
170 /* right block */
171 for(j=b_x+1; j<w; j++){
172 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
173 int error_j= s->error_status_table[mb_index_j];
174 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
175 if(intra_j==0 || !(error_j&DC_ERROR)){
176 color[0]= dc[j + b_y*stride];
177 distance[0]= j-b_x;
178 break;
179 }
180 }
181
182 /* left block */
183 for(j=b_x-1; j>=0; j--){
184 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
185 int error_j= s->error_status_table[mb_index_j];
186 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
187 if(intra_j==0 || !(error_j&DC_ERROR)){
188 color[1]= dc[j + b_y*stride];
189 distance[1]= b_x-j;
190 break;
191 }
192 }
193
194 /* bottom block */
195 for(j=b_y+1; j<h; j++){
196 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
197 int error_j= s->error_status_table[mb_index_j];
198 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
199 if(intra_j==0 || !(error_j&DC_ERROR)){
200 color[2]= dc[b_x + j*stride];
201 distance[2]= j-b_y;
202 break;
203 }
204 }
205
206 /* top block */
207 for(j=b_y-1; j>=0; j--){
208 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
209 int error_j= s->error_status_table[mb_index_j];
210 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]);
211 if(intra_j==0 || !(error_j&DC_ERROR)){
212 color[3]= dc[b_x + j*stride];
213 distance[3]= b_y-j;
214 break;
215 }
216 }
217
218 weight_sum=0;
219 guess=0;
220 for(j=0; j<4; j++){
221 int64_t weight= 256*256*256*16/distance[j];
222 guess+= weight*(int64_t)color[j];
223 weight_sum+= weight;
224 }
225 guess= (guess + weight_sum/2) / weight_sum;
226
227 dc[b_x + b_y*stride]= guess;
228 }
229 }
230 }
231
232 /**
233 * simple horizontal deblocking filter used for error resilience
234 * @param w width in 8 pixel blocks
235 * @param h height in 8 pixel blocks
236 */
237 static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
238 int b_x, b_y, mvx_stride, mvy_stride;
239 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
240 set_mv_strides(s, &mvx_stride, &mvy_stride);
241 mvx_stride >>= is_luma;
242 mvy_stride *= mvx_stride;
243
244 for(b_y=0; b_y<h; b_y++){
245 for(b_x=0; b_x<w-1; b_x++){
246 int y;
247 int left_status = s->error_status_table[( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride];
248 int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride];
249 int left_intra= IS_INTRA(s->current_picture.mb_type [( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]);
250 int right_intra= IS_INTRA(s->current_picture.mb_type [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]);
251 int left_damage = left_status&(DC_ERROR|AC_ERROR|MV_ERROR);
252 int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR);
253 int offset= b_x*8 + b_y*stride*8;
254 int16_t *left_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride* b_x ];
255 int16_t *right_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride*(b_x+1)];
256
257 if(!(left_damage||right_damage)) continue; // both undamaged
258
259 if( (!left_intra) && (!right_intra)
260 && FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue;
261
262 for(y=0; y<8; y++){
263 int a,b,c,d;
264
265 a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride];
266 b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride];
267 c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride];
268
269 d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1);
270 d= FFMAX(d, 0);
271 if(b<0) d= -d;
272
273 if(d==0) continue;
274
275 if(!(left_damage && right_damage))
276 d= d*16/9;
277
278 if(left_damage){
279 dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)];
280 dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)];
281 dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)];
282 dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)];
283 }
284 if(right_damage){
285 dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)];
286 dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)];
287 dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)];
288 dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)];
289 }
290 }
291 }
292 }
293 }
294
295 /**
296 * simple vertical deblocking filter used for error resilience
297 * @param w width in 8 pixel blocks
298 * @param h height in 8 pixel blocks
299 */
300 static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){
301 int b_x, b_y, mvx_stride, mvy_stride;
302 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
303 set_mv_strides(s, &mvx_stride, &mvy_stride);
304 mvx_stride >>= is_luma;
305 mvy_stride *= mvx_stride;
306
307 for(b_y=0; b_y<h-1; b_y++){
308 for(b_x=0; b_x<w; b_x++){
309 int x;
310 int top_status = s->error_status_table[(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride];
311 int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride];
312 int top_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]);
313 int bottom_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]);
314 int top_damage = top_status&(DC_ERROR|AC_ERROR|MV_ERROR);
315 int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR);
316 int offset= b_x*8 + b_y*stride*8;
317 int16_t *top_mv= s->current_picture.motion_val[0][mvy_stride* b_y + mvx_stride*b_x];
318 int16_t *bottom_mv= s->current_picture.motion_val[0][mvy_stride*(b_y+1) + mvx_stride*b_x];
319
320 if(!(top_damage||bottom_damage)) continue; // both undamaged
321
322 if( (!top_intra) && (!bottom_intra)
323 && FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue;
324
325 for(x=0; x<8; x++){
326 int a,b,c,d;
327
328 a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride];
329 b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride];
330 c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride];
331
332 d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1);
333 d= FFMAX(d, 0);
334 if(b<0) d= -d;
335
336 if(d==0) continue;
337
338 if(!(top_damage && bottom_damage))
339 d= d*16/9;
340
341 if(top_damage){
342 dst[offset + x + 7*stride] = cm[dst[offset + x + 7*stride] + ((d*7)>>4)];
343 dst[offset + x + 6*stride] = cm[dst[offset + x + 6*stride] + ((d*5)>>4)];
344 dst[offset + x + 5*stride] = cm[dst[offset + x + 5*stride] + ((d*3)>>4)];
345 dst[offset + x + 4*stride] = cm[dst[offset + x + 4*stride] + ((d*1)>>4)];
346 }
347 if(bottom_damage){
348 dst[offset + x + 8*stride] = cm[dst[offset + x + 8*stride] - ((d*7)>>4)];
349 dst[offset + x + 9*stride] = cm[dst[offset + x + 9*stride] - ((d*5)>>4)];
350 dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)];
351 dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)];
352 }
353 }
354 }
355 }
356 }
357
358 static void guess_mv(MpegEncContext *s){
359 uint8_t fixed[s->mb_stride * s->mb_height];
360 #define MV_FROZEN 3
361 #define MV_CHANGED 2
362 #define MV_UNCHANGED 1
363 const int mb_stride = s->mb_stride;
364 const int mb_width = s->mb_width;
365 const int mb_height= s->mb_height;
366 int i, depth, num_avail;
367 int mb_x, mb_y, mot_step, mot_stride;
368
369 set_mv_strides(s, &mot_step, &mot_stride);
370
371 num_avail=0;
372 for(i=0; i<s->mb_num; i++){
373 const int mb_xy= s->mb_index2xy[ i ];
374 int f=0;
375 int error= s->error_status_table[mb_xy];
376
377 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check
378 if(!(error&MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV
379
380 fixed[mb_xy]= f;
381 if(f==MV_FROZEN)
382 num_avail++;
383 }
384
385 if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || 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
390 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) continue;
391 if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
392
393 s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
394 s->mb_intra=0;
395 s->mv_type = MV_TYPE_16X16;
396 s->mb_skipped=0;
397
398 s->dsp.clear_blocks(s->block[0]);
399
400 s->mb_x= mb_x;
401 s->mb_y= mb_y;
402 s->mv[0][0][0]= 0;
403 s->mv[0][0][1]= 0;
404 decode_mb(s, 0);
405 }
406 }
407 return;
408 }
409
410 for(depth=0;; depth++){
411 int changed, pass, none_left;
412
413 none_left=1;
414 changed=1;
415 for(pass=0; (changed || pass<2) && pass<10; pass++){
416 int mb_x, mb_y;
417 int score_sum=0;
418
419 changed=0;
420 for(mb_y=0; mb_y<s->mb_height; mb_y++){
421 for(mb_x=0; mb_x<s->mb_width; mb_x++){
422 const int mb_xy= mb_x + mb_y*s->mb_stride;
423 int mv_predictor[8][2]={{0}};
424 int ref[8]={0};
425 int pred_count=0;
426 int j;
427 int best_score=256*256*256*64;
428 int best_pred=0;
429 const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
430 int prev_x= s->current_picture.motion_val[0][mot_index][0];
431 int prev_y= s->current_picture.motion_val[0][mot_index][1];
432
433 if((mb_x^mb_y^pass)&1) continue;
434
435 if(fixed[mb_xy]==MV_FROZEN) continue;
436 assert(!IS_INTRA(s->current_picture.mb_type[mb_xy]));
437 assert(s->last_picture_ptr && s->last_picture_ptr->data[0]);
438
439 j=0;
440 if(mb_x>0 && fixed[mb_xy-1 ]==MV_FROZEN) j=1;
441 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_FROZEN) j=1;
442 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1;
443 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1;
444 if(j==0) continue;
445
446 j=0;
447 if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1;
448 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1;
449 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1;
450 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1;
451 if(j==0 && pass>1) continue;
452
453 none_left=0;
454
455 if(mb_x>0 && fixed[mb_xy-1]){
456 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0];
457 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1];
458 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-1)];
459 pred_count++;
460 }
461 if(mb_x+1<mb_width && fixed[mb_xy+1]){
462 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_step][0];
463 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1];
464 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+1)];
465 pred_count++;
466 }
467 if(mb_y>0 && fixed[mb_xy-mb_stride]){
468 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0];
469 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1];
470 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)];
471 pred_count++;
472 }
473 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
474 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][0];
475 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1];
476 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)];
477 pred_count++;
478 }
479 if(pred_count==0) continue;
480
481 if(pred_count>1){
482 int sum_x=0, sum_y=0, sum_r=0;
483 int max_x, max_y, min_x, min_y, max_r, min_r;
484
485 for(j=0; j<pred_count; j++){
486 sum_x+= mv_predictor[j][0];
487 sum_y+= mv_predictor[j][1];
488 sum_r+= ref[j];
489 if(j && ref[j] != ref[j-1])
490 goto skip_mean_and_median;
491 }
492
493 /* mean */
494 mv_predictor[pred_count][0] = sum_x/j;
495 mv_predictor[pred_count][1] = sum_y/j;
496 ref [pred_count] = sum_r/j;
497
498 /* median */
499 if(pred_count>=3){
500 min_y= min_x= min_r= 99999;
501 max_y= max_x= max_r=-99999;
502 }else{
503 min_x=min_y=max_x=max_y=min_r=max_r=0;
504 }
505 for(j=0; j<pred_count; j++){
506 max_x= FFMAX(max_x, mv_predictor[j][0]);
507 max_y= FFMAX(max_y, mv_predictor[j][1]);
508 max_r= FFMAX(max_r, ref[j]);
509 min_x= FFMIN(min_x, mv_predictor[j][0]);
510 min_y= FFMIN(min_y, mv_predictor[j][1]);
511 min_r= FFMIN(min_r, ref[j]);
512 }
513 mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
514 mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
515 ref [pred_count+1] = sum_r - max_r - min_r;
516
517 if(pred_count==4){
518 mv_predictor[pred_count+1][0] /= 2;
519 mv_predictor[pred_count+1][1] /= 2;
520 ref [pred_count+1] /= 2;
521 }
522 pred_count+=2;
523 }
524 skip_mean_and_median:
525
526 /* zero MV */
527 pred_count++;
528
529 /* last MV */
530 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0];
531 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1];
532 ref [pred_count] = s->current_picture.ref_index[0][4*mb_xy];
533 pred_count++;
534
535 s->mv_dir = MV_DIR_FORWARD;
536 s->mb_intra=0;
537 s->mv_type = MV_TYPE_16X16;
538 s->mb_skipped=0;
539
540 s->dsp.clear_blocks(s->block[0]);
541
542 s->mb_x= mb_x;
543 s->mb_y= mb_y;
544
545 for(j=0; j<pred_count; j++){
546 int score=0;
547 uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
548
549 s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
550 s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
551
552 if(ref[j]<0) //predictor intra or otherwise not available
553 continue;
554
555 decode_mb(s, ref[j]);
556
557 if(mb_x>0 && fixed[mb_xy-1]){
558 int k;
559 for(k=0; k<16; k++)
560 score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]);
561 }
562 if(mb_x+1<mb_width && fixed[mb_xy+1]){
563 int k;
564 for(k=0; k<16; k++)
565 score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
566 }
567 if(mb_y>0 && fixed[mb_xy-mb_stride]){
568 int k;
569 for(k=0; k<16; k++)
570 score += FFABS(src[k-s->linesize ]-src[k ]);
571 }
572 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
573 int k;
574 for(k=0; k<16; k++)
575 score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
576 }
577
578 if(score <= best_score){ // <= will favor the last MV
579 best_score= score;
580 best_pred= j;
581 }
582 }
583 score_sum+= best_score;
584 s->mv[0][0][0]= mv_predictor[best_pred][0];
585 s->mv[0][0][1]= mv_predictor[best_pred][1];
586
587 for(i=0; i<mot_step; i++)
588 for(j=0; j<mot_step; j++){
589 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0];
590 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1];
591 }
592
593 decode_mb(s, ref[best_pred]);
594
595
596 if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
597 fixed[mb_xy]=MV_CHANGED;
598 changed++;
599 }else
600 fixed[mb_xy]=MV_UNCHANGED;
601 }
602 }
603
604 // printf(".%d/%d", changed, score_sum); fflush(stdout);
605 }
606
607 if(none_left)
608 return;
609
610 for(i=0; i<s->mb_num; i++){
611 int mb_xy= s->mb_index2xy[i];
612 if(fixed[mb_xy])
613 fixed[mb_xy]=MV_FROZEN;
614 }
615 // printf(":"); fflush(stdout);
616 }
617 }
618
619 static int is_intra_more_likely(MpegEncContext *s){
620 int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
621
622 if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction
623
624 undamaged_count=0;
625 for(i=0; i<s->mb_num; i++){
626 const int mb_xy= s->mb_index2xy[i];
627 const int error= s->error_status_table[mb_xy];
628 if(!((error&DC_ERROR) && (error&MV_ERROR)))
629 undamaged_count++;
630 }
631
632 if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
633
634 //prevent dsp.sad() check, that requires access to the image
635 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE)
636 return 1;
637
638 skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
639 is_intra_likely=0;
640
641 j=0;
642 for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
643 for(mb_x= 0; mb_x<s->mb_width; mb_x++){
644 int error;
645 const int mb_xy= mb_x + mb_y*s->mb_stride;
646
647 error= s->error_status_table[mb_xy];
648 if((error&DC_ERROR) && (error&MV_ERROR))
649 continue; //skip damaged
650
651 j++;
652 if((j%skip_amount) != 0) continue; //skip a few to speed things up
653
654 if(s->pict_type==FF_I_TYPE){
655 uint8_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
656 uint8_t *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize;
657
658 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16);
659 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
660 }else{
661 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
662 is_intra_likely++;
663 else
664 is_intra_likely--;
665 }
666 }
667 }
668 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
669 return is_intra_likely > 0;
670 }
671
672 void ff_er_frame_start(MpegEncContext *s){
673 if(!s->error_recognition) return;
674
675 memset(s->error_status_table, MV_ERROR|AC_ERROR|DC_ERROR|VP_START|AC_END|DC_END|MV_END, s->mb_stride*s->mb_height*sizeof(uint8_t));
676 s->error_count= 3*s->mb_num;
677 }
678
679 /**
680 * adds a slice.
681 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
682 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
683 * error of the same type occurred
684 */
685 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
686 const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1);
687 const int end_i = av_clip(endx + endy * s->mb_width , 0, s->mb_num);
688 const int start_xy= s->mb_index2xy[start_i];
689 const int end_xy = s->mb_index2xy[end_i];
690 int mask= -1;
691
692 if(s->avctx->hwaccel)
693 return;
694
695 if(start_i > end_i || start_xy > end_xy){
696 av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
697 return;
698 }
699
700 if(!s->error_recognition) return;
701
702 mask &= ~VP_START;
703 if(status & (AC_ERROR|AC_END)){
704 mask &= ~(AC_ERROR|AC_END);
705 s->error_count -= end_i - start_i + 1;
706 }
707 if(status & (DC_ERROR|DC_END)){
708 mask &= ~(DC_ERROR|DC_END);
709 s->error_count -= end_i - start_i + 1;
710 }
711 if(status & (MV_ERROR|MV_END)){
712 mask &= ~(MV_ERROR|MV_END);
713 s->error_count -= end_i - start_i + 1;
714 }
715
716 if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
717
718 if(mask == ~0x7F){
719 memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
720 }else{
721 int i;
722 for(i=start_xy; i<end_xy; i++){
723 s->error_status_table[ i ] &= mask;
724 }
725 }
726
727 if(end_i == s->mb_num)
728 s->error_count= INT_MAX;
729 else{
730 s->error_status_table[end_xy] &= mask;
731 s->error_status_table[end_xy] |= status;
732 }
733
734 s->error_status_table[start_xy] |= VP_START;
735
736 if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
737 int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
738
739 prev_status &= ~ VP_START;
740 if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
741 }
742 }
743
744 void ff_er_frame_end(MpegEncContext *s){
745 int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
746 int distance;
747 int threshold_part[4]= {100,100,100};
748 int threshold= 50;
749 int is_intra_likely;
750 int size = s->b8_stride * 2 * s->mb_height;
751 Picture *pic= s->current_picture_ptr;
752
753 if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
754 s->avctx->hwaccel ||
755 s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
756 s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
757 s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
758
759 if(s->current_picture.motion_val[0] == NULL){
760 av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
761
762 for(i=0; i<2; i++){
763 pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
764 pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
765 pic->motion_val[i]= pic->motion_val_base[i]+4;
766 }
767 pic->motion_subsample_log2= 3;
768 s->current_picture= *s->current_picture_ptr;
769 }
770
771 if(s->avctx->debug&FF_DEBUG_ER){
772 for(mb_y=0; mb_y<s->mb_height; mb_y++){
773 for(mb_x=0; mb_x<s->mb_width; mb_x++){
774 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
775
776 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
777 }
778 av_log(s->avctx, AV_LOG_DEBUG, "\n");
779 }
780 }
781
782 #if 1
783 /* handle overlapping slices */
784 for(error_type=1; error_type<=3; error_type++){
785 int end_ok=0;
786
787 for(i=s->mb_num-1; i>=0; i--){
788 const int mb_xy= s->mb_index2xy[i];
789 int error= s->error_status_table[mb_xy];
790
791 if(error&(1<<error_type))
792 end_ok=1;
793 if(error&(8<<error_type))
794 end_ok=1;
795
796 if(!end_ok)
797 s->error_status_table[mb_xy]|= 1<<error_type;
798
799 if(error&VP_START)
800 end_ok=0;
801 }
802 }
803 #endif
804 #if 1
805 /* handle slices with partitions of different length */
806 if(s->partitioned_frame){
807 int end_ok=0;
808
809 for(i=s->mb_num-1; i>=0; i--){
810 const int mb_xy= s->mb_index2xy[i];
811 int error= s->error_status_table[mb_xy];
812
813 if(error&AC_END)
814 end_ok=0;
815 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
816 end_ok=1;
817
818 if(!end_ok)
819 s->error_status_table[mb_xy]|= AC_ERROR;
820
821 if(error&VP_START)
822 end_ok=0;
823 }
824 }
825 #endif
826 /* handle missing slices */
827 if(s->error_recognition>=4){
828 int end_ok=1;
829
830 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
831 const int mb_xy= s->mb_index2xy[i];
832 int error1= s->error_status_table[mb_xy ];
833 int error2= s->error_status_table[s->mb_index2xy[i+1]];
834
835 if(error1&VP_START)
836 end_ok=1;
837
838 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
839 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
840 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
841 end_ok=0;
842 }
843
844 if(!end_ok)
845 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
846 }
847 }
848
849 #if 1
850 /* backward mark errors */
851 distance=9999999;
852 for(error_type=1; error_type<=3; error_type++){
853 for(i=s->mb_num-1; i>=0; i--){
854 const int mb_xy= s->mb_index2xy[i];
855 int error= s->error_status_table[mb_xy];
856
857 if(!s->mbskip_table[mb_xy]) //FIXME partition specific
858 distance++;
859 if(error&(1<<error_type))
860 distance= 0;
861
862 if(s->partitioned_frame){
863 if(distance < threshold_part[error_type-1])
864 s->error_status_table[mb_xy]|= 1<<error_type;
865 }else{
866 if(distance < threshold)
867 s->error_status_table[mb_xy]|= 1<<error_type;
868 }
869
870 if(error&VP_START)
871 distance= 9999999;
872 }
873 }
874 #endif
875
876 /* forward mark errors */
877 error=0;
878 for(i=0; i<s->mb_num; i++){
879 const int mb_xy= s->mb_index2xy[i];
880 int old_error= s->error_status_table[mb_xy];
881
882 if(old_error&VP_START)
883 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
884 else{
885 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
886 s->error_status_table[mb_xy]|= error;
887 }
888 }
889 #if 1
890 /* handle not partitioned case */
891 if(!s->partitioned_frame){
892 for(i=0; i<s->mb_num; i++){
893 const int mb_xy= s->mb_index2xy[i];
894 error= s->error_status_table[mb_xy];
895 if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
896 error|= AC_ERROR|DC_ERROR|MV_ERROR;
897 s->error_status_table[mb_xy]= error;
898 }
899 }
900 #endif
901
902 dc_error= ac_error= mv_error=0;
903 for(i=0; i<s->mb_num; i++){
904 const int mb_xy= s->mb_index2xy[i];
905 error= s->error_status_table[mb_xy];
906 if(error&DC_ERROR) dc_error ++;
907 if(error&AC_ERROR) ac_error ++;
908 if(error&MV_ERROR) mv_error ++;
909 }
910 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
911
912 is_intra_likely= is_intra_more_likely(s);
913
914 /* set unknown mb-type to most likely */
915 for(i=0; i<s->mb_num; i++){
916 const int mb_xy= s->mb_index2xy[i];
917 error= s->error_status_table[mb_xy];
918 if(!((error&DC_ERROR) && (error&MV_ERROR)))
919 continue;
920
921 if(is_intra_likely)
922 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
923 else
924 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
925 }
926
927 // change inter to intra blocks if no reference frames are available
928 if (!s->last_picture.data[0] && !s->next_picture.data[0])
929 for(i=0; i<s->mb_num; i++){
930 const int mb_xy= s->mb_index2xy[i];
931 if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
932 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
933 }
934
935 /* handle inter blocks with damaged AC */
936 for(mb_y=0; mb_y<s->mb_height; mb_y++){
937 for(mb_x=0; mb_x<s->mb_width; mb_x++){
938 const int mb_xy= mb_x + mb_y * s->mb_stride;
939 const int mb_type= s->current_picture.mb_type[mb_xy];
940 int dir = !s->last_picture.data[0];
941 error= s->error_status_table[mb_xy];
942
943 if(IS_INTRA(mb_type)) continue; //intra
944 if(error&MV_ERROR) continue; //inter with damaged MV
945 if(!(error&AC_ERROR)) continue; //undamaged inter
946
947 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
948 s->mb_intra=0;
949 s->mb_skipped=0;
950 if(IS_8X8(mb_type)){
951 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
952 int j;
953 s->mv_type = MV_TYPE_8X8;
954 for(j=0; j<4; j++){
955 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
956 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
957 }
958 }else{
959 s->mv_type = MV_TYPE_16X16;
960 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
961 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
962 }
963
964 s->dsp.clear_blocks(s->block[0]);
965
966 s->mb_x= mb_x;
967 s->mb_y= mb_y;
968 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
969 }
970 }
971
972 /* guess MVs */
973 if(s->pict_type==FF_B_TYPE){
974 for(mb_y=0; mb_y<s->mb_height; mb_y++){
975 for(mb_x=0; mb_x<s->mb_width; mb_x++){
976 int xy= mb_x*2 + mb_y*2*s->b8_stride;
977 const int mb_xy= mb_x + mb_y * s->mb_stride;
978 const int mb_type= s->current_picture.mb_type[mb_xy];
979 error= s->error_status_table[mb_xy];
980
981 if(IS_INTRA(mb_type)) continue;
982 if(!(error&MV_ERROR)) continue; //inter with undamaged MV
983 if(!(error&AC_ERROR)) continue; //undamaged inter
984
985 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
986 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
987 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
988 s->mb_intra=0;
989 s->mv_type = MV_TYPE_16X16;
990 s->mb_skipped=0;
991
992 if(s->pp_time){
993 int time_pp= s->pp_time;
994 int time_pb= s->pb_time;
995
996 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
997 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
998 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
999 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1000 }else{
1001 s->mv[0][0][0]= 0;
1002 s->mv[0][0][1]= 0;
1003 s->mv[1][0][0]= 0;
1004 s->mv[1][0][1]= 0;
1005 }
1006
1007 s->dsp.clear_blocks(s->block[0]);
1008 s->mb_x= mb_x;
1009 s->mb_y= mb_y;
1010 decode_mb(s, 0);
1011 }
1012 }
1013 }else
1014 guess_mv(s);
1015
1016 /* the filters below are not XvMC compatible, skip them */
1017 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1018 goto ec_clean;
1019 /* fill DC for inter blocks */
1020 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1021 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1022 int dc, dcu, dcv, y, n;
1023 int16_t *dc_ptr;
1024 uint8_t *dest_y, *dest_cb, *dest_cr;
1025 const int mb_xy= mb_x + mb_y * s->mb_stride;
1026 const int mb_type= s->current_picture.mb_type[mb_xy];
1027
1028 error= s->error_status_table[mb_xy];
1029
1030 if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1031 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1032
1033 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1034 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1035 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1036
1037 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1038 for(n=0; n<4; n++){
1039 dc=0;
1040 for(y=0; y<8; y++){
1041 int x;
1042 for(x=0; x<8; x++){
1043 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1044 }
1045 }
1046 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1047 }
1048
1049 dcu=dcv=0;
1050 for(y=0; y<8; y++){
1051 int x;
1052 for(x=0; x<8; x++){
1053 dcu+=dest_cb[x + y*(s->uvlinesize)];
1054 dcv+=dest_cr[x + y*(s->uvlinesize)];
1055 }
1056 }
1057 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1058 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1059 }
1060 }
1061 #if 1
1062 /* guess DC for damaged blocks */
1063 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1064 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
1065 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
1066 #endif
1067 /* filter luma DC */
1068 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1069
1070 #if 1
1071 /* render DC only intra */
1072 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1073 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1074 uint8_t *dest_y, *dest_cb, *dest_cr;
1075 const int mb_xy= mb_x + mb_y * s->mb_stride;
1076 const int mb_type= s->current_picture.mb_type[mb_xy];
1077
1078 error= s->error_status_table[mb_xy];
1079
1080 if(IS_INTER(mb_type)) continue;
1081 if(!(error&AC_ERROR)) continue; //undamaged
1082
1083 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1084 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1085 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1086
1087 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1088 }
1089 }
1090 #endif
1091
1092 if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1093 /* filter horizontal block boundaries */
1094 h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1095 h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1096 h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1097
1098 /* filter vertical block boundaries */
1099 v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1100 v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1101 v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1102 }
1103
1104 ec_clean:
1105 /* clean a few tables */
1106 for(i=0; i<s->mb_num; i++){
1107 const int mb_xy= s->mb_index2xy[i];
1108 int error= s->error_status_table[mb_xy];
1109
1110 if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1111 s->mbskip_table[mb_xy]=0;
1112 }
1113 s->mbintra_table[mb_xy]=1;
1114 }
1115 }