📄 block.cpp
字号:
/*!
********************************************************
*\file
* block.cpp
*\brief
* implementation for 8x8 block level functions.
*\date
* 12/6/2002
*
********************************************************/
#include "HEnc.h"
#include "block.h"
#include <stdio.h>
#include <stdlib.h>
/*!
*******************************************************************************
*
* Name: pred_lum
* Description: lum prediction for the data of one 8x8 block
* Input: interpolated lum image, the position of current block, MV
* Output: prediction data
* Optimization: no
* Last modified: 2002/12/21
*
*******************************************************************************/
void pred_lum_c(int pix_x, int pix_y, MotionVector *MV, unsigned char *ipol,
int lx, unsigned char *pred_block)
{
int pred_x, pred_y;
int i, j, k, l;
int h_space = 2;
int v_space = lx * 2;
unsigned char *tmp1;
unsigned char *tmp2 = pred_block;
pred_x = 2*pix_x + 2*MV->x + MV->x_half;
pred_y = 2*pix_y + 2*MV->y + MV->y_half;
tmp1 = ipol + lx*pred_y + pred_x;
for (i = 0, k = 0; i < 8; i++, k+=v_space)
{
for (j = 0, l = 0; j < 8; j++, l+=h_space)
{
*tmp2 = *(tmp1 + k + l);
tmp2++;
}
}
}
/*!
*******************************************************************************
*
* Name: pred_lum_bid
* Description: bi-direction lum prediction for the data of one 8x8 block(B frames only)
* Input: interpolated lum images, the position of current block, displacement
* Output: prediction data
* Optimization: no
* Last modified: 2003/1/9
*
*******************************************************************************/
void pred_lum_bid_c(int pix_x, int pix_y, int dxf, int dyf, int dxb, int dyb,
unsigned char *prev_ipol, unsigned char *next_ipol, int lx,
unsigned char *pred_block)
{
int fw_pred_x, fw_pred_y;
int bw_pred_x, bw_pred_y;
int i, j, k, l;
int h_space = 2;
int v_space = lx * 2;
unsigned char *tmp1;
unsigned char *tmp2;
unsigned char *tmp3 = pred_block;
fw_pred_x = 2*pix_x + dxf;
fw_pred_y = 2*pix_y + dyf;
bw_pred_x = 2*pix_x + dxb;
bw_pred_y = 2*pix_y + dyb;
tmp1 = prev_ipol + lx*fw_pred_y + fw_pred_x;
tmp2 = next_ipol + lx*bw_pred_y + bw_pred_x;
for (i = 0, k = 0; i < 8; i++, k+=v_space)
{
for (j = 0, l = 0; j < 8; j++, l+=h_space)
{
*tmp3 = (*(tmp1 + k + l) + *(tmp2 + k + l) + 1) / 2;
tmp3++;
}
}
}
/*!
*******************************************************************************
*
* Name: pred_obmc
* Description: overlaped motion compensation prediction for lum
* Input:
* Output:
* Optimization: no
* Last modified: 2002/12/25
*
*******************************************************************************/
void pred_obmc_c(int x, int y, MotionVector *MV[6][MBR+1][MBC+2], int pic_width,
unsigned char *prev_ipol, int lx, int block, unsigned char *pred_block)
{
int r = y/16+1;
int c = x/16+1;
int use4mv_c = (MV[0][r][c]->Mode == MODE_INTER4V ? 1 : 0);
int use4mv_t = (MV[0][r-1][c]->Mode == MODE_INTER4V ? 1 : 0);
int use4mv_l = (MV[0][r][c-1]->Mode == MODE_INTER4V ? 1 : 0);
int use4mv_r = (MV[0][r][c+1]->Mode == MODE_INTER4V ? 1 : 0);
int intra_t, intra_l, intra_r;
int vecc, vect, vecb, vecl, vecr;
int x_curr, y_curr, x_top, y_top, x_btm, y_btm, x_left, y_left, x_right, y_right;
int pred_x_c, pred_x_t, pred_x_b, pred_x_l, pred_x_r;
int pred_y_c, pred_y_t, pred_y_b, pred_y_l, pred_y_r;
int val_c, val_t, val_b, val_l, val_r;
int m, n;
intra_t = (MV[0][r-1][c]->Mode == MODE_INTRA ? 1 : 0);
intra_t = (MV[0][r-1][c]->Mode == MODE_INTRA_Q ? 1 : intra_t);
intra_l = (MV[0][r][c-1]->Mode == MODE_INTRA ? 1 : 0);
intra_l = (MV[0][r][c-1]->Mode == MODE_INTRA_Q ? 1 : intra_l);
intra_r = (MV[0][r][c+1]->Mode == MODE_INTRA ? 1 : 0);
intra_r = (MV[0][r][c+1]->Mode == MODE_INTRA_Q ? 1 : intra_r);
switch (block)
{
case 1:
vecc = use4mv_c ? 1 : 0;
x_curr = c;
y_curr = r;
vect = intra_t ? vecc : (use4mv_t ? 3 : 0);
x_top = c;
y_top = intra_t ? r : r-1;
vecb = use4mv_c ? 3 : 0;
x_btm = c;
y_btm = r;
vecl = intra_l ? vecc: (use4mv_l ? 2 : 0);
x_left = intra_l ? c : c-1;
y_left = r;
vecr = use4mv_c ? 2 : 0;
x_right = c;
y_right = r;
if (1 == c)
{
vecl = vecc;
x_left = 1;
}
if (1 == r)
{
vect = vecc;
y_top = 1;
}
break;
case 2:
vecc = use4mv_c ? 2 : 0;
x_curr = c;
y_curr = r;
vect = intra_t ? vecc : (use4mv_t ? 4 : 0);
x_top = c;
y_top = intra_t ? r : r-1;
vecb = use4mv_c ? 4 : 0;
x_btm = c;
y_btm = r;
vecl = use4mv_c ? 1 : 0;
x_left = c;
y_left = r;
vecr = intra_r ? vecc : (use4mv_r ? 1 : 0);
x_right = intra_r ? c : c+1;
y_right = r;
if (1 == r)
{
vect = vecc;
y_top = 1;
}
if (c == pic_width/16)
{
vecr = vecc;
x_right = c;
}
break;
case 3:
vecc = use4mv_c ? 3 : 0;
x_curr = c;
y_curr = r;
vect = use4mv_c ? 1 : 0;
x_top = c;
y_top = r;
vecb = vecc;
x_btm = c;
y_btm = r;
vecl = intra_l ? vecc : (use4mv_l ? 4 : 0);
x_left = intra_l ? c : c-1;
y_left = r;
vecr = use4mv_c ? 4 : 0;
x_right = c;
y_right = r;
if (1 == c)
{
vecl = vecc;
x_left = 1;
}
break;
case 4:
vecc = use4mv_c ? 4 : 0;
x_curr = c;
y_curr = r;
vect = use4mv_c ? 2 : 0;
x_top = c;
y_top = r;
vecb = vecc;
x_btm = c;
y_btm = r;
vecl = use4mv_c ? 3 : 0;
x_left = c;
y_left = r;
vecr = intra_r ? vecc : (use4mv_r ? 3 : 0);
x_right = intra_r ? c : c+1;
y_right = r;
if (c == pic_width/16)
{
vecr = vecc;
x_right = c;
}
break;
default:
printf("obmc error, block type not exist.\n");
exit(-1);
}
pred_x_c = 2*x + (((block-1)&1)<<4) + MV[vecc][y_curr][x_curr]->x*2 + MV[vecc][y_curr][x_curr]->x_half;
pred_x_t = 2*x + (((block-1)&1)<<4) + MV[vect][y_top][x_top]->x*2 + MV[vect][y_top][x_top]->x_half;
pred_x_b = 2*x + (((block-1)&1)<<4) + MV[vecb][y_btm][x_btm]->x*2 + MV[vecb][y_btm][x_btm]->x_half;
pred_x_l = 2*x + (((block-1)&1)<<4) + MV[vecl][y_left][x_left]->x*2 + MV[vecl][y_left][x_left]->x_half;
pred_x_r = 2*x + (((block-1)&1)<<4) + MV[vecr][y_right][x_right]->x*2 + MV[vecr][y_right][x_right]->x_half;
pred_y_c = 2*y + (((block-1)&2)<<3) + MV[vecc][y_curr][x_curr]->y*2 + MV[vecc][y_curr][x_curr]->y_half;
pred_y_t = 2*y + (((block-1)&2)<<3) + MV[vect][y_top][x_top]->y*2 + MV[vect][y_top][x_top]->y_half;
pred_y_b = 2*y + (((block-1)&2)<<3) + MV[vecb][y_btm][x_btm]->y*2 + MV[vecb][y_btm][x_btm]->y_half;
pred_y_l = 2*y + (((block-1)&2)<<3) + MV[vecl][y_left][x_left]->y*2 + MV[vecl][y_left][x_left]->y_half;
pred_y_r = 2*y + (((block-1)&2)<<3) + MV[vecr][y_right][x_right]->y*2 + MV[vecr][y_right][x_right]->y_half;
for (n = 0; n < 8; n++)
{
for (m = 0; m < 8; m++)
{
val_c = *(prev_ipol + (pred_y_c + n*2)*lx + pred_x_c+m*2) * Mc[n][m];
val_t = *(prev_ipol + (pred_y_t + n*2)*lx + pred_x_t+m*2) * Mt[n][m];
val_b = *(prev_ipol + (pred_y_b + n*2)*lx + pred_x_b+m*2) * Mb[n][m];
val_l = *(prev_ipol + (pred_y_l + n*2)*lx + pred_x_l+m*2) * Ml[n][m];
val_r = *(prev_ipol + (pred_y_r + n*2)*lx + pred_x_r+m*2) * Mr[n][m];
*(pred_block + n*8 +m) = (val_c + val_t + val_b + val_l + val_r + 4)>>3;
}
}
}
/*!
*******************************************************************************
*
* Name: pred_chrom
* Description: chrom prediction for the data of one 8x8 block
* Input: reference picture, the position of current block.
* Output: prediction data
* Optimization: no
* Last modified: 2002/11/21
* Note: the chrom data is interpolated online
*
*******************************************************************************/
void pred_chrom_c(int pix_x, int pix_y, unsigned char *prev, int lx,
int dx, int dy, unsigned char *pred_block)
{
int xint, yint;
int xh, yh;
int i, j;
int x_off, y_off;
unsigned char *tmp = pred_block;
xint = dx>>1;
xh = dx & 1;
yint = dy>>1;
yh = dy & 1;
if (!xh && !yh) //!< xh and yh are both zero
{
x_off = pix_x + xint;
y_off = pix_y + yint;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = *(prev + (y_off+i)*lx + x_off+j);
tmp++;
}
}
}
else if (!xh && yh) //!< yh is not zero
{
x_off = pix_x + xint;
y_off = pix_y + yint;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*(prev + (y_off+i)*lx + x_off+j) +
*(prev + (y_off+i+yh)*lx + x_off+j) + 1)>>1;
tmp++;
}
}
}
else if (xh && !yh) //!< xh is not zero
{
x_off = pix_x + xint;
y_off = pix_y + yint;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*(prev + (y_off+i)*lx + x_off+j) +
*(prev + (y_off+i)*lx + x_off+j+xh) + 1)>>1;
tmp++;
}
}
}
else //! neither xh nor yh is zero
{
x_off = pix_x + xint;
y_off = pix_y + yint;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*(prev + (y_off+i)*lx + x_off+j) +
*(prev + (y_off+i)*lx + x_off+j+xh) +
*(prev + (y_off+i+yh)*lx + x_off+j) +
*(prev + (y_off+i+yh)*lx + x_off+j+xh) +
2)>>2;
tmp++;
}
}
}
}
/*!
*******************************************************************************
*
* Name: pred_chrom_bid
* Description: bi-direction chrom prediction for the data of one 8x8 block
* (only used in B frames)
* Input: the pointer to previous picture and next picture,
* the position of current block, forward and backward displacement
* Output: prediction data
* Optimization: NO
* Last modified: 2002/11/21
* Note: the chrom data is interpolated online
*
*******************************************************************************/
void pred_chrom_bid_c(int pix_x, int pix_y, unsigned char *prev, unsigned char *next, int lx,
int dxf, int dyf, int dxb, int dyb, unsigned char *pred_block)
{
int xint1, yint1, xint2, yint2;
int xh1, yh1, xh2, yh2;
int i, j;
int x_off, y_off;
unsigned char *tmp = pred_block;
xint1 = dxf>>1;
xh1 = dxf & 1;
yint1 = dyf>>1;
yh1 = dyf & 1;
if (!xh1 && !yh1) //!< xh and yh are both zero
{
x_off = pix_x + xint1;
y_off = pix_y + yint1;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = *(prev + (y_off+i)*lx + x_off+j);
tmp++;
}
}
}
else if (!xh1 && yh1) //!< yh is not zero
{
x_off = pix_x + xint1;
y_off = pix_y + yint1;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*(prev + (y_off+i)*lx + x_off+j) +
*(prev + (y_off+i+yh1)*lx + x_off+j) + 1)>>1;
tmp++;
}
}
}
else if (xh1 && !yh1) //!< xh is not zero
{
x_off = pix_x + xint1;
y_off = pix_y + yint1;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*(prev + (y_off+i)*lx + x_off+j) +
*(prev + (y_off+i)*lx + x_off+j+xh1) + 1)>>1;
tmp++;
}
}
}
else //! neither xh nor yh is zero
{
x_off = pix_x + xint1;
y_off = pix_y + yint1;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*(prev + (y_off+i)*lx + x_off+j) +
*(prev + (y_off+i)*lx + x_off+j+xh1) +
*(prev + (y_off+i+yh1)*lx + x_off+j) +
*(prev + (y_off+i+yh1)*lx + x_off+j+xh1) +
2)>>2;
tmp++;
}
}
}
tmp = pred_block;
xint2 = dxb>>1;
xh2 = dxb & 1;
yint2 = dyb>>1;
yh2 = dyb & 1;
if (!xh2 && !yh2) //!< xh and yh are both zero
{
x_off = pix_x + xint2;
y_off = pix_y + yint2;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*tmp)/2 + (*(next + (y_off+i)*lx + x_off+j))/2;
tmp++;
}
}
}
else if (!xh2 && yh2) //!< yh is not zero
{
x_off = pix_x + xint2;
y_off = pix_y + yint2;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*tmp)/2 +
(*(next + (y_off+i)*lx + x_off+j) +
*(next + (y_off+i+yh2)*lx + x_off+j) + 1)/4;
tmp++;
}
}
}
else if (xh2 && !yh2) //!< xh is not zero
{
x_off = pix_x + xint2;
y_off = pix_y + yint2;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*tmp)/2 +
(*(next + (y_off+i)*lx + x_off+j) +
*(next + (y_off+i)*lx + x_off+j+xh2) + 1)/4;
tmp++;
}
}
}
else //! neither xh nor yh is zero
{
x_off = pix_x + xint2;
y_off = pix_y + yint2;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
*tmp = (*tmp)/2 +
(*(next + (y_off+i)*lx + x_off+j) +
*(next + (y_off+i)*lx + x_off+j+xh2) +
*(next + (y_off+i+yh2)*lx + x_off+j) +
*(next + (y_off+i+yh2)*lx + x_off+j+xh2) +
2)/8;
tmp++;
}
}
}
}
/*!
*******************************************************************************
*
* Name: make_diff
* Description: compute difference value of one 8x8 block during inter-frame coding
* Input: the pointer of current block, the pointer of predictive block
* Output:
* Effect: Fill difference block
* Optimization: NO
* Last modified: 2002/11/22
*
*******************************************************************************/
void make_diff_c(unsigned char* curr_block, int pic_width, unsigned char *pred_block, INT16 *diff_block)
{
unsigned char *tmp1 = curr_block;
unsigned char *tmp2 = pred_block;
INT16 *tmp3 = diff_block;
int i, j, k;
for (i = 0, k = 0; i < 8; i++, k+=pic_width)
{
for (j = 0; j < 8; j++)
{
*tmp3 = (INT16)( *(tmp1 + k + j) - *tmp2 );
tmp2++;
tmp3++;
}
}
}
/*!
*******************************************************************************
*
* Name: recon_pic
* Description: reconstruct one 8x8 block during inter-frame coding
* Input: pred_block, diff_block
* Output:
* Effect: Fill corresponding area of recon image
* Optimization: NO
* Last modified: 2002/11/22
*
*******************************************************************************/
void recon_pic_c(unsigned char* recon_block, int pic_width, unsigned char *pred_block, INT16 *diff_block)
{
unsigned char *tmp1 = recon_block;
unsigned char *tmp2 = pred_block;
INT16 *tmp3 = diff_block;
int i, j, k;
for (i = 0, k = 0; i < 8; i++, k+=pic_width)
{
for (j = 0; j < 8; j ++)
{
*(tmp1 + k + j) = (unsigned char)mmin(255, mmax(0, (INT16)(*tmp3 + *tmp2)));
tmp2++;
tmp3++;
}
}
}
/* removed temporarily, may be utilized in future
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -