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 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 42static 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 */ 69static 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 */ 84static 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 113static 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 */ 154static 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 */ 238static 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 */ 301static 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 359static 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; 418int 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 } 525skip_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 } 584score_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 620static 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 679void 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 */ 692void 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 751void 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 1111ec_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} 1123