Libav
|
00001 /* 00002 * Error resilience / concealment 00003 * 00004 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> 00005 * 00006 * This file is part of FFmpeg. 00007 * 00008 * FFmpeg is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * FFmpeg is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with FFmpeg; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00028 #include <limits.h> 00029 00030 #include "avcodec.h" 00031 #include "dsputil.h" 00032 #include "mpegvideo.h" 00033 #include "h264.h" 00034 #include "rectangle.h" 00035 00036 /* 00037 * H264 redefines mb_intra so it is not mistakely used (its uninitialized in h264) 00038 * but error concealment must support both h264 and h263 thus we must undo this 00039 */ 00040 #undef mb_intra 00041 00042 static void decode_mb(MpegEncContext *s, int ref){ 00043 s->dest[0] = s->current_picture.data[0] + (s->mb_y * 16* s->linesize ) + s->mb_x * 16; 00044 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); 00045 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); 00046 00047 if(CONFIG_H264_DECODER && s->codec_id == CODEC_ID_H264){ 00048 H264Context *h= (void*)s; 00049 h->mb_xy= s->mb_x + s->mb_y*s->mb_stride; 00050 memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache)); 00051 assert(ref>=0); 00052 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 00053 ref=0; 00054 fill_rectangle(&s->current_picture.ref_index[0][4*h->mb_xy], 2, 2, 2, ref, 1); 00055 fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); 00056 fill_rectangle(h->mv_cache[0][ scan8[0] ], 4, 4, 8, pack16to32(s->mv[0][0][0],s->mv[0][0][1]), 4); 00057 assert(!FRAME_MBAFF); 00058 ff_h264_hl_decode_mb(h); 00059 }else{ 00060 assert(ref==0); 00061 MPV_decode_mb(s, s->block); 00062 } 00063 } 00064 00069 static void set_mv_strides(MpegEncContext *s, int *mv_step, int *stride){ 00070 if(s->codec_id == CODEC_ID_H264){ 00071 H264Context *h= (void*)s; 00072 assert(s->quarter_sample); 00073 *mv_step= 4; 00074 *stride= h->b_stride; 00075 }else{ 00076 *mv_step= 2; 00077 *stride= s->b8_stride; 00078 } 00079 } 00080 00084 static void put_dc(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y) 00085 { 00086 int dc, dcu, dcv, y, i; 00087 for(i=0; i<4; i++){ 00088 dc= s->dc_val[0][mb_x*2 + (i&1) + (mb_y*2 + (i>>1))*s->b8_stride]; 00089 if(dc<0) dc=0; 00090 else if(dc>2040) dc=2040; 00091 for(y=0; y<8; y++){ 00092 int x; 00093 for(x=0; x<8; x++){ 00094 dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8; 00095 } 00096 } 00097 } 00098 dcu = s->dc_val[1][mb_x + mb_y*s->mb_stride]; 00099 dcv = s->dc_val[2][mb_x + mb_y*s->mb_stride]; 00100 if (dcu<0 ) dcu=0; 00101 else if(dcu>2040) dcu=2040; 00102 if (dcv<0 ) dcv=0; 00103 else if(dcv>2040) dcv=2040; 00104 for(y=0; y<8; y++){ 00105 int x; 00106 for(x=0; x<8; x++){ 00107 dest_cb[x + y*(s->uvlinesize)]= dcu/8; 00108 dest_cr[x + y*(s->uvlinesize)]= dcv/8; 00109 } 00110 } 00111 } 00112 00113 static void filter181(int16_t *data, int width, int height, int stride){ 00114 int x,y; 00115 00116 /* horizontal filter */ 00117 for(y=1; y<height-1; y++){ 00118 int prev_dc= data[0 + y*stride]; 00119 00120 for(x=1; x<width-1; x++){ 00121 int dc; 00122 00123 dc= - prev_dc 00124 + data[x + y*stride]*8 00125 - data[x + 1 + y*stride]; 00126 dc= (dc*10923 + 32768)>>16; 00127 prev_dc= data[x + y*stride]; 00128 data[x + y*stride]= dc; 00129 } 00130 } 00131 00132 /* vertical filter */ 00133 for(x=1; x<width-1; x++){ 00134 int prev_dc= data[x]; 00135 00136 for(y=1; y<height-1; y++){ 00137 int dc; 00138 00139 dc= - prev_dc 00140 + data[x + y *stride]*8 00141 - data[x + (y+1)*stride]; 00142 dc= (dc*10923 + 32768)>>16; 00143 prev_dc= data[x + y*stride]; 00144 data[x + y*stride]= dc; 00145 } 00146 } 00147 } 00148 00154 static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){ 00155 int b_x, b_y; 00156 00157 for(b_y=0; b_y<h; b_y++){ 00158 for(b_x=0; b_x<w; b_x++){ 00159 int color[4]={1024,1024,1024,1024}; 00160 int distance[4]={9999,9999,9999,9999}; 00161 int mb_index, error, j; 00162 int64_t guess, weight_sum; 00163 00164 mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; 00165 00166 error= s->error_status_table[mb_index]; 00167 00168 if(IS_INTER(s->current_picture.mb_type[mb_index])) continue; //inter 00169 if(!(error&DC_ERROR)) continue; //dc-ok 00170 00171 /* right block */ 00172 for(j=b_x+1; j<w; j++){ 00173 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride; 00174 int error_j= s->error_status_table[mb_index_j]; 00175 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]); 00176 if(intra_j==0 || !(error_j&DC_ERROR)){ 00177 color[0]= dc[j + b_y*stride]; 00178 distance[0]= j-b_x; 00179 break; 00180 } 00181 } 00182 00183 /* left block */ 00184 for(j=b_x-1; j>=0; j--){ 00185 int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride; 00186 int error_j= s->error_status_table[mb_index_j]; 00187 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]); 00188 if(intra_j==0 || !(error_j&DC_ERROR)){ 00189 color[1]= dc[j + b_y*stride]; 00190 distance[1]= b_x-j; 00191 break; 00192 } 00193 } 00194 00195 /* bottom block */ 00196 for(j=b_y+1; j<h; j++){ 00197 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride; 00198 int error_j= s->error_status_table[mb_index_j]; 00199 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]); 00200 if(intra_j==0 || !(error_j&DC_ERROR)){ 00201 color[2]= dc[b_x + j*stride]; 00202 distance[2]= j-b_y; 00203 break; 00204 } 00205 } 00206 00207 /* top block */ 00208 for(j=b_y-1; j>=0; j--){ 00209 int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride; 00210 int error_j= s->error_status_table[mb_index_j]; 00211 int intra_j= IS_INTRA(s->current_picture.mb_type[mb_index_j]); 00212 if(intra_j==0 || !(error_j&DC_ERROR)){ 00213 color[3]= dc[b_x + j*stride]; 00214 distance[3]= b_y-j; 00215 break; 00216 } 00217 } 00218 00219 weight_sum=0; 00220 guess=0; 00221 for(j=0; j<4; j++){ 00222 int64_t weight= 256*256*256*16/distance[j]; 00223 guess+= weight*(int64_t)color[j]; 00224 weight_sum+= weight; 00225 } 00226 guess= (guess + weight_sum/2) / weight_sum; 00227 00228 dc[b_x + b_y*stride]= guess; 00229 } 00230 } 00231 } 00232 00238 static void h_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ 00239 int b_x, b_y, mvx_stride, mvy_stride; 00240 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; 00241 set_mv_strides(s, &mvx_stride, &mvy_stride); 00242 mvx_stride >>= is_luma; 00243 mvy_stride *= mvx_stride; 00244 00245 for(b_y=0; b_y<h; b_y++){ 00246 for(b_x=0; b_x<w-1; b_x++){ 00247 int y; 00248 int left_status = s->error_status_table[( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]; 00249 int right_status= s->error_status_table[((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]; 00250 int left_intra= IS_INTRA(s->current_picture.mb_type [( b_x >>is_luma) + (b_y>>is_luma)*s->mb_stride]); 00251 int right_intra= IS_INTRA(s->current_picture.mb_type [((b_x+1)>>is_luma) + (b_y>>is_luma)*s->mb_stride]); 00252 int left_damage = left_status&(DC_ERROR|AC_ERROR|MV_ERROR); 00253 int right_damage= right_status&(DC_ERROR|AC_ERROR|MV_ERROR); 00254 int offset= b_x*8 + b_y*stride*8; 00255 int16_t *left_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride* b_x ]; 00256 int16_t *right_mv= s->current_picture.motion_val[0][mvy_stride*b_y + mvx_stride*(b_x+1)]; 00257 00258 if(!(left_damage||right_damage)) continue; // both undamaged 00259 00260 if( (!left_intra) && (!right_intra) 00261 && FFABS(left_mv[0]-right_mv[0]) + FFABS(left_mv[1]+right_mv[1]) < 2) continue; 00262 00263 for(y=0; y<8; y++){ 00264 int a,b,c,d; 00265 00266 a= dst[offset + 7 + y*stride] - dst[offset + 6 + y*stride]; 00267 b= dst[offset + 8 + y*stride] - dst[offset + 7 + y*stride]; 00268 c= dst[offset + 9 + y*stride] - dst[offset + 8 + y*stride]; 00269 00270 d= FFABS(b) - ((FFABS(a) + FFABS(c) + 1)>>1); 00271 d= FFMAX(d, 0); 00272 if(b<0) d= -d; 00273 00274 if(d==0) continue; 00275 00276 if(!(left_damage && right_damage)) 00277 d= d*16/9; 00278 00279 if(left_damage){ 00280 dst[offset + 7 + y*stride] = cm[dst[offset + 7 + y*stride] + ((d*7)>>4)]; 00281 dst[offset + 6 + y*stride] = cm[dst[offset + 6 + y*stride] + ((d*5)>>4)]; 00282 dst[offset + 5 + y*stride] = cm[dst[offset + 5 + y*stride] + ((d*3)>>4)]; 00283 dst[offset + 4 + y*stride] = cm[dst[offset + 4 + y*stride] + ((d*1)>>4)]; 00284 } 00285 if(right_damage){ 00286 dst[offset + 8 + y*stride] = cm[dst[offset + 8 + y*stride] - ((d*7)>>4)]; 00287 dst[offset + 9 + y*stride] = cm[dst[offset + 9 + y*stride] - ((d*5)>>4)]; 00288 dst[offset + 10+ y*stride] = cm[dst[offset +10 + y*stride] - ((d*3)>>4)]; 00289 dst[offset + 11+ y*stride] = cm[dst[offset +11 + y*stride] - ((d*1)>>4)]; 00290 } 00291 } 00292 } 00293 } 00294 } 00295 00301 static void v_block_filter(MpegEncContext *s, uint8_t *dst, int w, int h, int stride, int is_luma){ 00302 int b_x, b_y, mvx_stride, mvy_stride; 00303 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; 00304 set_mv_strides(s, &mvx_stride, &mvy_stride); 00305 mvx_stride >>= is_luma; 00306 mvy_stride *= mvx_stride; 00307 00308 for(b_y=0; b_y<h-1; b_y++){ 00309 for(b_x=0; b_x<w; b_x++){ 00310 int x; 00311 int top_status = s->error_status_table[(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]; 00312 int bottom_status= s->error_status_table[(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]; 00313 int top_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ( b_y >>is_luma)*s->mb_stride]); 00314 int bottom_intra= IS_INTRA(s->current_picture.mb_type [(b_x>>is_luma) + ((b_y+1)>>is_luma)*s->mb_stride]); 00315 int top_damage = top_status&(DC_ERROR|AC_ERROR|MV_ERROR); 00316 int bottom_damage= bottom_status&(DC_ERROR|AC_ERROR|MV_ERROR); 00317 int offset= b_x*8 + b_y*stride*8; 00318 int16_t *top_mv= s->current_picture.motion_val[0][mvy_stride* b_y + mvx_stride*b_x]; 00319 int16_t *bottom_mv= s->current_picture.motion_val[0][mvy_stride*(b_y+1) + mvx_stride*b_x]; 00320 00321 if(!(top_damage||bottom_damage)) continue; // both undamaged 00322 00323 if( (!top_intra) && (!bottom_intra) 00324 && FFABS(top_mv[0]-bottom_mv[0]) + FFABS(top_mv[1]+bottom_mv[1]) < 2) continue; 00325 00326 for(x=0; x<8; x++){ 00327 int a,b,c,d; 00328 00329 a= dst[offset + x + 7*stride] - dst[offset + x + 6*stride]; 00330 b= dst[offset + x + 8*stride] - dst[offset + x + 7*stride]; 00331 c= dst[offset + x + 9*stride] - dst[offset + x + 8*stride]; 00332 00333 d= FFABS(b) - ((FFABS(a) + FFABS(c)+1)>>1); 00334 d= FFMAX(d, 0); 00335 if(b<0) d= -d; 00336 00337 if(d==0) continue; 00338 00339 if(!(top_damage && bottom_damage)) 00340 d= d*16/9; 00341 00342 if(top_damage){ 00343 dst[offset + x + 7*stride] = cm[dst[offset + x + 7*stride] + ((d*7)>>4)]; 00344 dst[offset + x + 6*stride] = cm[dst[offset + x + 6*stride] + ((d*5)>>4)]; 00345 dst[offset + x + 5*stride] = cm[dst[offset + x + 5*stride] + ((d*3)>>4)]; 00346 dst[offset + x + 4*stride] = cm[dst[offset + x + 4*stride] + ((d*1)>>4)]; 00347 } 00348 if(bottom_damage){ 00349 dst[offset + x + 8*stride] = cm[dst[offset + x + 8*stride] - ((d*7)>>4)]; 00350 dst[offset + x + 9*stride] = cm[dst[offset + x + 9*stride] - ((d*5)>>4)]; 00351 dst[offset + x + 10*stride] = cm[dst[offset + x + 10*stride] - ((d*3)>>4)]; 00352 dst[offset + x + 11*stride] = cm[dst[offset + x + 11*stride] - ((d*1)>>4)]; 00353 } 00354 } 00355 } 00356 } 00357 } 00358 00359 static void guess_mv(MpegEncContext *s){ 00360 uint8_t fixed[s->mb_stride * s->mb_height]; 00361 #define MV_FROZEN 3 00362 #define MV_CHANGED 2 00363 #define MV_UNCHANGED 1 00364 const int mb_stride = s->mb_stride; 00365 const int mb_width = s->mb_width; 00366 const int mb_height= s->mb_height; 00367 int i, depth, num_avail; 00368 int mb_x, mb_y, mot_step, mot_stride; 00369 00370 set_mv_strides(s, &mot_step, &mot_stride); 00371 00372 num_avail=0; 00373 for(i=0; i<s->mb_num; i++){ 00374 const int mb_xy= s->mb_index2xy[ i ]; 00375 int f=0; 00376 int error= s->error_status_table[mb_xy]; 00377 00378 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) f=MV_FROZEN; //intra //FIXME check 00379 if(!(error&MV_ERROR)) f=MV_FROZEN; //inter with undamaged MV 00380 00381 fixed[mb_xy]= f; 00382 if(f==MV_FROZEN) 00383 num_avail++; 00384 } 00385 00386 if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){ 00387 for(mb_y=0; mb_y<s->mb_height; mb_y++){ 00388 for(mb_x=0; mb_x<s->mb_width; mb_x++){ 00389 const int mb_xy= mb_x + mb_y*s->mb_stride; 00390 00391 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) continue; 00392 if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue; 00393 00394 s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD; 00395 s->mb_intra=0; 00396 s->mv_type = MV_TYPE_16X16; 00397 s->mb_skipped=0; 00398 00399 s->dsp.clear_blocks(s->block[0]); 00400 00401 s->mb_x= mb_x; 00402 s->mb_y= mb_y; 00403 s->mv[0][0][0]= 0; 00404 s->mv[0][0][1]= 0; 00405 decode_mb(s, 0); 00406 } 00407 } 00408 return; 00409 } 00410 00411 for(depth=0;; depth++){ 00412 int changed, pass, none_left; 00413 00414 none_left=1; 00415 changed=1; 00416 for(pass=0; (changed || pass<2) && pass<10; pass++){ 00417 int mb_x, mb_y; 00418 int score_sum=0; 00419 00420 changed=0; 00421 for(mb_y=0; mb_y<s->mb_height; mb_y++){ 00422 for(mb_x=0; mb_x<s->mb_width; mb_x++){ 00423 const int mb_xy= mb_x + mb_y*s->mb_stride; 00424 int mv_predictor[8][2]={{0}}; 00425 int ref[8]={0}; 00426 int pred_count=0; 00427 int j; 00428 int best_score=256*256*256*64; 00429 int best_pred=0; 00430 const int mot_index= (mb_x + mb_y*mot_stride) * mot_step; 00431 int prev_x= s->current_picture.motion_val[0][mot_index][0]; 00432 int prev_y= s->current_picture.motion_val[0][mot_index][1]; 00433 00434 if((mb_x^mb_y^pass)&1) continue; 00435 00436 if(fixed[mb_xy]==MV_FROZEN) continue; 00437 assert(!IS_INTRA(s->current_picture.mb_type[mb_xy])); 00438 assert(s->last_picture_ptr && s->last_picture_ptr->data[0]); 00439 00440 j=0; 00441 if(mb_x>0 && fixed[mb_xy-1 ]==MV_FROZEN) j=1; 00442 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_FROZEN) j=1; 00443 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1; 00444 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1; 00445 if(j==0) continue; 00446 00447 j=0; 00448 if(mb_x>0 && fixed[mb_xy-1 ]==MV_CHANGED) j=1; 00449 if(mb_x+1<mb_width && fixed[mb_xy+1 ]==MV_CHANGED) j=1; 00450 if(mb_y>0 && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1; 00451 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1; 00452 if(j==0 && pass>1) continue; 00453 00454 none_left=0; 00455 00456 if(mb_x>0 && fixed[mb_xy-1]){ 00457 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0]; 00458 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1]; 00459 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-1)]; 00460 pred_count++; 00461 } 00462 if(mb_x+1<mb_width && fixed[mb_xy+1]){ 00463 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_step][0]; 00464 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1]; 00465 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+1)]; 00466 pred_count++; 00467 } 00468 if(mb_y>0 && fixed[mb_xy-mb_stride]){ 00469 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0]; 00470 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1]; 00471 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)]; 00472 pred_count++; 00473 } 00474 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){ 00475 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][0]; 00476 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1]; 00477 ref [pred_count] = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)]; 00478 pred_count++; 00479 } 00480 if(pred_count==0) continue; 00481 00482 if(pred_count>1){ 00483 int sum_x=0, sum_y=0, sum_r=0; 00484 int max_x, max_y, min_x, min_y, max_r, min_r; 00485 00486 for(j=0; j<pred_count; j++){ 00487 sum_x+= mv_predictor[j][0]; 00488 sum_y+= mv_predictor[j][1]; 00489 sum_r+= ref[j]; 00490 if(j && ref[j] != ref[j-1]) 00491 goto skip_mean_and_median; 00492 } 00493 00494 /* mean */ 00495 mv_predictor[pred_count][0] = sum_x/j; 00496 mv_predictor[pred_count][1] = sum_y/j; 00497 ref [pred_count] = sum_r/j; 00498 00499 /* median */ 00500 if(pred_count>=3){ 00501 min_y= min_x= min_r= 99999; 00502 max_y= max_x= max_r=-99999; 00503 }else{ 00504 min_x=min_y=max_x=max_y=min_r=max_r=0; 00505 } 00506 for(j=0; j<pred_count; j++){ 00507 max_x= FFMAX(max_x, mv_predictor[j][0]); 00508 max_y= FFMAX(max_y, mv_predictor[j][1]); 00509 max_r= FFMAX(max_r, ref[j]); 00510 min_x= FFMIN(min_x, mv_predictor[j][0]); 00511 min_y= FFMIN(min_y, mv_predictor[j][1]); 00512 min_r= FFMIN(min_r, ref[j]); 00513 } 00514 mv_predictor[pred_count+1][0] = sum_x - max_x - min_x; 00515 mv_predictor[pred_count+1][1] = sum_y - max_y - min_y; 00516 ref [pred_count+1] = sum_r - max_r - min_r; 00517 00518 if(pred_count==4){ 00519 mv_predictor[pred_count+1][0] /= 2; 00520 mv_predictor[pred_count+1][1] /= 2; 00521 ref [pred_count+1] /= 2; 00522 } 00523 pred_count+=2; 00524 } 00525 skip_mean_and_median: 00526 00527 /* zero MV */ 00528 pred_count++; 00529 00530 /* last MV */ 00531 mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index][0]; 00532 mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index][1]; 00533 ref [pred_count] = s->current_picture.ref_index[0][4*mb_xy]; 00534 pred_count++; 00535 00536 s->mv_dir = MV_DIR_FORWARD; 00537 s->mb_intra=0; 00538 s->mv_type = MV_TYPE_16X16; 00539 s->mb_skipped=0; 00540 00541 s->dsp.clear_blocks(s->block[0]); 00542 00543 s->mb_x= mb_x; 00544 s->mb_y= mb_y; 00545 00546 for(j=0; j<pred_count; j++){ 00547 int score=0; 00548 uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; 00549 00550 s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0]; 00551 s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1]; 00552 00553 if(ref[j]<0) //predictor intra or otherwise not available 00554 continue; 00555 00556 decode_mb(s, ref[j]); 00557 00558 if(mb_x>0 && fixed[mb_xy-1]){ 00559 int k; 00560 for(k=0; k<16; k++) 00561 score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize ]); 00562 } 00563 if(mb_x+1<mb_width && fixed[mb_xy+1]){ 00564 int k; 00565 for(k=0; k<16; k++) 00566 score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]); 00567 } 00568 if(mb_y>0 && fixed[mb_xy-mb_stride]){ 00569 int k; 00570 for(k=0; k<16; k++) 00571 score += FFABS(src[k-s->linesize ]-src[k ]); 00572 } 00573 if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){ 00574 int k; 00575 for(k=0; k<16; k++) 00576 score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]); 00577 } 00578 00579 if(score <= best_score){ // <= will favor the last MV 00580 best_score= score; 00581 best_pred= j; 00582 } 00583 } 00584 score_sum+= best_score; 00585 s->mv[0][0][0]= mv_predictor[best_pred][0]; 00586 s->mv[0][0][1]= mv_predictor[best_pred][1]; 00587 00588 for(i=0; i<mot_step; i++) 00589 for(j=0; j<mot_step; j++){ 00590 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0]; 00591 s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1]; 00592 } 00593 00594 decode_mb(s, ref[best_pred]); 00595 00596 00597 if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){ 00598 fixed[mb_xy]=MV_CHANGED; 00599 changed++; 00600 }else 00601 fixed[mb_xy]=MV_UNCHANGED; 00602 } 00603 } 00604 00605 // printf(".%d/%d", changed, score_sum); fflush(stdout); 00606 } 00607 00608 if(none_left) 00609 return; 00610 00611 for(i=0; i<s->mb_num; i++){ 00612 int mb_xy= s->mb_index2xy[i]; 00613 if(fixed[mb_xy]) 00614 fixed[mb_xy]=MV_FROZEN; 00615 } 00616 // printf(":"); fflush(stdout); 00617 } 00618 } 00619 00620 static int is_intra_more_likely(MpegEncContext *s){ 00621 int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y; 00622 00623 if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction 00624 00625 undamaged_count=0; 00626 for(i=0; i<s->mb_num; i++){ 00627 const int mb_xy= s->mb_index2xy[i]; 00628 const int error= s->error_status_table[mb_xy]; 00629 if(!((error&DC_ERROR) && (error&MV_ERROR))) 00630 undamaged_count++; 00631 } 00632 00633 if(s->codec_id == CODEC_ID_H264){ 00634 H264Context *h= (void*)s; 00635 if(h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0]) 00636 return 1; 00637 } 00638 00639 if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction 00640 00641 //prevent dsp.sad() check, that requires access to the image 00642 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == FF_I_TYPE) 00643 return 1; 00644 00645 skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs 00646 is_intra_likely=0; 00647 00648 j=0; 00649 for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){ 00650 for(mb_x= 0; mb_x<s->mb_width; mb_x++){ 00651 int error; 00652 const int mb_xy= mb_x + mb_y*s->mb_stride; 00653 00654 error= s->error_status_table[mb_xy]; 00655 if((error&DC_ERROR) && (error&MV_ERROR)) 00656 continue; //skip damaged 00657 00658 j++; 00659 if((j%skip_amount) != 0) continue; //skip a few to speed things up 00660 00661 if(s->pict_type==FF_I_TYPE){ 00662 uint8_t *mb_ptr = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; 00663 uint8_t *last_mb_ptr= s->last_picture.data [0] + mb_x*16 + mb_y*16*s->linesize; 00664 00665 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr , s->linesize, 16); 00666 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16); 00667 }else{ 00668 if(IS_INTRA(s->current_picture.mb_type[mb_xy])) 00669 is_intra_likely++; 00670 else 00671 is_intra_likely--; 00672 } 00673 } 00674 } 00675 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type); 00676 return is_intra_likely > 0; 00677 } 00678 00679 void ff_er_frame_start(MpegEncContext *s){ 00680 if(!s->error_recognition) return; 00681 00682 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)); 00683 s->error_count= 3*s->mb_num; 00684 } 00685 00692 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){ 00693 const int start_i= av_clip(startx + starty * s->mb_width , 0, s->mb_num-1); 00694 const int end_i = av_clip(endx + endy * s->mb_width , 0, s->mb_num); 00695 const int start_xy= s->mb_index2xy[start_i]; 00696 const int end_xy = s->mb_index2xy[end_i]; 00697 int mask= -1; 00698 00699 if(s->avctx->hwaccel) 00700 return; 00701 00702 if(start_i > end_i || start_xy > end_xy){ 00703 av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n"); 00704 return; 00705 } 00706 00707 if(!s->error_recognition) return; 00708 00709 mask &= ~VP_START; 00710 if(status & (AC_ERROR|AC_END)){ 00711 mask &= ~(AC_ERROR|AC_END); 00712 s->error_count -= end_i - start_i + 1; 00713 } 00714 if(status & (DC_ERROR|DC_END)){ 00715 mask &= ~(DC_ERROR|DC_END); 00716 s->error_count -= end_i - start_i + 1; 00717 } 00718 if(status & (MV_ERROR|MV_END)){ 00719 mask &= ~(MV_ERROR|MV_END); 00720 s->error_count -= end_i - start_i + 1; 00721 } 00722 00723 if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) s->error_count= INT_MAX; 00724 00725 if(mask == ~0x7F){ 00726 memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t)); 00727 }else{ 00728 int i; 00729 for(i=start_xy; i<end_xy; i++){ 00730 s->error_status_table[ i ] &= mask; 00731 } 00732 } 00733 00734 if(end_i == s->mb_num) 00735 s->error_count= INT_MAX; 00736 else{ 00737 s->error_status_table[end_xy] &= mask; 00738 s->error_status_table[end_xy] |= status; 00739 } 00740 00741 s->error_status_table[start_xy] |= VP_START; 00742 00743 if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){ 00744 int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ]; 00745 00746 prev_status &= ~ VP_START; 00747 if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX; 00748 } 00749 } 00750 00751 void ff_er_frame_end(MpegEncContext *s){ 00752 int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error; 00753 int distance; 00754 int threshold_part[4]= {100,100,100}; 00755 int threshold= 50; 00756 int is_intra_likely; 00757 int size = s->b8_stride * 2 * s->mb_height; 00758 Picture *pic= s->current_picture_ptr; 00759 00760 if(!s->error_recognition || s->error_count==0 || s->avctx->lowres || 00761 s->avctx->hwaccel || 00762 s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU || 00763 s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled 00764 s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return; 00765 00766 if(s->current_picture.motion_val[0] == NULL){ 00767 av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n"); 00768 00769 for(i=0; i<2; i++){ 00770 pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t)); 00771 pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t)); 00772 pic->motion_val[i]= pic->motion_val_base[i]+4; 00773 } 00774 pic->motion_subsample_log2= 3; 00775 s->current_picture= *s->current_picture_ptr; 00776 } 00777 00778 if(s->avctx->debug&FF_DEBUG_ER){ 00779 for(mb_y=0; mb_y<s->mb_height; mb_y++){ 00780 for(mb_x=0; mb_x<s->mb_width; mb_x++){ 00781 int status= s->error_status_table[mb_x + mb_y*s->mb_stride]; 00782 00783 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status); 00784 } 00785 av_log(s->avctx, AV_LOG_DEBUG, "\n"); 00786 } 00787 } 00788 00789 #if 1 00790 /* handle overlapping slices */ 00791 for(error_type=1; error_type<=3; error_type++){ 00792 int end_ok=0; 00793 00794 for(i=s->mb_num-1; i>=0; i--){ 00795 const int mb_xy= s->mb_index2xy[i]; 00796 int error= s->error_status_table[mb_xy]; 00797 00798 if(error&(1<<error_type)) 00799 end_ok=1; 00800 if(error&(8<<error_type)) 00801 end_ok=1; 00802 00803 if(!end_ok) 00804 s->error_status_table[mb_xy]|= 1<<error_type; 00805 00806 if(error&VP_START) 00807 end_ok=0; 00808 } 00809 } 00810 #endif 00811 #if 1 00812 /* handle slices with partitions of different length */ 00813 if(s->partitioned_frame){ 00814 int end_ok=0; 00815 00816 for(i=s->mb_num-1; i>=0; i--){ 00817 const int mb_xy= s->mb_index2xy[i]; 00818 int error= s->error_status_table[mb_xy]; 00819 00820 if(error&AC_END) 00821 end_ok=0; 00822 if((error&MV_END) || (error&DC_END) || (error&AC_ERROR)) 00823 end_ok=1; 00824 00825 if(!end_ok) 00826 s->error_status_table[mb_xy]|= AC_ERROR; 00827 00828 if(error&VP_START) 00829 end_ok=0; 00830 } 00831 } 00832 #endif 00833 /* handle missing slices */ 00834 if(s->error_recognition>=4){ 00835 int end_ok=1; 00836 00837 for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack 00838 const int mb_xy= s->mb_index2xy[i]; 00839 int error1= s->error_status_table[mb_xy ]; 00840 int error2= s->error_status_table[s->mb_index2xy[i+1]]; 00841 00842 if(error1&VP_START) 00843 end_ok=1; 00844 00845 if( error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END) 00846 && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END) 00847 && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit 00848 end_ok=0; 00849 } 00850 00851 if(!end_ok) 00852 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR; 00853 } 00854 } 00855 00856 #if 1 00857 /* backward mark errors */ 00858 distance=9999999; 00859 for(error_type=1; error_type<=3; error_type++){ 00860 for(i=s->mb_num-1; i>=0; i--){ 00861 const int mb_xy= s->mb_index2xy[i]; 00862 int error= s->error_status_table[mb_xy]; 00863 00864 if(!s->mbskip_table[mb_xy]) //FIXME partition specific 00865 distance++; 00866 if(error&(1<<error_type)) 00867 distance= 0; 00868 00869 if(s->partitioned_frame){ 00870 if(distance < threshold_part[error_type-1]) 00871 s->error_status_table[mb_xy]|= 1<<error_type; 00872 }else{ 00873 if(distance < threshold) 00874 s->error_status_table[mb_xy]|= 1<<error_type; 00875 } 00876 00877 if(error&VP_START) 00878 distance= 9999999; 00879 } 00880 } 00881 #endif 00882 00883 /* forward mark errors */ 00884 error=0; 00885 for(i=0; i<s->mb_num; i++){ 00886 const int mb_xy= s->mb_index2xy[i]; 00887 int old_error= s->error_status_table[mb_xy]; 00888 00889 if(old_error&VP_START) 00890 error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR); 00891 else{ 00892 error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR); 00893 s->error_status_table[mb_xy]|= error; 00894 } 00895 } 00896 #if 1 00897 /* handle not partitioned case */ 00898 if(!s->partitioned_frame){ 00899 for(i=0; i<s->mb_num; i++){ 00900 const int mb_xy= s->mb_index2xy[i]; 00901 error= s->error_status_table[mb_xy]; 00902 if(error&(AC_ERROR|DC_ERROR|MV_ERROR)) 00903 error|= AC_ERROR|DC_ERROR|MV_ERROR; 00904 s->error_status_table[mb_xy]= error; 00905 } 00906 } 00907 #endif 00908 00909 dc_error= ac_error= mv_error=0; 00910 for(i=0; i<s->mb_num; i++){ 00911 const int mb_xy= s->mb_index2xy[i]; 00912 error= s->error_status_table[mb_xy]; 00913 if(error&DC_ERROR) dc_error ++; 00914 if(error&AC_ERROR) ac_error ++; 00915 if(error&MV_ERROR) mv_error ++; 00916 } 00917 av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error); 00918 00919 is_intra_likely= is_intra_more_likely(s); 00920 00921 /* set unknown mb-type to most likely */ 00922 for(i=0; i<s->mb_num; i++){ 00923 const int mb_xy= s->mb_index2xy[i]; 00924 error= s->error_status_table[mb_xy]; 00925 if(!((error&DC_ERROR) && (error&MV_ERROR))) 00926 continue; 00927 00928 if(is_intra_likely) 00929 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4; 00930 else 00931 s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0; 00932 } 00933 00934 // change inter to intra blocks if no reference frames are available 00935 if (!s->last_picture.data[0] && !s->next_picture.data[0]) 00936 for(i=0; i<s->mb_num; i++){ 00937 const int mb_xy= s->mb_index2xy[i]; 00938 if(!IS_INTRA(s->current_picture.mb_type[mb_xy])) 00939 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4; 00940 } 00941 00942 /* handle inter blocks with damaged AC */ 00943 for(mb_y=0; mb_y<s->mb_height; mb_y++){ 00944 for(mb_x=0; mb_x<s->mb_width; mb_x++){ 00945 const int mb_xy= mb_x + mb_y * s->mb_stride; 00946 const int mb_type= s->current_picture.mb_type[mb_xy]; 00947 int dir = !s->last_picture.data[0]; 00948 error= s->error_status_table[mb_xy]; 00949 00950 if(IS_INTRA(mb_type)) continue; //intra 00951 if(error&MV_ERROR) continue; //inter with damaged MV 00952 if(!(error&AC_ERROR)) continue; //undamaged inter 00953 00954 s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD; 00955 s->mb_intra=0; 00956 s->mb_skipped=0; 00957 if(IS_8X8(mb_type)){ 00958 int mb_index= mb_x*2 + mb_y*2*s->b8_stride; 00959 int j; 00960 s->mv_type = MV_TYPE_8X8; 00961 for(j=0; j<4; j++){ 00962 s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0]; 00963 s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1]; 00964 } 00965 }else{ 00966 s->mv_type = MV_TYPE_16X16; 00967 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0]; 00968 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1]; 00969 } 00970 00971 s->dsp.clear_blocks(s->block[0]); 00972 00973 s->mb_x= mb_x; 00974 s->mb_y= mb_y; 00975 decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/); 00976 } 00977 } 00978 00979 /* guess MVs */ 00980 if(s->pict_type==FF_B_TYPE){ 00981 for(mb_y=0; mb_y<s->mb_height; mb_y++){ 00982 for(mb_x=0; mb_x<s->mb_width; mb_x++){ 00983 int xy= mb_x*2 + mb_y*2*s->b8_stride; 00984 const int mb_xy= mb_x + mb_y * s->mb_stride; 00985 const int mb_type= s->current_picture.mb_type[mb_xy]; 00986 error= s->error_status_table[mb_xy]; 00987 00988 if(IS_INTRA(mb_type)) continue; 00989 if(!(error&MV_ERROR)) continue; //inter with undamaged MV 00990 if(!(error&AC_ERROR)) continue; //undamaged inter 00991 00992 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD; 00993 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD; 00994 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD; 00995 s->mb_intra=0; 00996 s->mv_type = MV_TYPE_16X16; 00997 s->mb_skipped=0; 00998 00999 if(s->pp_time){ 01000 int time_pp= s->pp_time; 01001 int time_pb= s->pb_time; 01002 01003 s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp; 01004 s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp; 01005 s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp; 01006 s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp; 01007 }else{ 01008 s->mv[0][0][0]= 0; 01009 s->mv[0][0][1]= 0; 01010 s->mv[1][0][0]= 0; 01011 s->mv[1][0][1]= 0; 01012 } 01013 01014 s->dsp.clear_blocks(s->block[0]); 01015 s->mb_x= mb_x; 01016 s->mb_y= mb_y; 01017 decode_mb(s, 0); 01018 } 01019 } 01020 }else 01021 guess_mv(s); 01022 01023 /* the filters below are not XvMC compatible, skip them */ 01024 if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) 01025 goto ec_clean; 01026 /* fill DC for inter blocks */ 01027 for(mb_y=0; mb_y<s->mb_height; mb_y++){ 01028 for(mb_x=0; mb_x<s->mb_width; mb_x++){ 01029 int dc, dcu, dcv, y, n; 01030 int16_t *dc_ptr; 01031 uint8_t *dest_y, *dest_cb, *dest_cr; 01032 const int mb_xy= mb_x + mb_y * s->mb_stride; 01033 const int mb_type= s->current_picture.mb_type[mb_xy]; 01034 01035 error= s->error_status_table[mb_xy]; 01036 01037 if(IS_INTRA(mb_type) && s->partitioned_frame) continue; 01038 // if(error&MV_ERROR) continue; //inter data damaged FIXME is this good? 01039 01040 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; 01041 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize; 01042 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize; 01043 01044 dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride]; 01045 for(n=0; n<4; n++){ 01046 dc=0; 01047 for(y=0; y<8; y++){ 01048 int x; 01049 for(x=0; x<8; x++){ 01050 dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize]; 01051 } 01052 } 01053 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3; 01054 } 01055 01056 dcu=dcv=0; 01057 for(y=0; y<8; y++){ 01058 int x; 01059 for(x=0; x<8; x++){ 01060 dcu+=dest_cb[x + y*(s->uvlinesize)]; 01061 dcv+=dest_cr[x + y*(s->uvlinesize)]; 01062 } 01063 } 01064 s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3; 01065 s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3; 01066 } 01067 } 01068 #if 1 01069 /* guess DC for damaged blocks */ 01070 guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1); 01071 guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0); 01072 guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0); 01073 #endif 01074 /* filter luma DC */ 01075 filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride); 01076 01077 #if 1 01078 /* render DC only intra */ 01079 for(mb_y=0; mb_y<s->mb_height; mb_y++){ 01080 for(mb_x=0; mb_x<s->mb_width; mb_x++){ 01081 uint8_t *dest_y, *dest_cb, *dest_cr; 01082 const int mb_xy= mb_x + mb_y * s->mb_stride; 01083 const int mb_type= s->current_picture.mb_type[mb_xy]; 01084 01085 error= s->error_status_table[mb_xy]; 01086 01087 if(IS_INTER(mb_type)) continue; 01088 if(!(error&AC_ERROR)) continue; //undamaged 01089 01090 dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize; 01091 dest_cb= s->current_picture.data[1] + mb_x*8 + mb_y*8 *s->uvlinesize; 01092 dest_cr= s->current_picture.data[2] + mb_x*8 + mb_y*8 *s->uvlinesize; 01093 01094 put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y); 01095 } 01096 } 01097 #endif 01098 01099 if(s->avctx->error_concealment&FF_EC_DEBLOCK){ 01100 /* filter horizontal block boundaries */ 01101 h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); 01102 h_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); 01103 h_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); 01104 01105 /* filter vertical block boundaries */ 01106 v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize , 1); 01107 v_block_filter(s, s->current_picture.data[1], s->mb_width , s->mb_height , s->uvlinesize, 0); 01108 v_block_filter(s, s->current_picture.data[2], s->mb_width , s->mb_height , s->uvlinesize, 0); 01109 } 01110 01111 ec_clean: 01112 /* clean a few tables */ 01113 for(i=0; i<s->mb_num; i++){ 01114 const int mb_xy= s->mb_index2xy[i]; 01115 int error= s->error_status_table[mb_xy]; 01116 01117 if(s->pict_type!=FF_B_TYPE && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){ 01118 s->mbskip_table[mb_xy]=0; 01119 } 01120 s->mbintra_table[mb_xy]=1; 01121 } 01122 }