Hotfix for regtest-error failure
[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] && s->codec_id == CODEC_ID_H264)
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 && s->codec_id == CODEC_ID_H264) //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 pic->ref_index[0]= av_realloc(pic->ref_index[0], s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
771
772 if(s->avctx->debug&FF_DEBUG_ER){
773 for(mb_y=0; mb_y<s->mb_height; mb_y++){
774 for(mb_x=0; mb_x<s->mb_width; mb_x++){
775 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
776
777 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
778 }
779 av_log(s->avctx, AV_LOG_DEBUG, "\n");
780 }
781 }
782
783 #if 1
784 /* handle overlapping slices */
785 for(error_type=1; error_type<=3; error_type++){
786 int end_ok=0;
787
788 for(i=s->mb_num-1; i>=0; i--){
789 const int mb_xy= s->mb_index2xy[i];
790 int error= s->error_status_table[mb_xy];
791
792 if(error&(1<<error_type))
793 end_ok=1;
794 if(error&(8<<error_type))
795 end_ok=1;
796
797 if(!end_ok)
798 s->error_status_table[mb_xy]|= 1<<error_type;
799
800 if(error&VP_START)
801 end_ok=0;
802 }
803 }
804 #endif
805 #if 1
806 /* handle slices with partitions of different length */
807 if(s->partitioned_frame){
808 int end_ok=0;
809
810 for(i=s->mb_num-1; i>=0; i--){
811 const int mb_xy= s->mb_index2xy[i];
812 int error= s->error_status_table[mb_xy];
813
814 if(error&AC_END)
815 end_ok=0;
816 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
817 end_ok=1;
818
819 if(!end_ok)
820 s->error_status_table[mb_xy]|= AC_ERROR;
821
822 if(error&VP_START)
823 end_ok=0;
824 }
825 }
826 #endif
827 /* handle missing slices */
828 if(s->error_recognition>=4){
829 int end_ok=1;
830
831 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
832 const int mb_xy= s->mb_index2xy[i];
833 int error1= s->error_status_table[mb_xy ];
834 int error2= s->error_status_table[s->mb_index2xy[i+1]];
835
836 if(error1&VP_START)
837 end_ok=1;
838
839 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
840 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
841 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
842 end_ok=0;
843 }
844
845 if(!end_ok)
846 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
847 }
848 }
849
850 #if 1
851 /* backward mark errors */
852 distance=9999999;
853 for(error_type=1; error_type<=3; error_type++){
854 for(i=s->mb_num-1; i>=0; i--){
855 const int mb_xy= s->mb_index2xy[i];
856 int error= s->error_status_table[mb_xy];
857
858 if(!s->mbskip_table[mb_xy]) //FIXME partition specific
859 distance++;
860 if(error&(1<<error_type))
861 distance= 0;
862
863 if(s->partitioned_frame){
864 if(distance < threshold_part[error_type-1])
865 s->error_status_table[mb_xy]|= 1<<error_type;
866 }else{
867 if(distance < threshold)
868 s->error_status_table[mb_xy]|= 1<<error_type;
869 }
870
871 if(error&VP_START)
872 distance= 9999999;
873 }
874 }
875 #endif
876
877 /* forward mark errors */
878 error=0;
879 for(i=0; i<s->mb_num; i++){
880 const int mb_xy= s->mb_index2xy[i];
881 int old_error= s->error_status_table[mb_xy];
882
883 if(old_error&VP_START)
884 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
885 else{
886 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
887 s->error_status_table[mb_xy]|= error;
888 }
889 }
890 #if 1
891 /* handle not partitioned case */
892 if(!s->partitioned_frame){
893 for(i=0; i<s->mb_num; i++){
894 const int mb_xy= s->mb_index2xy[i];
895 error= s->error_status_table[mb_xy];
896 if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
897 error|= AC_ERROR|DC_ERROR|MV_ERROR;
898 s->error_status_table[mb_xy]= error;
899 }
900 }
901 #endif
902
903 dc_error= ac_error= mv_error=0;
904 for(i=0; i<s->mb_num; i++){
905 const int mb_xy= s->mb_index2xy[i];
906 error= s->error_status_table[mb_xy];
907 if(error&DC_ERROR) dc_error ++;
908 if(error&AC_ERROR) ac_error ++;
909 if(error&MV_ERROR) mv_error ++;
910 }
911 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
912
913 is_intra_likely= is_intra_more_likely(s);
914
915 /* set unknown mb-type to most likely */
916 for(i=0; i<s->mb_num; i++){
917 const int mb_xy= s->mb_index2xy[i];
918 error= s->error_status_table[mb_xy];
919 if(!((error&DC_ERROR) && (error&MV_ERROR)))
920 continue;
921
922 if(is_intra_likely)
923 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
924 else
925 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
926 }
927
928 // change inter to intra blocks if no reference frames are available
929 if (!s->last_picture.data[0] && !s->next_picture.data[0])
930 for(i=0; i<s->mb_num; i++){
931 const int mb_xy= s->mb_index2xy[i];
932 if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
933 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
934 }
935
936 /* handle inter blocks with damaged AC */
937 for(mb_y=0; mb_y<s->mb_height; mb_y++){
938 for(mb_x=0; mb_x<s->mb_width; mb_x++){
939 const int mb_xy= mb_x + mb_y * s->mb_stride;
940 const int mb_type= s->current_picture.mb_type[mb_xy];
941 int dir = !s->last_picture.data[0];
942 error= s->error_status_table[mb_xy];
943
944 if(IS_INTRA(mb_type)) continue; //intra
945 if(error&MV_ERROR) continue; //inter with damaged MV
946 if(!(error&AC_ERROR)) continue; //undamaged inter
947
948 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
949 s->mb_intra=0;
950 s->mb_skipped=0;
951 if(IS_8X8(mb_type)){
952 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
953 int j;
954 s->mv_type = MV_TYPE_8X8;
955 for(j=0; j<4; j++){
956 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
957 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
958 }
959 }else{
960 s->mv_type = MV_TYPE_16X16;
961 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
962 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
963 }
964
965 s->dsp.clear_blocks(s->block[0]);
966
967 s->mb_x= mb_x;
968 s->mb_y= mb_y;
969 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
970 }
971 }
972
973 /* guess MVs */
974 if(s->pict_type==FF_B_TYPE){
975 for(mb_y=0; mb_y<s->mb_height; mb_y++){
976 for(mb_x=0; mb_x<s->mb_width; mb_x++){
977 int xy= mb_x*2 + mb_y*2*s->b8_stride;
978 const int mb_xy= mb_x + mb_y * s->mb_stride;
979 const int mb_type= s->current_picture.mb_type[mb_xy];
980 error= s->error_status_table[mb_xy];
981
982 if(IS_INTRA(mb_type)) continue;
983 if(!(error&MV_ERROR)) continue; //inter with undamaged MV
984 if(!(error&AC_ERROR)) continue; //undamaged inter
985
986 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
987 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
988 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
989 s->mb_intra=0;
990 s->mv_type = MV_TYPE_16X16;
991 s->mb_skipped=0;
992
993 if(s->pp_time){
994 int time_pp= s->pp_time;
995 int time_pb= s->pb_time;
996
997 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
998 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
999 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
1000 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
1001 }else{
1002 s->mv[0][0][0]= 0;
1003 s->mv[0][0][1]= 0;
1004 s->mv[1][0][0]= 0;
1005 s->mv[1][0][1]= 0;
1006 }
1007
1008 s->dsp.clear_blocks(s->block[0]);
1009 s->mb_x= mb_x;
1010 s->mb_y= mb_y;
1011 decode_mb(s, 0);
1012 }
1013 }
1014 }else
1015 guess_mv(s);
1016
1017 /* the filters below are not XvMC compatible, skip them */
1018 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
1019 goto ec_clean;
1020 /* fill DC for inter blocks */
1021 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1022 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1023 int dc, dcu, dcv, y, n;
1024 int16_t *dc_ptr;
1025 uint8_t *dest_y, *dest_cb, *dest_cr;
1026 const int mb_xy= mb_x + mb_y * s->mb_stride;
1027 const int mb_type= s->current_picture.mb_type[mb_xy];
1028
1029 error= s->error_status_table[mb_xy];
1030
1031 if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
1032 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
1033
1034 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1035 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1036 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1037
1038 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
1039 for(n=0; n<4; n++){
1040 dc=0;
1041 for(y=0; y<8; y++){
1042 int x;
1043 for(x=0; x<8; x++){
1044 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
1045 }
1046 }
1047 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
1048 }
1049
1050 dcu=dcv=0;
1051 for(y=0; y<8; y++){
1052 int x;
1053 for(x=0; x<8; x++){
1054 dcu+=dest_cb[x + y*(s->uvlinesize)];
1055 dcv+=dest_cr[x + y*(s->uvlinesize)];
1056 }
1057 }
1058 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
1059 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
1060 }
1061 }
1062 #if 1
1063 /* guess DC for damaged blocks */
1064 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
1065 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0);
1066 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0);
1067 #endif
1068 /* filter luma DC */
1069 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
1070
1071 #if 1
1072 /* render DC only intra */
1073 for(mb_y=0; mb_y<s->mb_height; mb_y++){
1074 for(mb_x=0; mb_x<s->mb_width; mb_x++){
1075 uint8_t *dest_y, *dest_cb, *dest_cr;
1076 const int mb_xy= mb_x + mb_y * s->mb_stride;
1077 const int mb_type= s->current_picture.mb_type[mb_xy];
1078
1079 error= s->error_status_table[mb_xy];
1080
1081 if(IS_INTER(mb_type)) continue;
1082 if(!(error&AC_ERROR)) continue; //undamaged
1083
1084 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
1085 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize;
1086 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize;
1087
1088 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
1089 }
1090 }
1091 #endif
1092
1093 if(s->avctx->error_concealment&FF_EC_DEBLOCK){
1094 /* filter horizontal block boundaries */
1095 h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1096 h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1097 h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1098
1099 /* filter vertical block boundaries */
1100 v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1);
1101 v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0);
1102 v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0);
1103 }
1104
1105 ec_clean:
1106 /* clean a few tables */
1107 for(i=0; i<s->mb_num; i++){
1108 const int mb_xy= s->mb_index2xy[i];
1109 int error= s->error_status_table[mb_xy];
1110
1111 if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
1112 s->mbskip_table[mb_xy]=0;
1113 }
1114 s->mbintra_table[mb_xy]=1;
1115 }
1116 }