error_concealment: optimize guess_dc()

Fixes Ticket811
Bug found by: Oana Stratulat

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2011-12-22 00:24:39 +01:00
parent 8d960fbc70
commit a40f43db64
1 changed files with 63 additions and 51 deletions

View File

@ -154,11 +154,68 @@ static void filter181(int16_t *data, int width, int height, int stride){
*/ */
static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, int is_luma){
int b_x, b_y; int b_x, b_y;
int16_t (*col )[4] = av_malloc(stride*h*sizeof( int16_t)*4);
uint16_t (*dist)[4] = av_malloc(stride*h*sizeof(uint16_t)*4);
for(b_y=0; b_y<h; b_y++){
int color= 1024;
int distance= -1;
for(b_x=0; b_x<w; b_x++){
int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color= dc[b_x + b_y*stride];
distance= b_x;
}
col [b_x + b_y*stride][1]= color;
dist[b_x + b_y*stride][1]= distance >= 0 ? b_x-distance : 9999;
}
color= 1024;
distance= -1;
for(b_x=w-1; b_x>=0; b_x--){
int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color= dc[b_x + b_y*stride];
distance= b_x;
}
col [b_x + b_y*stride][0]= color;
dist[b_x + b_y*stride][0]= distance >= 0 ? distance-b_x : 9999;
}
}
for(b_x=0; b_x<w; b_x++){
int color= 1024;
int distance= -1;
for(b_y=0; b_y<h; b_y++){
int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color= dc[b_x + b_y*stride];
distance= b_y;
}
col [b_x + b_y*stride][3]= color;
dist[b_x + b_y*stride][3]= distance >= 0 ? b_y-distance : 9999;
}
color= 1024;
distance= -1;
for(b_y=h-1; b_y>=0; b_y--){
int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color= dc[b_x + b_y*stride];
distance= b_y;
}
col [b_x + b_y*stride][2]= color;
dist[b_x + b_y*stride][2]= distance >= 0 ? distance-b_y : 9999;
}
}
for(b_y=0; b_y<h; b_y++){ for(b_y=0; b_y<h; b_y++){
for(b_x=0; b_x<w; b_x++){ for(b_x=0; b_x<w; b_x++){
int color[4]={1024,1024,1024,1024};
int distance[4]={9999,9999,9999,9999};
int mb_index, error, j; int mb_index, error, j;
int64_t guess, weight_sum; int64_t guess, weight_sum;
@ -169,59 +226,12 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i
if(IS_INTER(s->current_picture.f.mb_type[mb_index])) continue; //inter if(IS_INTER(s->current_picture.f.mb_type[mb_index])) continue; //inter
if(!(error&ER_DC_ERROR)) continue; //dc-ok if(!(error&ER_DC_ERROR)) continue; //dc-ok
/* right block */
for(j=b_x+1; j<w; j++){
int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[0]= dc[j + b_y*stride];
distance[0]= j-b_x;
break;
}
}
/* left block */
for(j=b_x-1; j>=0; j--){
int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[1]= dc[j + b_y*stride];
distance[1]= b_x-j;
break;
}
}
/* bottom block */
for(j=b_y+1; j<h; j++){
int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[2]= dc[b_x + j*stride];
distance[2]= j-b_y;
break;
}
}
/* top block */
for(j=b_y-1; j>=0; j--){
int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride;
int error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[mb_index_j]);
if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[3]= dc[b_x + j*stride];
distance[3]= b_y-j;
break;
}
}
weight_sum=0; weight_sum=0;
guess=0; guess=0;
for(j=0; j<4; j++){ for(j=0; j<4; j++){
int64_t weight= 256*256*256*16/distance[j]; int64_t weight= 256*256*256*16/dist[b_x + b_y*stride][j];
guess+= weight*(int64_t)color[j]; guess+= weight*(int64_t)col[b_x + b_y*stride][j];
weight_sum+= weight; weight_sum+= weight;
} }
guess= (guess + weight_sum/2) / weight_sum; guess= (guess + weight_sum/2) / weight_sum;
@ -229,6 +239,8 @@ static void guess_dc(MpegEncContext *s, int16_t *dc, int w, int h, int stride, i
dc[b_x + b_y*stride]= guess; dc[b_x + b_y*stride]= guess;
} }
} }
av_freep(&col);
av_freep(&dist);
} }
/** /**