--- postprocessing.c 2003/05/03 23:26:55 1.1 +++ postprocessing.c 2003/05/03 23:26:55 1.1.2.1 @@ -0,0 +1,202 @@ +#include +#include +#include + +#include "../portab.h" +#include "../global.h" +#include "image.h" +#include "postprocessing.h" + +void +image_deblock(IMAGE * img, int edged_width, + const MACROBLOCK * mbs, int mb_width, int mb_height, int mb_stride, + int flags) +{ + const int edged_width2 = edged_width /2; + int i,j; + int quant; + + /* luma: j,i in block units */ + if ((flags & XVID_DEC_DEBLOCKY)) + { + for (j = 1; j < mb_height*2; j++) /* horizontal deblocking */ + for (i = 0; i < mb_width*2; i++) + { + quant = mbs[(j+0)/2*mb_stride + (i/2)].quant; + deblock8x8_h(img->y + j*8*edged_width + i*8, edged_width, quant); + } + + for (j = 0; j < mb_height*2; j++) /* vertical deblocking */ + for (i = 1; i < mb_width*2; i++) + { + quant = mbs[(j+0)/2*mb_stride + (i/2)].quant; + deblock8x8_v(img->y + j*8*edged_width + i*8, edged_width, quant); + } + } + + + /* chroma */ + if ((flags & XVID_DEC_DEBLOCKUV)) + { + for (j = 1; j < mb_height; j++) /* horizontal deblocking */ + for (i = 0; i < mb_width; i++) + { + quant = mbs[(j+0)*mb_stride + i].quant; + deblock8x8_h(img->u + j*8*edged_width2 + i*8, edged_width2, quant); + deblock8x8_h(img->v + j*8*edged_width2 + i*8, edged_width2, quant); + } + + for (j = 0; j < mb_height; j++) /* vertical deblocking */ + for (i = 1; i < mb_width; i++) + { + quant = mbs[(j+0)*mb_stride + i].quant; + deblock8x8_v(img->u + j*8*edged_width2 + i*8, edged_width2, quant); + deblock8x8_v(img->v + j*8*edged_width2 + i*8, edged_width2, quant); + } + } +} + +#define THR1 2 +#define THR2 6 + +void deblock8x8_h(uint8_t *img, int stride, int quant) +{ + int i, j; + int eq_cnt; + uint8_t *v[10], p0, p9; + int min, max; + int a30, a31, a32; + int diff, limit; + + for(j = 0; j < 8; j++) { + eq_cnt = 0; + + /* Load pixel addresses for filtering */ + + for(i = 0; i < 10; i++) + v[i] = img + (i-5)*stride + j; + + /* First, decide whether to use default or DC-offset mode */ + + for(i = 0; i < 9; i++) + { + if(ABS(*v[i] - *v[(i+1)]) < THR1) + eq_cnt++; + } + + if(eq_cnt < THR2) { /* Default mode */ + + a30 = (*v[3] * 2 - *v[4] * 5 + *v[5] * 5 - *v[6] * 2); + + if(ABS(a30) < 8*quant) { + a31 = (*v[1] * 2 - *v[2] * 5 + *v[3] * 5 - *v[4] * 2); + a32 = (*v[5] * 2 - *v[6] * 5 + *v[7] * 5 - *v[8] * 2); + + diff = (5 * ((SIGN(a30) * MIN(ABS(a30), MIN(ABS(a31), ABS(a32)))) - a30) + 32) >> 6; + limit = (*v[4] - *v[5]) / 2; + + if (limit > 0) + diff = (diff < 0) ? 0 : ((diff > limit) ? limit : diff); + else + diff = (diff > 0) ? 0 : ((diff < limit) ? limit : diff); + + *v[4] -= diff; + *v[5] += diff; + } + } + else { /* DC-offset mode */ + + /* Now decide whether to apply smoothing filter or not */ + max = MAX(*v[1], MAX(*v[2], MAX(*v[3], MAX(*v[4], MAX(*v[5], MAX(*v[6], MAX(*v[7], *v[8]))))))); + min = MIN(*v[1], MIN(*v[2], MIN(*v[3], MIN(*v[4], MIN(*v[5], MIN(*v[6], MIN(*v[7], *v[8]))))))); + + if((max-min) < 2*quant) { + + /* Choose edge pixels */ + p0 = (ABS(*v[1]-*v[0]) < quant) ? *v[0] : *v[1]; + p9 = (ABS(*v[8]-*v[9]) < quant) ? *v[9] : *v[8]; + + *v[1] = (6*p0 + (*v[1]<<2) + (*v[2]<<1) + (*v[3]<<1) + *v[4] + *v[5] + 8) >> 4; + *v[2] = ((p0<<2) + (*v[1]<<1) + (*v[2]<<2) + (*v[3]<<1) + (*v[4]<<1) + *v[5] + *v[6] + 8) >> 4; + *v[3] = ((p0<<1) + (*v[1]<<1) + (*v[2]<<1) + (*v[3]<<2) + (*v[4]<<1) + (*v[5]<<1) + *v[6] + *v[7] + 8) >> 4; + *v[4] = (p0 + *v[1] + (*v[2]<<1) + (*v[3]<<1) + (*v[4]<<2) + (*v[5]<<1) + (*v[6]<<1) + *v[7] + *v[8] + 8) >> 4; + *v[5] = (*v[1] + *v[2] + (*v[3]<<1) + (*v[4]<<1) + (*v[5]<<2) + (*v[6]<<1) + (*v[7]<<1) + *v[8] + p9 + 8) >> 4; + *v[6] = (*v[2] + *v[3] + (*v[4]<<1) + (*v[5]<<1) + (*v[6]<<2) + (*v[7]<<1) + (*v[8]<<1) + (p9<<1) + 8) >> 4; + *v[7] = (*v[3] + *v[4] + (*v[5]<<1) + (*v[6]<<1) + (*v[7]<<2) + (*v[8]<<1) + (p9<<2) + 8) >> 4; + *v[8] = (*v[4] + *v[5] + (*v[6]<<1) + (*v[7]<<1) + (*v[8]<<2) + 6*p9 + 8) >> 4; + } + } + } +} + + + +void deblock8x8_v(uint8_t *img, int stride, int quant) +{ + int i, j; + int eq_cnt; + uint8_t *v[10], p0, p9; + int min, max; + int a30, a31, a32; + int diff, limit; + + for(j = 0; j < 8; j++) { + eq_cnt = 0; + + /* Load pixel addresses for filtering */ + + for(i = 0; i < 10; i++) + v[i] = img + j*stride + (i-5); + + /* First, decide whether to use default or DC-offset mode */ + + for(i = 0; i < 9; i++) + { + if(ABS(*v[i] - *v[i+1]) < THR1) + eq_cnt++; + } + + if(eq_cnt < THR2) { /* Default mode */ + + a30 = (*v[3] * 2 - *v[4] * 5 + *v[5] * 5 - *v[6] * 2); + + if(ABS(a30) < 8*quant) { + a31 = (*v[1] * 2 - *v[2] * 5 + *v[3] * 5 - *v[4] * 2); + a32 = (*v[5] * 2 - *v[6] * 5 + *v[7] * 5 - *v[8] * 2); + + diff = (5 * ((SIGN(a30) * MIN(ABS(a30), MIN(ABS(a31), ABS(a32)))) - a30) + 32) >> 6; + limit = (*v[4] - *v[5]) / 2; + + if (limit > 0) + diff = (diff < 0) ? 0 : ((diff > limit) ? limit : diff); + else + diff = (diff > 0) ? 0 : ((diff < limit) ? limit : diff); + + *v[4] -= diff; + *v[5] += diff; + } + } + else { /* DC-offset mode */ + + /* Now decide whether to apply smoothing filter or not */ + max = MAX(*v[1], MAX(*v[2], MAX(*v[3], MAX(*v[4], MAX(*v[5], MAX(*v[6], MAX(*v[7], *v[8]))))))); + min = MIN(*v[1], MIN(*v[2], MIN(*v[3], MIN(*v[4], MIN(*v[5], MIN(*v[6], MIN(*v[7], *v[8]))))))); + + if((max-min) < 2*quant) { + + /* Choose edge pixels */ + p0 = (ABS(*v[1]-*v[0]) < quant) ? *v[0] : *v[1]; + p9 = (ABS(*v[8]-*v[9]) < quant) ? *v[9] : *v[8]; + + *v[1] = (6*p0 + (*v[1]<<2) + (*v[2]<<1) + (*v[3]<<1) + *v[4] + *v[5] + 8) >> 4; + *v[2] = ((p0<<2) + (*v[1]<<1) + (*v[2]<<2) + (*v[3]<<1) + (*v[4]<<1) + *v[5] + *v[6] + 8) >> 4; + *v[3] = ((p0<<1) + (*v[1]<<1) + (*v[2]<<1) + (*v[3]<<2) + (*v[4]<<1) + (*v[5]<<1) + *v[6] + *v[7] + 8) >> 4; + *v[4] = (p0 + *v[1] + (*v[2]<<1) + (*v[3]<<1) + (*v[4]<<2) + (*v[5]<<1) + (*v[6]<<1) + *v[7] + *v[8] + 8) >> 4; + *v[5] = (*v[1] + *v[2] + (*v[3]<<1) + (*v[4]<<1) + (*v[5]<<2) + (*v[6]<<1) + (*v[7]<<1) + *v[8] + p9 + 8) >> 4; + *v[6] = (*v[2] + *v[3] + (*v[4]<<1) + (*v[5]<<1) + (*v[6]<<2) + (*v[7]<<1) + (*v[8]<<1) + (p9<<1) + 8) >> 4; + *v[7] = (*v[3] + *v[4] + (*v[5]<<1) + (*v[6]<<1) + (*v[7]<<2) + (*v[8]<<1) + (p9<<2) + 8) >> 4; + *v[8] = (*v[4] + *v[5] + (*v[6]<<1) + (*v[7]<<1) + (*v[8]<<2) + 6*p9 + 8) >> 4; + } + } + } +} \ No newline at end of file