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