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

Generated on Fri Sep 16 2011 17:17:36 for FFmpeg by  doxygen 1.7.1