• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

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 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 #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         else if(s->last_picture.data[0] && s->last_picture.motion_val[0]){
00386             const int mb_y= mb_xy / s->mb_stride;
00387             const int mb_x= mb_xy % s->mb_stride;
00388             const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
00389             s->current_picture.motion_val[0][mot_index][0]= s->last_picture.motion_val[0][mot_index][0];
00390             s->current_picture.motion_val[0][mot_index][1]= s->last_picture.motion_val[0][mot_index][1];
00391             s->current_picture.ref_index[0][4*mb_xy]      = s->last_picture.ref_index[0][4*mb_xy];
00392         }
00393     }
00394 
00395     if((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || num_avail <= mb_width/2){
00396         for(mb_y=0; mb_y<s->mb_height; mb_y++){
00397             for(mb_x=0; mb_x<s->mb_width; mb_x++){
00398                 const int mb_xy= mb_x + mb_y*s->mb_stride;
00399 
00400                 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))  continue;
00401                 if(!(s->error_status_table[mb_xy]&MV_ERROR)) continue;
00402 
00403                 s->mv_dir = s->last_picture.data[0] ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
00404                 s->mb_intra=0;
00405                 s->mv_type = MV_TYPE_16X16;
00406                 s->mb_skipped=0;
00407 
00408                 s->dsp.clear_blocks(s->block[0]);
00409 
00410                 s->mb_x= mb_x;
00411                 s->mb_y= mb_y;
00412                 s->mv[0][0][0]= 0;
00413                 s->mv[0][0][1]= 0;
00414                 decode_mb(s, 0);
00415             }
00416         }
00417         return;
00418     }
00419 
00420     for(depth=0;; depth++){
00421         int changed, pass, none_left;
00422 
00423         none_left=1;
00424         changed=1;
00425         for(pass=0; (changed || pass<2) && pass<10; pass++){
00426             int mb_x, mb_y;
00427 int score_sum=0;
00428 
00429             changed=0;
00430             for(mb_y=0; mb_y<s->mb_height; mb_y++){
00431                 for(mb_x=0; mb_x<s->mb_width; mb_x++){
00432                     const int mb_xy= mb_x + mb_y*s->mb_stride;
00433                     int mv_predictor[8][2]={{0}};
00434                     int ref[8]={0};
00435                     int pred_count=0;
00436                     int j;
00437                     int best_score=256*256*256*64;
00438                     int best_pred=0;
00439                     const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
00440                     int prev_x, prev_y, prev_ref;
00441 
00442                     if((mb_x^mb_y^pass)&1) continue;
00443 
00444                     if(fixed[mb_xy]==MV_FROZEN) continue;
00445                     assert(!IS_INTRA(s->current_picture.mb_type[mb_xy]));
00446                     assert(s->last_picture_ptr && s->last_picture_ptr->data[0]);
00447 
00448                     j=0;
00449                     if(mb_x>0           && fixed[mb_xy-1        ]==MV_FROZEN) j=1;
00450                     if(mb_x+1<mb_width  && fixed[mb_xy+1        ]==MV_FROZEN) j=1;
00451                     if(mb_y>0           && fixed[mb_xy-mb_stride]==MV_FROZEN) j=1;
00452                     if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_FROZEN) j=1;
00453                     if(j==0) continue;
00454 
00455                     j=0;
00456                     if(mb_x>0           && fixed[mb_xy-1        ]==MV_CHANGED) j=1;
00457                     if(mb_x+1<mb_width  && fixed[mb_xy+1        ]==MV_CHANGED) j=1;
00458                     if(mb_y>0           && fixed[mb_xy-mb_stride]==MV_CHANGED) j=1;
00459                     if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]==MV_CHANGED) j=1;
00460                     if(j==0 && pass>1) continue;
00461 
00462                     none_left=0;
00463 
00464                     if(mb_x>0 && fixed[mb_xy-1]){
00465                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_step][0];
00466                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_step][1];
00467                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy-1)];
00468                         pred_count++;
00469                     }
00470                     if(mb_x+1<mb_width && fixed[mb_xy+1]){
00471                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_step][0];
00472                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_step][1];
00473                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy+1)];
00474                         pred_count++;
00475                     }
00476                     if(mb_y>0 && fixed[mb_xy-mb_stride]){
00477                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][0];
00478                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index - mot_stride*mot_step][1];
00479                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy-s->mb_stride)];
00480                         pred_count++;
00481                     }
00482                     if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
00483                         mv_predictor[pred_count][0]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][0];
00484                         mv_predictor[pred_count][1]= s->current_picture.motion_val[0][mot_index + mot_stride*mot_step][1];
00485                         ref         [pred_count]   = s->current_picture.ref_index[0][4*(mb_xy+s->mb_stride)];
00486                         pred_count++;
00487                     }
00488                     if(pred_count==0) continue;
00489 
00490                     if(pred_count>1){
00491                         int sum_x=0, sum_y=0, sum_r=0;
00492                         int max_x, max_y, min_x, min_y, max_r, min_r;
00493 
00494                         for(j=0; j<pred_count; j++){
00495                             sum_x+= mv_predictor[j][0];
00496                             sum_y+= mv_predictor[j][1];
00497                             sum_r+= ref[j];
00498                             if(j && ref[j] != ref[j-1])
00499                                 goto skip_mean_and_median;
00500                         }
00501 
00502                         /* mean */
00503                         mv_predictor[pred_count][0] = sum_x/j;
00504                         mv_predictor[pred_count][1] = sum_y/j;
00505                         ref         [pred_count]    = sum_r/j;
00506 
00507                         /* median */
00508                         if(pred_count>=3){
00509                             min_y= min_x= min_r= 99999;
00510                             max_y= max_x= max_r=-99999;
00511                         }else{
00512                             min_x=min_y=max_x=max_y=min_r=max_r=0;
00513                         }
00514                         for(j=0; j<pred_count; j++){
00515                             max_x= FFMAX(max_x, mv_predictor[j][0]);
00516                             max_y= FFMAX(max_y, mv_predictor[j][1]);
00517                             max_r= FFMAX(max_r, ref[j]);
00518                             min_x= FFMIN(min_x, mv_predictor[j][0]);
00519                             min_y= FFMIN(min_y, mv_predictor[j][1]);
00520                             min_r= FFMIN(min_r, ref[j]);
00521                         }
00522                         mv_predictor[pred_count+1][0] = sum_x - max_x - min_x;
00523                         mv_predictor[pred_count+1][1] = sum_y - max_y - min_y;
00524                         ref         [pred_count+1]    = sum_r - max_r - min_r;
00525 
00526                         if(pred_count==4){
00527                             mv_predictor[pred_count+1][0] /= 2;
00528                             mv_predictor[pred_count+1][1] /= 2;
00529                             ref         [pred_count+1]    /= 2;
00530                         }
00531                         pred_count+=2;
00532                     }
00533 skip_mean_and_median:
00534 
00535                     /* zero MV */
00536                     pred_count++;
00537 
00538                     if (!fixed[mb_xy] && 0) {
00539                         if (s->avctx->codec_id == CODEC_ID_H264) {
00540                             // FIXME
00541                         } else {
00542                             ff_thread_await_progress((AVFrame *) s->last_picture_ptr,
00543                                                      mb_y, 0);
00544                         }
00545                         if (!s->last_picture.motion_val[0] ||
00546                             !s->last_picture.ref_index[0])
00547                             goto skip_last_mv;
00548                         prev_x = s->last_picture.motion_val[0][mot_index][0];
00549                         prev_y = s->last_picture.motion_val[0][mot_index][1];
00550                         prev_ref = s->last_picture.ref_index[0][4*mb_xy];
00551                     } else {
00552                         prev_x = s->current_picture.motion_val[0][mot_index][0];
00553                         prev_y = s->current_picture.motion_val[0][mot_index][1];
00554                         prev_ref = s->current_picture.ref_index[0][4*mb_xy];
00555                     }
00556 
00557                     /* last MV */
00558                     mv_predictor[pred_count][0]= prev_x;
00559                     mv_predictor[pred_count][1]= prev_y;
00560                     ref         [pred_count]   = prev_ref;
00561                     pred_count++;
00562                 skip_last_mv:
00563 
00564                     s->mv_dir = MV_DIR_FORWARD;
00565                     s->mb_intra=0;
00566                     s->mv_type = MV_TYPE_16X16;
00567                     s->mb_skipped=0;
00568 
00569                     s->dsp.clear_blocks(s->block[0]);
00570 
00571                     s->mb_x= mb_x;
00572                     s->mb_y= mb_y;
00573 
00574                     for(j=0; j<pred_count; j++){
00575                         int score=0;
00576                         uint8_t *src= s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
00577 
00578                         s->current_picture.motion_val[0][mot_index][0]= s->mv[0][0][0]= mv_predictor[j][0];
00579                         s->current_picture.motion_val[0][mot_index][1]= s->mv[0][0][1]= mv_predictor[j][1];
00580 
00581                         if(ref[j]<0) //predictor intra or otherwise not available
00582                             continue;
00583 
00584                         decode_mb(s, ref[j]);
00585 
00586                         if(mb_x>0 && fixed[mb_xy-1]){
00587                             int k;
00588                             for(k=0; k<16; k++)
00589                                 score += FFABS(src[k*s->linesize-1 ]-src[k*s->linesize   ]);
00590                         }
00591                         if(mb_x+1<mb_width && fixed[mb_xy+1]){
00592                             int k;
00593                             for(k=0; k<16; k++)
00594                                 score += FFABS(src[k*s->linesize+15]-src[k*s->linesize+16]);
00595                         }
00596                         if(mb_y>0 && fixed[mb_xy-mb_stride]){
00597                             int k;
00598                             for(k=0; k<16; k++)
00599                                 score += FFABS(src[k-s->linesize   ]-src[k               ]);
00600                         }
00601                         if(mb_y+1<mb_height && fixed[mb_xy+mb_stride]){
00602                             int k;
00603                             for(k=0; k<16; k++)
00604                                 score += FFABS(src[k+s->linesize*15]-src[k+s->linesize*16]);
00605                         }
00606 
00607                         if(score <= best_score){ // <= will favor the last MV
00608                             best_score= score;
00609                             best_pred= j;
00610                         }
00611                     }
00612 score_sum+= best_score;
00613                     s->mv[0][0][0]= mv_predictor[best_pred][0];
00614                     s->mv[0][0][1]= mv_predictor[best_pred][1];
00615 
00616                     for(i=0; i<mot_step; i++)
00617                         for(j=0; j<mot_step; j++){
00618                             s->current_picture.motion_val[0][mot_index+i+j*mot_stride][0]= s->mv[0][0][0];
00619                             s->current_picture.motion_val[0][mot_index+i+j*mot_stride][1]= s->mv[0][0][1];
00620                         }
00621 
00622                     decode_mb(s, ref[best_pred]);
00623 
00624 
00625                     if(s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y){
00626                         fixed[mb_xy]=MV_CHANGED;
00627                         changed++;
00628                     }else
00629                         fixed[mb_xy]=MV_UNCHANGED;
00630                 }
00631             }
00632 
00633 //            printf(".%d/%d", changed, score_sum); fflush(stdout);
00634         }
00635 
00636         if(none_left)
00637             return;
00638 
00639         for(i=0; i<s->mb_num; i++){
00640             int mb_xy= s->mb_index2xy[i];
00641             if(fixed[mb_xy])
00642                 fixed[mb_xy]=MV_FROZEN;
00643         }
00644 //        printf(":"); fflush(stdout);
00645     }
00646 }
00647 
00648 static int is_intra_more_likely(MpegEncContext *s){
00649     int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y;
00650 
00651     if(!s->last_picture_ptr || !s->last_picture_ptr->data[0]) return 1; //no previous frame available -> use spatial prediction
00652 
00653     undamaged_count=0;
00654     for(i=0; i<s->mb_num; i++){
00655         const int mb_xy= s->mb_index2xy[i];
00656         const int error= s->error_status_table[mb_xy];
00657         if(!((error&DC_ERROR) && (error&MV_ERROR)))
00658             undamaged_count++;
00659     }
00660 
00661     if(s->codec_id == CODEC_ID_H264){
00662         H264Context *h= (void*)s;
00663         if (h->list_count <= 0 || h->ref_count[0] <= 0 || !h->ref_list[0][0].data[0])
00664             return 1;
00665     }
00666 
00667     if(undamaged_count < 5) return 0; //almost all MBs damaged -> use temporal prediction
00668 
00669     //prevent dsp.sad() check, that requires access to the image
00670     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration && s->pict_type == AV_PICTURE_TYPE_I)
00671         return 1;
00672 
00673     skip_amount= FFMAX(undamaged_count/50, 1); //check only upto 50 MBs
00674     is_intra_likely=0;
00675 
00676     j=0;
00677     for(mb_y= 0; mb_y<s->mb_height-1; mb_y++){
00678         for(mb_x= 0; mb_x<s->mb_width; mb_x++){
00679             int error;
00680             const int mb_xy= mb_x + mb_y*s->mb_stride;
00681 
00682             error= s->error_status_table[mb_xy];
00683             if((error&DC_ERROR) && (error&MV_ERROR))
00684                 continue; //skip damaged
00685 
00686             j++;
00687             if((j%skip_amount) != 0) continue; //skip a few to speed things up
00688 
00689             if(s->pict_type==AV_PICTURE_TYPE_I){
00690                 uint8_t *mb_ptr     = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
00691                 uint8_t *last_mb_ptr= s->last_picture.data   [0] + mb_x*16 + mb_y*16*s->linesize;
00692 
00693                 if (s->avctx->codec_id == CODEC_ID_H264) {
00694                     // FIXME
00695                 } else {
00696                     ff_thread_await_progress((AVFrame *) s->last_picture_ptr,
00697                                              mb_y, 0);
00698                 }
00699                 is_intra_likely += s->dsp.sad[0](NULL, last_mb_ptr, mb_ptr                    , s->linesize, 16);
00700                 // FIXME need await_progress() here
00701                 is_intra_likely -= s->dsp.sad[0](NULL, last_mb_ptr, last_mb_ptr+s->linesize*16, s->linesize, 16);
00702             }else{
00703                 if(IS_INTRA(s->current_picture.mb_type[mb_xy]))
00704                    is_intra_likely++;
00705                 else
00706                    is_intra_likely--;
00707             }
00708         }
00709     }
00710 //printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type);
00711     return is_intra_likely > 0;
00712 }
00713 
00714 void ff_er_frame_start(MpegEncContext *s){
00715     if(!s->error_recognition) return;
00716 
00717     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));
00718     s->error_count= 3*s->mb_num;
00719     s->error_occurred = 0;
00720 }
00721 
00728 void ff_er_add_slice(MpegEncContext *s, int startx, int starty, int endx, int endy, int status){
00729     const int start_i= av_clip(startx + starty * s->mb_width    , 0, s->mb_num-1);
00730     const int end_i  = av_clip(endx   + endy   * s->mb_width    , 0, s->mb_num);
00731     const int start_xy= s->mb_index2xy[start_i];
00732     const int end_xy  = s->mb_index2xy[end_i];
00733     int mask= -1;
00734 
00735     if(s->avctx->hwaccel)
00736         return;
00737 
00738     if(start_i > end_i || start_xy > end_xy){
00739         av_log(s->avctx, AV_LOG_ERROR, "internal error, slice end before start\n");
00740         return;
00741     }
00742 
00743     if(!s->error_recognition) return;
00744 
00745     mask &= ~VP_START;
00746     if(status & (AC_ERROR|AC_END)){
00747         mask &= ~(AC_ERROR|AC_END);
00748         s->error_count -= end_i - start_i + 1;
00749     }
00750     if(status & (DC_ERROR|DC_END)){
00751         mask &= ~(DC_ERROR|DC_END);
00752         s->error_count -= end_i - start_i + 1;
00753     }
00754     if(status & (MV_ERROR|MV_END)){
00755         mask &= ~(MV_ERROR|MV_END);
00756         s->error_count -= end_i - start_i + 1;
00757     }
00758 
00759     if(status & (AC_ERROR|DC_ERROR|MV_ERROR)) {
00760         s->error_occurred = 1;
00761         s->error_count= INT_MAX;
00762     }
00763 
00764     if(mask == ~0x7F){
00765         memset(&s->error_status_table[start_xy], 0, (end_xy - start_xy) * sizeof(uint8_t));
00766     }else{
00767         int i;
00768         for(i=start_xy; i<end_xy; i++){
00769             s->error_status_table[ i ] &= mask;
00770         }
00771     }
00772 
00773     if(end_i == s->mb_num)
00774         s->error_count= INT_MAX;
00775     else{
00776         s->error_status_table[end_xy] &= mask;
00777         s->error_status_table[end_xy] |= status;
00778     }
00779 
00780     s->error_status_table[start_xy] |= VP_START;
00781 
00782     if(start_xy > 0 && s->avctx->thread_count <= 1 && s->avctx->skip_top*s->mb_width < start_i){
00783         int prev_status= s->error_status_table[ s->mb_index2xy[start_i - 1] ];
00784 
00785         prev_status &= ~ VP_START;
00786         if(prev_status != (MV_END|DC_END|AC_END)) s->error_count= INT_MAX;
00787     }
00788 }
00789 
00790 void ff_er_frame_end(MpegEncContext *s){
00791     int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error;
00792     int distance;
00793     int threshold_part[4]= {100,100,100};
00794     int threshold= 50;
00795     int is_intra_likely;
00796     int size = s->b8_stride * 2 * s->mb_height;
00797     Picture *pic= s->current_picture_ptr;
00798 
00799     if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
00800        s->avctx->hwaccel ||
00801        s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
00802        s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
00803        s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) return;
00804 
00805     if(s->current_picture.motion_val[0] == NULL){
00806         av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
00807 
00808         for(i=0; i<2; i++){
00809             pic->ref_index[i]= av_mallocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t));
00810             pic->motion_val_base[i]= av_mallocz((size+4) * 2 * sizeof(uint16_t));
00811             pic->motion_val[i]= pic->motion_val_base[i]+4;
00812         }
00813         pic->motion_subsample_log2= 3;
00814         s->current_picture= *s->current_picture_ptr;
00815     }
00816 
00817     if(s->avctx->debug&FF_DEBUG_ER){
00818         for(mb_y=0; mb_y<s->mb_height; mb_y++){
00819             for(mb_x=0; mb_x<s->mb_width; mb_x++){
00820                 int status= s->error_status_table[mb_x + mb_y*s->mb_stride];
00821 
00822                 av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status);
00823             }
00824             av_log(s->avctx, AV_LOG_DEBUG, "\n");
00825         }
00826     }
00827 
00828 #if 1
00829     /* handle overlapping slices */
00830     for(error_type=1; error_type<=3; error_type++){
00831         int end_ok=0;
00832 
00833         for(i=s->mb_num-1; i>=0; i--){
00834             const int mb_xy= s->mb_index2xy[i];
00835             int error= s->error_status_table[mb_xy];
00836 
00837             if(error&(1<<error_type))
00838                 end_ok=1;
00839             if(error&(8<<error_type))
00840                 end_ok=1;
00841 
00842             if(!end_ok)
00843                 s->error_status_table[mb_xy]|= 1<<error_type;
00844 
00845             if(error&VP_START)
00846                 end_ok=0;
00847         }
00848     }
00849 #endif
00850 #if 1
00851     /* handle slices with partitions of different length */
00852     if(s->partitioned_frame){
00853         int end_ok=0;
00854 
00855         for(i=s->mb_num-1; i>=0; i--){
00856             const int mb_xy= s->mb_index2xy[i];
00857             int error= s->error_status_table[mb_xy];
00858 
00859             if(error&AC_END)
00860                 end_ok=0;
00861             if((error&MV_END) || (error&DC_END) || (error&AC_ERROR))
00862                 end_ok=1;
00863 
00864             if(!end_ok)
00865                 s->error_status_table[mb_xy]|= AC_ERROR;
00866 
00867             if(error&VP_START)
00868                 end_ok=0;
00869         }
00870     }
00871 #endif
00872     /* handle missing slices */
00873     if(s->error_recognition>=4){
00874         int end_ok=1;
00875 
00876         for(i=s->mb_num-2; i>=s->mb_width+100; i--){ //FIXME +100 hack
00877             const int mb_xy= s->mb_index2xy[i];
00878             int error1= s->error_status_table[mb_xy  ];
00879             int error2= s->error_status_table[s->mb_index2xy[i+1]];
00880 
00881             if(error1&VP_START)
00882                 end_ok=1;
00883 
00884             if(   error2==(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
00885                && error1!=(VP_START|DC_ERROR|AC_ERROR|MV_ERROR|AC_END|DC_END|MV_END)
00886                && ((error1&AC_END) || (error1&DC_END) || (error1&MV_END))){ //end & uninit
00887                 end_ok=0;
00888             }
00889 
00890             if(!end_ok)
00891                 s->error_status_table[mb_xy]|= DC_ERROR|AC_ERROR|MV_ERROR;
00892         }
00893     }
00894 
00895 #if 1
00896     /* backward mark errors */
00897     distance=9999999;
00898     for(error_type=1; error_type<=3; error_type++){
00899         for(i=s->mb_num-1; i>=0; i--){
00900             const int mb_xy= s->mb_index2xy[i];
00901             int error= s->error_status_table[mb_xy];
00902 
00903             if(!s->mbskip_table[mb_xy]) //FIXME partition specific
00904                 distance++;
00905             if(error&(1<<error_type))
00906                 distance= 0;
00907 
00908             if(s->partitioned_frame){
00909                 if(distance < threshold_part[error_type-1])
00910                     s->error_status_table[mb_xy]|= 1<<error_type;
00911             }else{
00912                 if(distance < threshold)
00913                     s->error_status_table[mb_xy]|= 1<<error_type;
00914             }
00915 
00916             if(error&VP_START)
00917                 distance= 9999999;
00918         }
00919     }
00920 #endif
00921 
00922     /* forward mark errors */
00923     error=0;
00924     for(i=0; i<s->mb_num; i++){
00925         const int mb_xy= s->mb_index2xy[i];
00926         int old_error= s->error_status_table[mb_xy];
00927 
00928         if(old_error&VP_START)
00929             error= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
00930         else{
00931             error|= old_error& (DC_ERROR|AC_ERROR|MV_ERROR);
00932             s->error_status_table[mb_xy]|= error;
00933         }
00934     }
00935 #if 1
00936     /* handle not partitioned case */
00937     if(!s->partitioned_frame){
00938         for(i=0; i<s->mb_num; i++){
00939             const int mb_xy= s->mb_index2xy[i];
00940             error= s->error_status_table[mb_xy];
00941             if(error&(AC_ERROR|DC_ERROR|MV_ERROR))
00942                 error|= AC_ERROR|DC_ERROR|MV_ERROR;
00943             s->error_status_table[mb_xy]= error;
00944         }
00945     }
00946 #endif
00947 
00948     dc_error= ac_error= mv_error=0;
00949     for(i=0; i<s->mb_num; i++){
00950         const int mb_xy= s->mb_index2xy[i];
00951         error= s->error_status_table[mb_xy];
00952         if(error&DC_ERROR) dc_error ++;
00953         if(error&AC_ERROR) ac_error ++;
00954         if(error&MV_ERROR) mv_error ++;
00955     }
00956     av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors\n", dc_error, ac_error, mv_error);
00957 
00958     is_intra_likely= is_intra_more_likely(s);
00959 
00960     /* set unknown mb-type to most likely */
00961     for(i=0; i<s->mb_num; i++){
00962         const int mb_xy= s->mb_index2xy[i];
00963         error= s->error_status_table[mb_xy];
00964         if(!((error&DC_ERROR) && (error&MV_ERROR)))
00965             continue;
00966 
00967         if(is_intra_likely)
00968             s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
00969         else
00970             s->current_picture.mb_type[mb_xy]= MB_TYPE_16x16 | MB_TYPE_L0;
00971     }
00972 
00973     // change inter to intra blocks if no reference frames are available
00974     if (!s->last_picture.data[0] && !s->next_picture.data[0])
00975         for(i=0; i<s->mb_num; i++){
00976             const int mb_xy= s->mb_index2xy[i];
00977             if(!IS_INTRA(s->current_picture.mb_type[mb_xy]))
00978                 s->current_picture.mb_type[mb_xy]= MB_TYPE_INTRA4x4;
00979         }
00980 
00981     /* handle inter blocks with damaged AC */
00982     for(mb_y=0; mb_y<s->mb_height; mb_y++){
00983         for(mb_x=0; mb_x<s->mb_width; mb_x++){
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             int dir = !s->last_picture.data[0];
00987             error= s->error_status_table[mb_xy];
00988 
00989             if(IS_INTRA(mb_type)) continue; //intra
00990             if(error&MV_ERROR) continue;              //inter with damaged MV
00991             if(!(error&AC_ERROR)) continue;           //undamaged inter
00992 
00993             s->mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD;
00994             s->mb_intra=0;
00995             s->mb_skipped=0;
00996             if(IS_8X8(mb_type)){
00997                 int mb_index= mb_x*2 + mb_y*2*s->b8_stride;
00998                 int j;
00999                 s->mv_type = MV_TYPE_8X8;
01000                 for(j=0; j<4; j++){
01001                     s->mv[0][j][0] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][0];
01002                     s->mv[0][j][1] = s->current_picture.motion_val[dir][ mb_index + (j&1) + (j>>1)*s->b8_stride ][1];
01003                 }
01004             }else{
01005                 s->mv_type = MV_TYPE_16X16;
01006                 s->mv[0][0][0] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][0];
01007                 s->mv[0][0][1] = s->current_picture.motion_val[dir][ mb_x*2 + mb_y*2*s->b8_stride ][1];
01008             }
01009 
01010             s->dsp.clear_blocks(s->block[0]);
01011 
01012             s->mb_x= mb_x;
01013             s->mb_y= mb_y;
01014             decode_mb(s, 0/*FIXME h264 partitioned slices need this set*/);
01015         }
01016     }
01017 
01018     /* guess MVs */
01019     if(s->pict_type==AV_PICTURE_TYPE_B){
01020         for(mb_y=0; mb_y<s->mb_height; mb_y++){
01021             for(mb_x=0; mb_x<s->mb_width; mb_x++){
01022                 int xy= mb_x*2 + mb_y*2*s->b8_stride;
01023                 const int mb_xy= mb_x + mb_y * s->mb_stride;
01024                 const int mb_type= s->current_picture.mb_type[mb_xy];
01025                 error= s->error_status_table[mb_xy];
01026 
01027                 if(IS_INTRA(mb_type)) continue;
01028                 if(!(error&MV_ERROR)) continue;           //inter with undamaged MV
01029                 if(!(error&AC_ERROR)) continue;           //undamaged inter
01030 
01031                 s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD;
01032                 if(!s->last_picture.data[0]) s->mv_dir &= ~MV_DIR_FORWARD;
01033                 if(!s->next_picture.data[0]) s->mv_dir &= ~MV_DIR_BACKWARD;
01034                 s->mb_intra=0;
01035                 s->mv_type = MV_TYPE_16X16;
01036                 s->mb_skipped=0;
01037 
01038                 if(s->pp_time){
01039                     int time_pp= s->pp_time;
01040                     int time_pb= s->pb_time;
01041 
01042                     if (s->avctx->codec_id == CODEC_ID_H264) {
01043                         //FIXME
01044                     } else {
01045                         ff_thread_await_progress((AVFrame *) s->next_picture_ptr,
01046                                                  mb_y, 0);
01047                     }
01048                     s->mv[0][0][0] = s->next_picture.motion_val[0][xy][0]*time_pb/time_pp;
01049                     s->mv[0][0][1] = s->next_picture.motion_val[0][xy][1]*time_pb/time_pp;
01050                     s->mv[1][0][0] = s->next_picture.motion_val[0][xy][0]*(time_pb - time_pp)/time_pp;
01051                     s->mv[1][0][1] = s->next_picture.motion_val[0][xy][1]*(time_pb - time_pp)/time_pp;
01052                 }else{
01053                     s->mv[0][0][0]= 0;
01054                     s->mv[0][0][1]= 0;
01055                     s->mv[1][0][0]= 0;
01056                     s->mv[1][0][1]= 0;
01057                 }
01058 
01059                 s->dsp.clear_blocks(s->block[0]);
01060                 s->mb_x= mb_x;
01061                 s->mb_y= mb_y;
01062                 decode_mb(s, 0);
01063             }
01064         }
01065     }else
01066         guess_mv(s);
01067 
01068     /* the filters below are not XvMC compatible, skip them */
01069     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration)
01070         goto ec_clean;
01071     /* fill DC for inter blocks */
01072     for(mb_y=0; mb_y<s->mb_height; mb_y++){
01073         for(mb_x=0; mb_x<s->mb_width; mb_x++){
01074             int dc, dcu, dcv, y, n;
01075             int16_t *dc_ptr;
01076             uint8_t *dest_y, *dest_cb, *dest_cr;
01077             const int mb_xy= mb_x + mb_y * s->mb_stride;
01078             const int mb_type= s->current_picture.mb_type[mb_xy];
01079 
01080             error= s->error_status_table[mb_xy];
01081 
01082             if(IS_INTRA(mb_type) && s->partitioned_frame) continue;
01083 //            if(error&MV_ERROR) continue; //inter data damaged FIXME is this good?
01084 
01085             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
01086             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
01087             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
01088 
01089             dc_ptr= &s->dc_val[0][mb_x*2 + mb_y*2*s->b8_stride];
01090             for(n=0; n<4; n++){
01091                 dc=0;
01092                 for(y=0; y<8; y++){
01093                     int x;
01094                     for(x=0; x<8; x++){
01095                        dc+= dest_y[x + (n&1)*8 + (y + (n>>1)*8)*s->linesize];
01096                     }
01097                 }
01098                 dc_ptr[(n&1) + (n>>1)*s->b8_stride]= (dc+4)>>3;
01099             }
01100 
01101             dcu=dcv=0;
01102             for(y=0; y<8; y++){
01103                 int x;
01104                 for(x=0; x<8; x++){
01105                     dcu+=dest_cb[x + y*(s->uvlinesize)];
01106                     dcv+=dest_cr[x + y*(s->uvlinesize)];
01107                 }
01108             }
01109             s->dc_val[1][mb_x + mb_y*s->mb_stride]= (dcu+4)>>3;
01110             s->dc_val[2][mb_x + mb_y*s->mb_stride]= (dcv+4)>>3;
01111         }
01112     }
01113 #if 1
01114     /* guess DC for damaged blocks */
01115     guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1);
01116     guess_dc(s, s->dc_val[1], s->mb_width  , s->mb_height  , s->mb_stride, 0);
01117     guess_dc(s, s->dc_val[2], s->mb_width  , s->mb_height  , s->mb_stride, 0);
01118 #endif
01119     /* filter luma DC */
01120     filter181(s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride);
01121 
01122 #if 1
01123     /* render DC only intra */
01124     for(mb_y=0; mb_y<s->mb_height; mb_y++){
01125         for(mb_x=0; mb_x<s->mb_width; mb_x++){
01126             uint8_t *dest_y, *dest_cb, *dest_cr;
01127             const int mb_xy= mb_x + mb_y * s->mb_stride;
01128             const int mb_type= s->current_picture.mb_type[mb_xy];
01129 
01130             error= s->error_status_table[mb_xy];
01131 
01132             if(IS_INTER(mb_type)) continue;
01133             if(!(error&AC_ERROR)) continue;              //undamaged
01134 
01135             dest_y = s->current_picture.data[0] + mb_x*16 + mb_y*16*s->linesize;
01136             dest_cb= s->current_picture.data[1] + mb_x*8  + mb_y*8 *s->uvlinesize;
01137             dest_cr= s->current_picture.data[2] + mb_x*8  + mb_y*8 *s->uvlinesize;
01138 
01139             put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y);
01140         }
01141     }
01142 #endif
01143 
01144     if(s->avctx->error_concealment&FF_EC_DEBLOCK){
01145         /* filter horizontal block boundaries */
01146         h_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
01147         h_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
01148         h_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
01149 
01150         /* filter vertical block boundaries */
01151         v_block_filter(s, s->current_picture.data[0], s->mb_width*2, s->mb_height*2, s->linesize  , 1);
01152         v_block_filter(s, s->current_picture.data[1], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
01153         v_block_filter(s, s->current_picture.data[2], s->mb_width  , s->mb_height  , s->uvlinesize, 0);
01154     }
01155 
01156 ec_clean:
01157     /* clean a few tables */
01158     for(i=0; i<s->mb_num; i++){
01159         const int mb_xy= s->mb_index2xy[i];
01160         int error= s->error_status_table[mb_xy];
01161 
01162         if(s->pict_type!=AV_PICTURE_TYPE_B && (error&(DC_ERROR|MV_ERROR|AC_ERROR))){
01163             s->mbskip_table[mb_xy]=0;
01164         }
01165         s->mbintra_table[mb_xy]=1;
01166     }
01167 }

Generated on Fri Feb 22 2013 07:24:26 for FFmpeg by  doxygen 1.7.1