📄 image.c
字号:
diff_v += img->quad[abs(imgUV_org[1][j][i]-imgUV[1][j][i])];
}
}
/* Collecting SNR statistics */
if (diff_y != 0)
{
snr->snr_y=(float)(10*log10(65025*(float)impix/(float)diff_y)); /* luma snr for current frame */
snr->snr_u=(float)(10*log10(65025*(float)impix/(float)(4*diff_u))); /* u croma snr for current frame, 1/4 of luma samples*/
snr->snr_v=(float)(10*log10(65025*(float)impix/(float)(4*diff_v))); /* v croma snr for current frame, 1/4 of luma samples*/
}
if (img->number == 0)
{
snr->snr_y1=(float)(10*log10(65025*(float)impix/(float)diff_y)); /* keep luma snr for first frame */
snr->snr_u1=(float)(10*log10(65025*(float)impix/(float)(4*diff_u))); /* keep croma u snr for first frame */
snr->snr_v1=(float)(10*log10(65025*(float)impix/(float)(4*diff_v))); /* keep croma v snr for first frame */
snr->snr_ya=snr->snr_y1;
snr->snr_ua=snr->snr_u1;
snr->snr_va=snr->snr_v1;
}
/* B pictures */
else
{
snr->snr_ya=(float)(snr->snr_ya*(img->number+Bframe_ctr)+snr->snr_y)/(img->number+Bframe_ctr+1); /* average snr lume for all frames inc. first */
snr->snr_ua=(float)(snr->snr_ua*(img->number+Bframe_ctr)+snr->snr_u)/(img->number+Bframe_ctr+1); /* average snr u croma for all frames inc. first */
snr->snr_va=(float)(snr->snr_va*(img->number+Bframe_ctr)+snr->snr_v)/(img->number+Bframe_ctr+1); /* average snr v croma for all frames inc. first */
}
}
/************************************************************************
*
* Name : loopfilter()
*
* Description: Filter to reduce blocking artifacts. The filter strengh
* is QP dependent.
*
************************************************************************/
static unsigned char
overallActivity[256], qp_overallActivity = 255;
static int
beta;
extern const int QP2QUANT[32];
void loopfilter()
{
static int MAP[32];
/*GH: see dynamic mem allocation in image.c */
/*byte imgY_tmp[288][352]; */ /* temp luma image */
/*byte imgUV_tmp[2][144][176]; */ /* temp chroma image */
int x,y,y4,x4,k,uv,str1,str2;
if (qp_overallActivity != img->qp)
{
int
i, alpha,
ALPHA_TABLE[32] = {
0, 0, 0, 0, 0, 0, 0, 0,
3, 3, 3, 7, 7, 7, 12, 17,
17, 22, 28, 34, 40, 47, 60, 67,
82, 89,112,137,153,187,213,249
},
BETA_TABLE[32] = {
0, 0, 0, 0, 0, 0, 0, 0,
3, 3, 3, 4, 4, 4, 6, 6,
6, 7, 8, 8, 9, 9, 10, 10,
11, 11, 12, 12, 13, 13, 14, 14
};
for (i=0; i<32; i++)
MAP[i] = QP2QUANT[i]-1;
/*
* ALPHA(img->qp) = ceil(2.0 * MAP(img->qp) * ln(MAP(img->qp)))
*/
alpha = ALPHA_TABLE[img->qp];
/*
* BETA(img->qp) = floor(4.0 * log(MAP[img->qp]) + 0.5)
*/
beta = BETA_TABLE[img->qp];
for (k=0; k<256; k++)
if (2*k >= alpha+(alpha/2))
overallActivity[k] = 1;
else if (2*k >= alpha)
overallActivity[k] = 2;
else
overallActivity[k] = 3;
qp_overallActivity = img->qp;
}
/* Luma hor */
for(y=0;y<img->height;y++)
for(x=0;x<img->width;x++)
imgY_tmp[y][x]=imgY[y][x];
for(y=0;y<img->height;y++)
{
y4=y/4;
for(x=4;x<img->width;x=x+4)
{
x4=x/4;
str1 = loopb[x4][y4+1];
str2 = loopb[x4+1][y4+1];
if((str1!=0)&&(str2!=0))
{
/*
* Copy one line of 4+4 reconstruction pels into the filtering buffer.
*/
for(k=0;k<8;k++)
img->li[k]=imgY_tmp[y][x-4+k];
/*
* Check for longer filtering on macroblock border if either block is intracoded.
*/
if(!(x4%4) && (str1 == 3 || str2 == 3))
{
if(loop(str1,str2, 1, 0))
{
imgY_tmp[y][x-4+6] = img->lu[6];
imgY[y][x-3] = img->lu[1];
imgY[y][x+2] = img->lu[6];
}
}
else
loop(str1,str2, 0, 0);
/*
* Place back the filtered values into the filtered reconstruction buffer.
*/
for (k=2;k<6;k++)
imgY[y][x-4+k]=img->lu[k];
}
}
}
/* Luma vert */
for(y=0;y<img->height;y++)
for(x=0;x<img->width;x++)
imgY_tmp[y][x]=imgY[y][x];
for(x=0;x<img->width;x++)
{
x4=x/4;
for(y=4;y<img->height;y=y+4)
{
y4=y/4;
str1 = loopb[x4+1][y4];
str2 = loopb[x4+1][y4+1];
if((str1 != 0) && (str2 != 0))
{
/*
* Copy one line of 4+4 reconstruction pels into the filtering buffer.
*/
for(k=0;k<8;k++)
img->li[k]=imgY_tmp[y-4+k][x];
/*
* Check for longer filtering on macroblock border if either block is intracoded.
*/
if(!(y4%4) && (str1 == 3 || str2 == 3))
{
if(loop(str1,str2, 1, 0)){
imgY_tmp[y-4+6][x] = img->lu[6];
imgY[y-3][x] = img->lu[1];
imgY[y+2][x] = img->lu[6];
}
}
else
loop(str1,str2, 0, 0);
/*
* Place back the filtered values into the filtered reconstruction buffer.
*/
for (k=2;k<6;k++)
imgY[y-4+k][x]=img->lu[k];
}
}
}
/* chroma */
for (uv=0;uv<2;uv++)
{
/* horizontal chroma */
for(y=0;y<img->height_cr;y++)
for(x=0;x<img->width_cr;x++)
imgUV_tmp[uv][y][x]=imgUV[uv][y][x];
for(y=0;y<img->height_cr;y++)
{
y4=y/4;
for(x=4;x<img->width_cr;x=x+4)
{
x4=x/4;
str1 = loopc[x4][y4+1];
str2 = loopc[x4+1][y4+1];
if((str1 != 0) && (str2 != 0))
{
/*
* Copy one line of 4+4 reconstruction pels into the filtering buffer.
*/
for(k=0;k<8;k++)
img->li[k]=imgUV_tmp[uv][y][x-4+k];
/*
* Check for longer filtering on macroblock border if either block is intracoded.
*/
if(!(x4%2) && (loopb[2*x4][2*y4+1] == 3 || loopb[2*x4+1][2*y4+1] == 3))
loop(str1,str2, 1, 1);
else
loop(str1,str2, 0, 1);
/*
* Place back the filtered values into the filtered reconstruction buffer.
*/
for (k=2;k<6;k++)
imgUV[uv][y][x-4+k]=img->lu[k];
}
}
}
/* vertical chroma */
for(y=0;y<img->height_cr;y++)
for(x=0;x<img->width_cr;x++)
imgUV_tmp[uv][y][x]=imgUV[uv][y][x];
for(x=0;x<img->width_cr;x++)
{
x4=x/4;
for(y=4;y<img->height_cr;y=y+4)
{
y4=y/4;
str1 = loopc[x4+1][y4];
str2 = loopc[x4+1][y4+1];
if((str1 != 0) && (str2 != 0))
{
/*
* Copy one line of 4+4 reconstruction pels into the filtering buffer.
*/
for(k=0;k<8;k++)
img->li[k]=imgUV_tmp[uv][y-4+k][x];
/*
* Check for longer filtering on macroblock border if either block is intracoded.
*/
if(!(y4%2) && (loopb[2*x4+1][2*y4] == 3 || loopb[2*x4+1][2*y4+1] == 3))
loop(str1,str2, 1, 1);
else
loop(str1,str2, 0, 1);
/*
* Place back the filtered values into the filtered reconstruction buffer.
*/
for (k=2;k<6;k++)
imgUV[uv][y-4+k][x]=img->lu[k];
}
}
}
}
}
/************************************************************************
*
* Name : loop()
*
* Description: Filters up to 6 pixels from 8 pixel input
*
************************************************************************/
int loop(int ibl, int ibr, int longFilt, int chroma)
{
int
delta, halfLim, dr, dl, i, truncLimLeft, truncLimRight,
diff, clip, clip_left, clip_right;
/* Limit the difference between filtered and nonfiltered based
* on QP and strength
*/
clip_left = FILTER_STR[img->qp][ibl];
clip_right = FILTER_STR[img->qp][ibr];
/* The step across the block boundaries */
delta = abs(img->li[3]-img->li[4]);
/* Find overall activity parameter (n/2) */
halfLim = overallActivity[delta];
/* Truncate left limit to 2 for small stengths */
if (ibl <= 1)
truncLimLeft = (halfLim > 2) ? 2 : halfLim;
else
truncLimLeft = halfLim;
/* Truncate right limit to 2 for small stengths */
if (ibr <= 1)
truncLimRight = (halfLim > 2) ? 2 : halfLim;
else
truncLimRight = halfLim;
/* Find right activity parameter dr */
for (dr=1; dr<truncLimRight; dr++)
{
if (dr*abs(img->li[4]-img->li[4+dr]) > beta)
break;
}
/* Find left activity parameter dl */
for (dl=1; dl<truncLimLeft; dl++)
{
if (dl*abs(img->li[3]-img->li[3-dl]) > beta)
break;
}
if(dr < 2 || dl < 2)
{
/* no filtering when either one of activity params is below two */
img->lu[2] = img->li[2];
img->lu[3] = img->li[3];
img->lu[4] = img->li[4];
img->lu[5] = img->li[5];
return 0;
}
if(longFilt)
{
if(dr == 3 && dl == 3 &&
delta >= 2 && delta < img->qp/4)
{
if(chroma)
{
img->lu[3] = (25*(img->li[1] + img->li[5]) + 26*(img->li[2] + img->li[3] + img->li[4]) + 64) >> 7;
img->lu[2] = (25*(img->li[0] + img->li[4]) + 26*(img->li[1] + img->li[2] + img->lu[3]) + 64) >> 7;
img->lu[4] = (25*(img->li[2] + img->li[6]) + 26*(img->li[3] + img->li[4] + img->li[5]) + 64) >> 7;
img->lu[5] = (25*(img->li[3] + img->li[7]) + 26*(img->lu[4] + img->li[5] + img->li[6]) + 64) >> 7;
return 0;
}
else
{
img->lu[3] = (25*(img->li[1] + img->li[5]) + 26*(img->li[2] + img->li[3] + img->li[4]) + 64) >> 7;
img->lu[2] = (25*(img->li[0] + img->li[4]) + 26*(img->li[1] + img->li[2] + img->lu[3]) + 64) >> 7;
img->lu[1] = (25*(img->li[1] + img->lu[3]) + 26*(img->li[0] + img->li[1] + img->lu[2]) + 64) >> 7;
img->lu[4] = (25*(img->li[2] + img->li[6]) + 26*(img->li[3] + img->li[4] + img->li[5]) + 64) >> 7;
img->lu[5] = (25*(img->li[3] + img->li[7]) + 26*(img->lu[4] + img->li[5] + img->li[6]) + 64) >> 7;
img->lu[6] = (25*(img->lu[4] + img->li[6]) + 26*(img->lu[5] + img->li[6] + img->li[7]) + 64) >> 7;
return 1;
}
}
}
/* Filter pixels at the edge */
img->lu[4] = (21*(img->li[3] + img->li[5]) + 22*img->li[4] + 32) >> 6;
img->lu[3] = (21*(img->li[2] + img->li[4]) + 22*img->li[3] + 32) >> 6;
if(dr == 3)
img->lu[5] = (21*(img->lu[4] + img->li[6]) + 22*img->li[5] + 32) >> 6;
else
img->lu[5] = img->li[5];
if(dl == 3)
img->lu[2] = (21*(img->li[1] + img->lu[3]) + 22*img->li[2] + 32) >> 6;
else
img->lu[2] = img->li[2];
/* Clipping parameter depends on one table and left and right act params */
clip = (clip_left + clip_right + dl + dr) / 2;
/* Pixels at the edge are clipped differently */
for (i=3; i<=4; i++)
{
diff = (int)img->lu[i] - (int)img->li[i];
if (diff)
{
if (diff > clip)
diff = clip;
else if (diff < -clip)
diff = -clip;
img->lu[i] = img->li[i] + diff;
}
}
/* pixel from left is clipped */
diff = (int)img->lu[2] - (int)img->li[2];
if (diff)
{
if (diff > clip_left)
diff = clip_left;
else if (diff < -clip_left)
diff = -clip_left;
img->lu[2] = img->li[2] + diff;
}
/* pixel from right is clipped */
diff = (int)img->lu[5] - (int)img->li[5];
if (diff)
{
if (diff > clip_right)
diff = clip_right;
else if (diff < -clip_right)
diff = -clip_right;
img->lu[5] = img->li[5] + diff;
}
return 0;
}
/************************************************************************
*
* Name : dummy_slice_too_big()
*
* Description: Just a placebo
*
************************************************************************/
Boolean dummy_slice_too_big(int bits_slice)
{
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -