a7ae0438cdcd6c7e29664363a943fbc5d3aa5d38
[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(CONFIG_H264_DECODER && 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(s->codec_id == CODEC_ID_H264){
633 H264Context *h= (void*)s;
634 if(h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0])
635 return 1;
636 }
637
638 if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
639
640 //prevent dsp.sad() check, that requires access to the image
641 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE)
642 return 1;
643
644 skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
645 is_intra_likely=0;
646
647 j=0;
648 for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
649 for(mb_x= 0; mb_x<s->mb_width; mb_x++){
650 int error;
651 const int mb_xy= mb_x + mb_y*s->mb_stride;
652
653 error= s->error_status_table[mb_xy];
654 if((error&DC_ERROR) && (error&MV_ERROR))
655 continue; //skip damaged
656
657 j++;
658 if((j%skip_amount) != 0) continue; //skip a few to speed things up
659
660 if(s->pict_type==FF_I_TYPE){
661 uint8_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
662 uint8_t *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize;
663
664 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16);
665 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
666 }else{
667 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
668 is_intra_likely++;
669 else
670 is_intra_likely--;
671 }
672 }
673 }
674 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
675 return is_intra_likely > 0;
676 }
677
678 void ff_er_frame_start(MpegEncContext *s){
679 if(!s->error_recognition) return;
680
681 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));
682 s->error_count= 3*s->mb_num;
683 }
684
685 /**
686 * adds a slice.
687 * @param endx x component of the last macroblock, can be -1 for the last of the previous line
688 * @param status the status at the end (MV_END, AC_ERROR, ...), it is assumed that no earlier end or
689 * error of the same type occurred
690 */
691 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
692 const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1);
693 const int end_i = av_clip(endx + endy * s->mb_width , 0, s->mb_num);
694 const int start_xy= s->mb_index2xy[start_i];
695 const int end_xy = s->mb_index2xy[end_i];
696 int mask= -1;
697
698 if(s->avctx->hwaccel)
699 return;
700
701 if(start_i > end_i || start_xy > end_xy){
702 av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
703 return;
704 }
705
706 if(!s->error_recognition) return;
707
708 mask &= ~VP_START;
709 if(status & (AC_ERROR|AC_END)){
710 mask &= ~(AC_ERROR|AC_END);
711 s->error_count -= end_i - start_i + 1;
712 }
713 if(status & (DC_ERROR|DC_END)){
714 mask &= ~(DC_ERROR|DC_END);
715 s->error_count -= end_i - start_i + 1;
716 }
717 if(status & (MV_ERROR|MV_END)){
718 mask &= ~(MV_ERROR|MV_END);
719 s->error_count -= end_i - start_i + 1;
720 }
721
722 if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX;
723
724 if(mask == ~0x7F){
725 memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
726 }else{
727 int i;
728 for(i=start_xy; i<end_xy; i++){
729 s->error_status_table[ i ] &= mask;
730 }
731 }
732
733 if(end_i == s->mb_num)
734 s->error_count= INT_MAX;
735 else{
736 s->error_status_table[end_xy] &= mask;
737 s->error_status_table[end_xy] |= status;
738 }
739
740 s->error_status_table[start_xy] |= VP_START;
741
742 if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
743 int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
744
745 prev_status &= ~ VP_START;
746 if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
747 }
748 }
749
750 void ff_er_frame_end(MpegEncContext *s){
751 int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
752 int distance;
753 int threshold_part[4]= {100,100,100};
754 int threshold= 50;
755 int is_intra_likely;
756 int size = s->b8_stride * 2 * s->mb_height;
757 Picture *pic= s->current_picture_ptr;
758
759 if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
760 s->avctx->hwaccel ||
761 s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
762 s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
763 s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
764
765 if(s->current_picture.motion_val[0] == NULL){
766 av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
767
768 for(i=0; i<2; i++){
769 pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
770 pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
771 pic->motion_val[i]= pic->motion_val_base[i]+4;
772 }
773 pic->motion_subsample_log2= 3;
774 s->current_picture= *s->current_picture_ptr;
775 }
776
777 if(s->avctx->debug&FF_DEBUG_ER){
778 for(mb_y=0; mb_y<s->mb_height; mb_y++){
779 for(mb_x=0; mb_x<s->mb_width; mb_x++){
780 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
781
782 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
783 }
784 av_log(s->avctx, AV_LOG_DEBUG, "\n");
785 }
786 }
787
788 #if 1
789 /* handle overlapping slices */
790 for(error_type=1; error_type<=3; error_type++){
791 int end_ok=0;
792
793 for(i=s->mb_num-1; i>=0; i--){
794 const int mb_xy= s->mb_index2xy[i];
795 int error= s->error_status_table[mb_xy];
796
797 if(error&(1<<error_type))
798 end_ok=1;
799 if(error&(8<<error_type))
800 end_ok=1;
801
802 if(!end_ok)
803 s->error_status_table[mb_xy]|= 1<<error_type;
804
805 if(error&VP_START)
806 end_ok=0;
807 }
808 }
809 #endif
810 #if 1
811 /* handle slices with partitions of different length */
812 if(s->partitioned_frame){
813 int end_ok=0;
814
815 for(i=s->mb_num-1; i>=0; i--){
816 const int mb_xy= s->mb_index2xy[i];
817 int error= s->error_status_table[mb_xy];
818
819 if(error&AC_END)
820 end_ok=0;
821 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
822 end_ok=1;
823
824 if(!end_ok)
825 s->error_status_table[mb_xy]|= AC_ERROR;
826
827 if(error&VP_START)
828 end_ok=0;
829 }
830 }
831 #endif
832 /* handle missing slices */
833 if(s->error_recognition>=4){
834 int end_ok=1;
835
836 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
837 const int mb_xy= s->mb_index2xy[i];
838 int error1= s->error_status_table[mb_xy ];
839 int error2= s->error_status_table[s->mb_index2xy[i+1]];
840
841 if(error1&VP_START)
842 end_ok=1;
843
844 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
845 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
846 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
847 end_ok=0;
848 }
849
850 if(!end_ok)
851 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
852 }
853 }
854
855 #if 1
856 /* backward mark errors */
857 distance=9999999;
858 for(error_type=1; error_type<=3; error_type++){
859 for(i=s->mb_num-1; i>=0; i--){
860 const int mb_xy= s->mb_index2xy[i];
861 int error= s->error_status_table[mb_xy];
862
863 if(!s->mbskip_table[mb_xy]) //FIXME partition specific
864 distance++;
865 if(error&(1<<error_type))
866 distance= 0;
867
868 if(s->partitioned_frame){
869 if(distance < threshold_part[error_type-1])
870 s->error_status_table[mb_xy]|= 1<<error_type;
871 }else{
872 if(distance < threshold)
873 s->error_status_table[mb_xy]|= 1<<error_type;
874 }
875
876 if(error&VP_START)
877 distance= 9999999;
878 }
879 }
880 #endif
881
882 /* forward mark errors */
883 error=0;
884 for(i=0; i<s->mb_num; i++){
885 const int mb_xy= s->mb_index2xy[i];
886 int old_error= s->error_status_table[mb_xy];
887
888 if(old_error&VP_START)
889 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
890 else{
891 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
892 s->error_status_table[mb_xy]|= error;
893 }
894 }
895 #if 1
896 /* handle not partitioned case */
897 if(!s->partitioned_frame){
898 for(i=0; i<s->mb_num; i++){
899 const int mb_xy= s->mb_index2xy[i];
900 error= s->error_status_table[mb_xy];
901 if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
902 error|= AC_ERROR|DC_ERROR|MV_ERROR;
903 s->error_status_table[mb_xy]= error;
904 }
905 }
906 #endif
907
908 dc_error= ac_error= mv_error=0;
909 for(i=0; i<s->mb_num; i++){
910 const int mb_xy= s->mb_index2xy[i];
911 error= s->error_status_table[mb_xy];
912 if(error&DC_ERROR) dc_error ++;
913 if(error&AC_ERROR) ac_error ++;
914 if(error&MV_ERROR) mv_error ++;
915 }
916 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
917
918 is_intra_likely= is_intra_more_likely(s);
919
920 /* set unknown mb-type to most likely */
921 for(i=0; i<s->mb_num; i++){
922 const int mb_xy= s->mb_index2xy[i];
923 error= s->error_status_table[mb_xy];
924 if(!((error&DC_ERROR) && (error&MV_ERROR)))
925 continue;
926
927 if(is_intra_likely)
928 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
929 else
930 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
931 }
932
933 // change inter to intra blocks if no reference frames are available
934 if (!s->last_picture.data[0] && !s->next_picture.data[0])
935 for(i=0; i<s->mb_num; i++){
936 const int mb_xy= s->mb_index2xy[i];
937 if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
938 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
939 }
940
941 /* handle inter blocks with damaged AC */
942 for(mb_y=0; mb_y<s->mb_height; mb_y++){
943 for(mb_x=0; mb_x<s->mb_width; mb_x++){
944 const int mb_xy= mb_x + mb_y * s->mb_stride;
945 const int mb_type= s->current_picture.mb_type[mb_xy];
946 int dir = !s->last_picture.data[0];
947 error= s->error_status_table[mb_xy];
948
949 if(IS_INTRA(mb_type)) continue; //intra
950 if(error&MV_ERROR) continue; //inter with damaged MV
951 if(!(error&AC_ERROR)) continue; //undamaged inter
952
953 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
954 s->mb_intra=0;
955 s->mb_skipped=0;
956 if(IS_8X8(mb_type)){
957 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
958 int j;
959 s->mv_type = MV_TYPE_8X8;
960 for(j=0; j<4; j++){
961 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
962 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
963 }
964 }else{
965 s->mv_type = MV_TYPE_16X16;
966 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
967 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
968 }
969
970 s->dsp.clear_blocks(s->block[0]);
971
972 s->mb_x= mb_x;
973 s->mb_y= mb_y;
974 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
975 }
976 }
977
978 /* guess MVs */
979 if(s->pict_type==FF_B_TYPE){
980 for(mb_y=0; mb_y<s->mb_height; mb_y++){
981 for(mb_x=0; mb_x<s->mb_width; mb_x++){
982 int xy= mb_x*2 + mb_y*2*s->b8_stride;
983 const int mb_xy= mb_x + mb_y * s->mb_stride;
984 const int mb_type= s->current_picture.mb_type[mb_xy];
985 error= s->error_status_table[mb_xy];
986
987 if(IS_INTRA(mb_type)) continue;
988 if(!(error&MV_ERROR)) continue; //inter with undamaged MV
989 if(!(error&AC_ERROR)) continue; //undamaged inter
990
991 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
992 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
993 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
994 s->mb_intra=0;
995 s->mv_type = MV_TYPE_16X16;
996 s->mb_skipped=0;
997
998 if(s->pp_time){
999 int time_pp= s->pp_time;
1000 int time_pb= s->pb_time;
1001
1002 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
1003 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
1004 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1005 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1006 }else{
1007 s->mv[0][0][0]= 0;
1008 s->mv[0][0][1]= 0;
1009 s->mv[1][0][0]= 0;
1010 s->mv[1][0][1]= 0;
1011 }
1012
1013 s->dsp.clear_blocks(s->block[0]);
1014 s->mb_x= mb_x;
1015 s->mb_y= mb_y;
1016 decode_mb(s, 0);
1017 }
1018 }
1019 }else
1020 guess_mv(s);
1021
1022 /* the filters below are not XvMC compatible, skip them */
1023 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1024 goto ec_clean;
1025 /* fill DC for inter blocks */
1026 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1027 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1028 int dc, dcu, dcv, y, n;
1029 int16_t *dc_ptr;
1030 uint8_t *dest_y, *dest_cb, *dest_cr;
1031 const int mb_xy= mb_x + mb_y * s->mb_stride;
1032 const int mb_type= s->current_picture.mb_type[mb_xy];
1033
1034 error= s->error_status_table[mb_xy];
1035
1036 if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1037 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1038
1039 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1040 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1041 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1042
1043 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1044 for(n=0; n<4; n++){
1045 dc=0;
1046 for(y=0; y<8; y++){
1047 int x;
1048 for(x=0; x<8; x++){
1049 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1050 }
1051 }
1052 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1053 }
1054
1055 dcu=dcv=0;
1056 for(y=0; y<8; y++){
1057 int x;
1058 for(x=0; x<8; x++){
1059 dcu+=dest_cb[x + y*(s->uvlinesize)];
1060 dcv+=dest_cr[x + y*(s->uvlinesize)];
1061 }
1062 }
1063 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1064 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1065 }
1066 }
1067 #if 1
1068 /* guess DC for damaged blocks */
1069 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1070 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
1071 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
1072 #endif
1073 /* filter luma DC */
1074 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1075
1076 #if 1
1077 /* render DC only intra */
1078 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1079 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1080 uint8_t *dest_y, *dest_cb, *dest_cr;
1081 const int mb_xy= mb_x + mb_y * s->mb_stride;
1082 const int mb_type= s->current_picture.mb_type[mb_xy];
1083
1084 error= s->error_status_table[mb_xy];
1085
1086 if(IS_INTER(mb_type)) continue;
1087 if(!(error&AC_ERROR)) continue; //undamaged
1088
1089 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1090 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1091 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1092
1093 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1094 }
1095 }
1096 #endif
1097
1098 if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1099 /* filter horizontal block boundaries */
1100 h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1101 h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1102 h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1103
1104 /* filter vertical block boundaries */
1105 v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1106 v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1107 v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1108 }
1109
1110 ec_clean:
1111 /* clean a few tables */
1112 for(i=0; i<s->mb_num; i++){
1113 const int mb_xy= s->mb_index2xy[i];
1114 int error= s->error_status_table[mb_xy];
1115
1116 if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1117 s->mbskip_table[mb_xy]=0;
1118 }
1119 s->mbintra_table[mb_xy]=1;
1120 }
1121 }