📄 image.c
字号:
for (i=0; i < img->width_cr; i++)
imgUV_ref[uv][j][i]=fgetc(p_ref);
img->quad[0]=0;
diff_y=0;
for (j=0; j < img->height; ++j)
{
for (i=0; i < img->width; ++i)
{
diff_y += img->quad[abs(imgY[j][i]-imgY_ref[j][i])];
}
}
// Chroma
diff_u=0;
diff_v=0;
for (j=0; j < img->height_cr; ++j)
{
for (i=0; i < img->width_cr; ++i)
{
diff_u += img->quad[abs(imgUV_ref[0][j][i]-imgUV[0][j][i])];
diff_v += img->quad[abs(imgUV_ref[1][j][i]-imgUV[1][j][i])];
}
}
// Collecting SNR statistics
if (diff_y != 0)
{
snr->snr_y=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y)); // luma snr for current frame
}
if (diff_u != 0)
{
snr->snr_u=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u))); // chroma snr for current frame
snr->snr_v=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v))); // chroma snr for current frame
}
if (img->number == 0) // first
{
snr->snr_y1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y)); // keep luma snr for first frame
snr->snr_u1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u))); // keep chroma snr for first frame
snr->snr_v1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v))); // keep chroma snr for first frame
snr->snr_ya=snr->snr_y1;
snr->snr_ua=snr->snr_u1;
snr->snr_va=snr->snr_v1;
}
else
{
snr->snr_ya=(float)(snr->snr_ya*(img->number+Bframe_ctr)+snr->snr_y)/(img->number+Bframe_ctr+1); // average snr chroma for all frames
snr->snr_ua=(float)(snr->snr_ua*(img->number+Bframe_ctr)+snr->snr_u)/(img->number+Bframe_ctr+1); // average snr luma for all frames
snr->snr_va=(float)(snr->snr_va*(img->number+Bframe_ctr)+snr->snr_v)/(img->number+Bframe_ctr+1); // average snr luma for all frames
}
}
/*!
************************************************************************
* \brief
* Direct interpolation of a specific subpel position
*
* \author
* Thomas Wedi, 12.01.2001 <wedi@tnt.uni-hannover.de>
*
* \para Remarks:
* A further significant complexity reduction is possible
* if the direct interpolation is not performed on pixel basis
* but on block basis,
*
************************************************************************
*/
void get_block(int ref_frame,int x_pos, int y_pos, struct img_par *img, int block[BLOCK_SIZE][BLOCK_SIZE])
{
switch(img->mv_res)
{
case 0:
get_quarterpel_block(ref_frame,x_pos,y_pos,img,block);
break;
case 1:
get_eighthpel_block(ref_frame,x_pos,y_pos,img,block);
break;
default:
snprintf(errortext, ET_SIZE, "wrong mv-resolution: %d",img->mv_res);
error(errortext, 600);
break;
}
}
/*!
************************************************************************
* \brief
* Interpolation of 1/4 subpixel
************************************************************************
*/
void get_quarterpel_block(int ref_frame,int x_pos, int y_pos, struct img_par *img, int block[BLOCK_SIZE][BLOCK_SIZE])
{
int dx, dy;
int x, y;
int i, j;
int maxold_x,maxold_y;
int result;
int pres_x;
int pres_y;
int tmp_res[4][9];
static const int COEF[6] = {
1, -5, 20, 20, -5, 1
};
dx = x_pos&3;
dy = y_pos&3;
x_pos = (x_pos-dx)/4;
y_pos = (y_pos-dy)/4;
maxold_x = img->width-1;
maxold_y = img->height-1;
if (dx == 0 && dy == 0) { /* fullpel position */
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i))];
}
else if (dx == 3 && dy == 3) { /* funny position */
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (
mref[ref_frame][max(0,min(maxold_y,y_pos+j)) ][max(0,min(maxold_x,x_pos+i)) ]+
mref[ref_frame][max(0,min(maxold_y,y_pos+j)) ][max(0,min(maxold_x,x_pos+i+1))]+
mref[ref_frame][max(0,min(maxold_y,y_pos+j+1))][max(0,min(maxold_x,x_pos+i+1))]+
mref[ref_frame][max(0,min(maxold_y,y_pos+j+1))][max(0,min(maxold_x,x_pos+i)) ]+2)/4;
}
else { /* other positions */
if (dy == 0) { /* No vertical interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, x = -2; x < 4; x++)
result += mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF[x+2];
block[i][j] = max(0, min(255, (result+16)/32));
}
}
if ((dx&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+dx/2))])/2;
}
}
else if (dx == 0) { /* No horizontal interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, y = -2; y < 4; y++)
result += mref[ref_frame][max(0,min(maxold_y,y_pos+j+y))][max(0,min(maxold_x,x_pos+i))]*COEF[y+2];
block[i][j] = max(0, min(255, (result+16)/32));
}
}
if ((dy&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + mref[ref_frame][max(0,min(maxold_y,y_pos+j+dy/2))][max(0,min(maxold_x,x_pos+i))])/2;
}
}
else if (dx == 2) { /* Vertical & horizontal interpolation */
for (j = -2; j < BLOCK_SIZE+3; j++) {
for (i = 0; i < BLOCK_SIZE; i++)
for (tmp_res[i][j+2] = 0, x = -2; x < 4; x++)
tmp_res[i][j+2] += mref[ref_frame][max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF[x+2];
}
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, y = -2; y < 4; y++)
result += tmp_res[i][j+y+2]*COEF[y+2];
block[i][j] = max(0, min(255, (result+512)/1024));
}
}
if ((dy&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + max(0, min(255, (tmp_res[i][j+2+dy/2]+16)/32)))/2;
}
}
else if (dy == 2) { /* Horizontal & vertical interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = -2; i < BLOCK_SIZE+3; i++)
for (tmp_res[j][i+2] = 0, y = -2; y < 4; y++)
tmp_res[j][i+2] += mref[ref_frame][max(0,min(maxold_y,y_pos+j+y))][max(0,min(maxold_x,x_pos+i))]*COEF[y+2];
}
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (result = 0, x = -2; x < 4; x++)
result += tmp_res[j][i+x+2]*COEF[x+2];
block[i][j] = max(0, min(255, (result+512)/1024));
}
}
if ((dx&1) == 1) {
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + max(0, min(255, (tmp_res[j][i+2+dx/2]+16)/32)))/2;
}
}
else { /* Diagonal interpolation */
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
pres_y = dy == 1 ? y_pos+j : y_pos+j+1;
pres_y = max(0,min(maxold_y,pres_y));
for (result = 0, x = -2; x < 4; x++)
result += mref[ref_frame][pres_y][max(0,min(maxold_x,x_pos+i+x))]*COEF[x+2];
block[i][j] = max(0, min(255, (result+16)/32));
}
}
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
pres_x = dx == 1 ? x_pos+i : x_pos+i+1;
pres_x = max(0,min(maxold_x,pres_x));
for (result = 0, y = -2; y < 4; y++)
result += mref[ref_frame][max(0,min(maxold_y,y_pos+j+y))][pres_x]*COEF[y+2];
block[i][j] = (block[i][j] + max(0, min(255, (result+16)/32))) / 2;
}
}
}
}
}
/*!
************************************************************************
* \brief
* Interpolation of 1/8 subpixel
************************************************************************
*/
static void get_fullpel_block(int ref_frame,int x_pres, int y_pres, int max_x, int max_y, int block[BLOCK_SIZE][BLOCK_SIZE])
{
int i, j;
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = mref[ref_frame][max(0,min(y_pres+j,max_y))][max(0,min(x_pres+i,max_x))];
}
static void interp_block_X(int ref_frame, int pres_x, int pres_y, const int *coefx, int max_x, int max_y, int block[BLOCK_SIZE][BLOCK_SIZE])
{
int i, j, x;
int result;
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for(result = 0, x = -3; x < 5; x++)
result += mref[ref_frame][max(0,min(max_y,pres_y+j))][max(0,min(pres_x+i+x,max_x))]*coefx[x+3];
block[i][j] = max(0, min(255, (result+128)/256));
}
}
}
static void interp_block_Y(int ref_frame, int pres_x, int pres_y, const int *coefy, int max_x, int max_y, int block[BLOCK_SIZE][BLOCK_SIZE])
{
int i, j, y;
int result;
for (j = 0; j < BLOCK_SIZE; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for(result = 0, y = -3; y < 5; y++)
result += mref[ref_frame][max(0,min(pres_y+j+y,max_y))][max(0,min(max_x,pres_x+i))]*coefy[y+3];
block[i][j] = max(0, min(255, (result+128)/256));
}
}
}
static void interp_block_3_1(int block[BLOCK_SIZE][BLOCK_SIZE],
int block1[BLOCK_SIZE][BLOCK_SIZE],
int block2[BLOCK_SIZE][BLOCK_SIZE])
{
int i, j;
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (3*block1[i][j] + block2[i][j] + 2) / 4;
}
static void average_block(int block[BLOCK_SIZE][BLOCK_SIZE], int block2[BLOCK_SIZE][BLOCK_SIZE])
{
int i, j;
for (j = 0; j < BLOCK_SIZE; j++)
for (i = 0; i < BLOCK_SIZE; i++)
block[i][j] = (block[i][j] + block2[i][j]) / 2;
}
void get_eighthpel_block(int ref_frame,int x_pos, int y_pos, struct img_par *img, int block[BLOCK_SIZE][BLOCK_SIZE])
{
static const int COEF[3][8] = {
{-3, 12, -37, 229, 71, -21, 6, -1},
{-3, 12, -39, 158, 158, -39, 12, -3},
{-1, 6, -21, 71, 229, -37, 12, -3}
};
int block2[BLOCK_SIZE][BLOCK_SIZE];
int dx=0, x=0;
int dy=0, y=0;
int pres_x=0;
int pres_y=0;
int max_x=0,max_y=0;
int tmp[4][4+8];
int result;
int i, j;
dx = x_pos&7;
dy = y_pos&7;
pres_x = x_pos>>3;
pres_y = y_pos>>3;
max_x = img->width-1;
max_y = img->height-1;
/* choose filter depending on subpel position */
if(dx==0 && dy==0) { /* fullpel position */
get_fullpel_block(ref_frame, pres_x, pres_y, max_x, max_y, block);
}
else if(dy == 0) { /* Only horizontal interpolation */
if (dx == 1)
get_fullpel_block(ref_frame, pres_x, pres_y, max_x, max_y, block);
else
interp_block_X(ref_frame, pres_x, pres_y, COEF[dx/2-1], max_x, max_y, block);
if ((dx&1) != 0) {
if (dx == 7)
get_fullpel_block(ref_frame, pres_x+1, pres_y, max_x, max_y, block2);
else
interp_block_X(ref_frame, pres_x, pres_y, COEF[dx/2], max_x, max_y, block2);
average_block(block, block2);
}
}
else if (dx == 0) { /* Only vertical interpolation */
if (dy == 1)
get_fullpel_block(ref_frame, pres_x, pres_y, max_x, max_y, block);
else
interp_block_Y(ref_frame, pres_x, pres_y, COEF[dy/2-1], max_x, max_y, block);
if ((dy&1) != 0) {
if (dy == 7)
get_fullpel_block(ref_frame, pres_x, pres_y+1, max_x, max_y, block2);
else
interp_block_Y(ref_frame, pres_x, pres_y, COEF[dy/2], max_x, max_y, block2);
average_block(block, block2);
}
}
else if ((dx&1) == 0) { /* Horizontal 1/4-pel and vertical 1/8-pel interpolation */
for (j = -3; j < BLOCK_SIZE+5; j++) {
for (i = 0; i < BLOCK_SIZE; i++) {
for (tmp[i][j+3] = 0, x = -3; x < 5; x++)
tmp[i][j+3] += mref[ref_frame][max(0,min(pres_y+j,max_y))][max(0,min(pres_x+i+x,max_x))]*COEF[dx/2-1][x+3];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -