Libav 0.7.1
libavcodec/error_resilience.c
Go to the documentation of this file.
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 }