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