Commit a40f43db authored by Michael Niedermayer's avatar Michael Niedermayer

error_concealment: optimize guess_dc()

Fixes Ticket811
Bug found by: Oana Stratulat
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 8d960fbc
...@@ -154,74 +154,84 @@ static void filter181(int16_t *data, int width, int height, int stride){ ...@@ -154,74 +154,84 @@ 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++){ for(b_y=0; b_y<h; b_y++){
int color= 1024;
int distance= -1;
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 mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
int distance[4]={9999,9999,9999,9999};
int mb_index, error, j;
int64_t guess, weight_sum;
mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
error= s->error_status_table[mb_index];
if(IS_INTER(s->current_picture.f.mb_type[mb_index])) continue; //inter
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 error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[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)){ if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[0]= dc[j + b_y*stride]; color= dc[b_x + b_y*stride];
distance[0]= j-b_x; distance= b_x;
break;
} }
col [b_x + b_y*stride][1]= color;
dist[b_x + b_y*stride][1]= distance >= 0 ? b_x-distance : 9999;
} }
color= 1024;
/* left block */ distance= -1;
for(j=b_x-1; j>=0; j--){ for(b_x=w-1; b_x>=0; b_x--){
int mb_index_j= (j>>is_luma) + (b_y>>is_luma)*s->mb_stride; 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 error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[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)){ if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[1]= dc[j + b_y*stride]; color= dc[b_x + b_y*stride];
distance[1]= b_x-j; distance= b_x;
break;
} }
col [b_x + b_y*stride][0]= color;
dist[b_x + b_y*stride][0]= distance >= 0 ? distance-b_x : 9999;
} }
}
/* bottom block */ for(b_x=0; b_x<w; b_x++){
for(j=b_y+1; j<h; j++){ int color= 1024;
int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride; 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 error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[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)){ if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[2]= dc[b_x + j*stride]; color= dc[b_x + b_y*stride];
distance[2]= j-b_y; distance= b_y;
break;
} }
col [b_x + b_y*stride][3]= color;
dist[b_x + b_y*stride][3]= distance >= 0 ? b_y-distance : 9999;
} }
color= 1024;
/* top block */ distance= -1;
for(j=b_y-1; j>=0; j--){ for(b_y=h-1; b_y>=0; b_y--){
int mb_index_j= (b_x>>is_luma) + (j>>is_luma)*s->mb_stride; 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 error_j= s->error_status_table[mb_index_j];
int intra_j = IS_INTRA(s->current_picture.f.mb_type[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)){ if(intra_j==0 || !(error_j&ER_DC_ERROR)){
color[3]= dc[b_x + j*stride]; color= dc[b_x + b_y*stride];
distance[3]= b_y-j; distance= b_y;
break; }
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_x=0; b_x<w; b_x++){
int mb_index, error, j;
int64_t guess, weight_sum;
mb_index= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
error= s->error_status_table[mb_index];
if(IS_INTER(s->current_picture.f.mb_type[mb_index])) continue; //inter
if(!(error&ER_DC_ERROR)) continue; //dc-ok
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 ...@@ -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);
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment