📄 block.cpp
字号:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "global.h"
#include "block.h"
#define Q_BITS 15
#define DQ_BITS 6
#define DQ_ROUND (1<<(DQ_BITS-1))
//#define FAST_INTEGER
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
static const int quant_coef[6][4][4] = {
{{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243},{13107, 8066,13107, 8066},{ 8066, 5243, 8066, 5243}},
{{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660},{11916, 7490,11916, 7490},{ 7490, 4660, 7490, 4660}},
{{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194},{10082, 6554,10082, 6554},{ 6554, 4194, 6554, 4194}},
{{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647},{ 9362, 5825, 9362, 5825},{ 5825, 3647, 5825, 3647}},
{{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355},{ 8192, 5243, 8192, 5243},{ 5243, 3355, 5243, 3355}},
{{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893},{ 7282, 4559, 7282, 4559},{ 4559, 2893, 4559, 2893}}
};
static const int dequant_coef[6][4][4] = {
{{10, 13, 10, 13},{ 13, 16, 13, 16},{10, 13, 10, 13},{ 13, 16, 13, 16}},
{{11, 14, 11, 14},{ 14, 18, 14, 18},{11, 14, 11, 14},{ 14, 18, 14, 18}},
{{13, 16, 13, 16},{ 16, 20, 16, 20},{13, 16, 13, 16},{ 16, 20, 16, 20}},
{{14, 18, 14, 18},{ 18, 23, 18, 23},{14, 18, 14, 18},{ 18, 23, 18, 23}},
{{16, 20, 16, 20},{ 20, 25, 20, 25},{16, 20, 16, 20},{ 20, 25, 20, 25}},
{{18, 23, 18, 23},{ 23, 29, 23, 29},{18, 23, 18, 23},{ 23, 29, 23, 29}}
};
static const int A[4][4] = {
{ 16, 20, 16, 20},
{ 20, 25, 20, 25},
{ 16, 20, 16, 20},
{ 20, 25, 20, 25}
};
static int quant_coef1[6][16];
static int dequant_coef1[6][16];
extern char intra_mb_pos[72][92];
extern char intra_mb_pos1[72][92];
void InitQuantTable()
{
int i,j,coeff_ctr,qp_rem;
for(qp_rem=0;qp_rem<6;qp_rem++)
for (coeff_ctr=0;coeff_ctr < 16;coeff_ctr++)
{
i=SNGL_SCAN[coeff_ctr][0];
j=SNGL_SCAN[coeff_ctr][1];
quant_coef1[qp_rem][coeff_ctr]=quant_coef[qp_rem][i][j];
dequant_coef1[qp_rem][coeff_ctr]=dequant_coef[qp_rem][i][j];
}
}
/************************************************************************
*
* Routine: intrapred_chroma()
*
* Description: Chroma intra prediction. There are 3 pred modes:
* 1. DC, Used if:
* a) 16x16 based 'plane' luma prediction
* b) 16x16 based vert/hor pred. impossible due to edges
* b) if sum of 4x4 luma pred. is 'DC based'
* 2) Vertical, used if:
* a) 16x16 based vertical luma pred. is used
* b) if sum of 4x4 luma pred is 'vertical based'
* 3) Horizontal, used if:
* a) 16x16 based horizontal luma pred. is used
* b) if sum of 4x4 luma pred is 'horizontal based'
*
* Input: Starting point of current chroma macro block image posision, chroma component and predmode
*
* Output: 8x8 array with given intra chroma prediction and diff array
*
************************************************************************/
void intrapred_chroma(struct img_par *img,int img_c_x,int img_c_y,int uv)
{
int s, s0, s1, s2, s3, i, j;
int block_x, block_y;
int img_cx = img_c_x;//img->pix_c_x;
int img_cy = img_c_y;//img->pix_c_y;
int img_cx_1 = img_c_x-1;//img->pix_c_x-1;
int img_cx_4 = img_c_x+4;//img->pix_c_x+4;
int img_cy_1 = img_c_y-1;//img->pix_c_y-1;
int img_cy_4 = img_c_y+4;//img->pix_c_y+4;
int *pp;
int width_cr=img->width_cr+IMG_PAD_SIZE;
if(uv==0) pp=MbCb;
else pp=MbCr;
for (block_y=0; block_y<8; block_y+=4)
for (block_x=0; block_x<8; block_x+=4)
{
s=128;
s0=s1=s2=s3=0;
//===== get prediction value =====
switch ((block_y>>1) + (block_x>>2))
{
case 0: //===== TOP LEFT =====
if (img_cy > 0) for (i=0;i<4;i++) s0 += imgUV[uv][img_cy_1*width_cr+img_cx +i];
if (img_cx > 0) for (i=0;i<4;i++) s2 += imgUV[uv][(img_cy +i)*width_cr+img_cx_1 ];
if ((img_cy > 0) && (img_cx > 0)) s = (s0+s2+4) >> 3;
else if (img_cy > 0) s = (s0 +2) >> 2;
else if (img_cx > 0) s = (s2 +2) >> 2;
img->s[0]=s;
break;
case 1: //===== TOP RIGHT =====
if (img_cy > 0) for (i=0;i<4;i++) s1 += imgUV[uv][img_cy_1*width_cr+img_cx_4+i];
else if (img_cx > 0) for (i=0;i<4;i++) s2 += imgUV[uv][(img_cy +i)*width_cr+img_cx_1 ];
if (img_cy > 0) s = (s1 +2) >> 2;
else if (img_cx > 0) s = (s2 +2) >> 2;
img->s[1]=s;
break;
case 2: //===== BOTTOM LEFT =====
if (img_cx > 0) for (i=0;i<4;i++) s3 += imgUV[uv][(img_cy_4+i)*width_cr+img_cx_1 ];
else if (img_cy > 0) for (i=0;i<4;i++) s0 += imgUV[uv][img_cy_1*width_cr+img_cx +i];
if (img_cx > 0) s = (s3 +2) >> 2;
else if (img_cy > 0) s = (s0 +2) >> 2;
img->s[2]=s;
break;
case 3: //===== BOTTOM RIGHT =====
if (img_cy > 0) for (i=0;i<4;i++) s1 += imgUV[uv][img_cy_1*width_cr+img_cx_4+i];
if (img_cx > 0) for (i=0;i<4;i++) s3 += imgUV[uv][(img_cy_4+i)*width_cr+img_cx_1 ];
if ((img_cy > 0) && (img_cx > 0)) s = (s1+s3+4) >> 3;
else if (img_cy > 0) s = (s1 +2) >> 2;
else if (img_cx > 0) s = (s3 +2) >> 2;
img->s[3]=s;
break;
}
//===== prediction =====
for (j=block_y; j<block_y+4; j++)
for (i=block_x; i<block_x+4; i++)
{
pp[j*8+i]=s;
}
}
}
/************************************************************************
*
* Routine: motion_search()
*
* Description: In this routine motion search (integer pel+1/3 pel) and mode selection
* is performed. Since we treat all 4x4 blocks before coding/decoding the
* prediction may not be based on decoded pixels (except for some of the blocks).
* This will result in too good prediction. To compensate for this the SAD for
* intra(tot_intra_sad) is given a 'handicap' depending on QP.
*
* Input: Best intra SAD value.
*
* Output: Reference image.
*
************************************************************************/
#define IABS(x) absm((x))
int SAD_Macroblock(struct img_par *img,byte* ii, byte* kk,int Min_FRAME,int curr_sad)
{
int sad = curr_sad;
#ifdef FAST_SAD
int i;
int x0,x1,x2,x3,x4,x5;
int y0,y1,y2,y3,y4,y5;
int lx=img->width+(img->width<<1);
for(i=0;i<16;i+=3)
{
x0=ii[ 0]; y0=kk[ 0];
x1=ii[ 3]; y1=kk[ 3];
x2=ii[ 6]; y2=kk[ 6];
x3=ii[ 9]; y3=kk[ 9];
x4=ii[12]; y4=kk[12];
x5=ii[15]; y5=kk[15];
sad+=IABS(x0-y0)+IABS(x1-y1)+IABS(x2-y2)+IABS(x3-y3)+IABS(x4-y4)+IABS(x5-y5);
ii += lx; kk += lx;
if (sad > Min_FRAME) return 32767;
}
return sad;
#else
int i;
int lx=img->width+IMG_PAD_SIZE;
for(i=0;i<16;i+=1)
{
sad += (\
IABS(ii[ 0]-kk[ 0])
+IABS(ii[ 1]-kk[ 1])
+IABS(ii[ 2]-kk[ 2])
+IABS(ii[ 3]-kk[ 3])
+IABS(ii[ 4]-kk[ 4])
+IABS(ii[ 5]-kk[ 5])
+IABS(ii[ 6]-kk[ 6])
+IABS(ii[ 7]-kk[ 7])
+IABS(ii[ 8]-kk[ 8])
+IABS(ii[ 9]-kk[ 9])
+IABS(ii[10]-kk[10])
+IABS(ii[11]-kk[11])
+IABS(ii[12]-kk[12])
+IABS(ii[13]-kk[13])
+IABS(ii[14]-kk[14])
+IABS(ii[15]-kk[15]));
ii += lx;
kk += lx;
if (sad > Min_FRAME)
return 0x7fff;
}
return sad;
#endif
}
int SAD_Macroblock_sub(struct img_par *img,byte* ii, byte* kk,int Min_FRAME,int curr_sad)
{
int sad = curr_sad;
int i;
int lx=img->width+IMG_PAD_SIZE;
for(i=0;i<8;i+=1)
{
sad += (\
IABS(ii[ 0]-kk[ 0])
+IABS(ii[ 1]-kk[ 1])
+IABS(ii[ 2]-kk[ 2])
+IABS(ii[ 3]-kk[ 3])
+IABS(ii[ 4]-kk[ 4])
+IABS(ii[ 5]-kk[ 5])
+IABS(ii[ 6]-kk[ 6])
+IABS(ii[ 7]-kk[ 7])
+IABS(ii[ 8]-kk[ 8])
+IABS(ii[ 9]-kk[ 9])
+IABS(ii[10]-kk[10])
+IABS(ii[11]-kk[11])
+IABS(ii[12]-kk[12])
+IABS(ii[13]-kk[13])
+IABS(ii[14]-kk[14])
+IABS(ii[15]-kk[15]));
ii += lx;
kk += lx;
if (sad > Min_FRAME)
return 0x7fff;
}
return sad;
}
int SAD_Macroblock_sub2(struct img_par *img,byte* ii, byte* kk,int Min_FRAME,int curr_sad)
{
int sad = curr_sad;
int i;
int lx=img->width+IMG_PAD_SIZE;
for(i=0;i<16;i+=1)
{
sad += (\
IABS(ii[ 0]-kk[ 0])
+IABS(ii[ 1]-kk[ 1])
+IABS(ii[ 2]-kk[ 2])
+IABS(ii[ 3]-kk[ 3])
+IABS(ii[ 4]-kk[ 4])
+IABS(ii[ 5]-kk[ 5])
+IABS(ii[ 6]-kk[ 6])
+IABS(ii[ 7]-kk[ 7]));
ii += lx;
kk += lx;
if (sad > Min_FRAME)
return 0x7fff;
}
return sad;
}
int motion_search_16x8(struct img_par *img,int MinCost)
{
int i,index;
int vec0_x,vec0_y,vec1_x,vec1_y,vec2_x,vec2_y;
int pic_block_x,pic_block_y,pic_pix_y,pic_pix_x;
int ip0,ip1,ip2,ip3,ip4,ip5;
int best_inter_sad[2],current_inter_sad;
int tmp0,tmp1;
int lambda = QP2QUANT[img->qp-SHIFT_QP];
int x,y,offset,type,pos;
byte* curr;
byte* prev;
Point* point=search;
SAD_TABLE * sadTbl=sadTable;
int maxX=img->width-12;
int maxY=img->height-4;
int sadTimes=25;
int mvx0,mvy0,mvx1,mvy1;
int x_curr,y_curr;
int width=img->width+IMG_PAD_SIZE;
#ifdef FAST_INTEGER
int prev_AE1[17];
int prev_m1,prev_m2=0;
static int prevm[4] = {2, 3, 0, 1};
static int htp[4] = {-1, 0, 1, 0};
static int vtp[4] = {0, 1, 0, -1};
int j_min_now, i_min_now, i_min_next=0, j_min_next=0, sad_layr,Coffset,ioffset=0,l,m,j;
int distortion_0, distortion_1, distortion_2;
#endif
for(index=0;index<2;index++)
{
point=search;
sadTbl=sadTable;
pic_block_y=img->block_y+2*index;
pic_pix_y=img->pix_y+8*index;
pic_block_x=img->block_x;
pic_pix_x=img->pix_x;
x_curr=pic_pix_x;
y_curr=pic_pix_y;
if(index==0)
{
vec0_x=pic_block_x-1;
vec0_y=pic_block_y;
vec1_x=pic_block_x;
vec1_y=pic_block_y-1;
vec2_x=pic_block_x+4;
vec2_y=pic_block_y-1;
if (pic_block_y == 0)
{
vec1_x=vec0_x;
vec2_x=vec0_x;
vec1_y=vec0_y;
vec2_y=vec0_y;
}
if (vec2_x > (img->width>>2)-1)
{
vec2_x=pic_block_x-1;
}
ip1=tmp_mv[vec1_y][vec1_x+4][0];
ip0=tmp_mv[vec0_y][vec0_x+4][0];
ip2=tmp_mv[vec2_y][vec2_x+4][0];
ip3=tmp_mv[vec0_y][vec0_x+4][1];
ip4=tmp_mv[vec1_y][vec1_x+4][1];
ip5=tmp_mv[vec2_y][vec2_x+4][1];
if(!intra_mb_pos[vec1_y][vec1_x+4])
{
img->mv1[index][0] = ip1;
img->mv1[index][1] = ip4;
}
else
{
if((!intra_mb_pos[vec0_y][vec0_x+4])&&(intra_mb_pos[vec2_y][vec2_x+4]))
{
img->mv1[index][0] = ip0;
img->mv1[index][1] = ip3;
}
else if((intra_mb_pos[vec0_y][vec0_x+4])&&(!intra_mb_pos[vec2_y][vec2_x+4]))
{
img->mv1[index][0] = ip2;
img->mv1[index][1] = ip5;
}
else
{
img->mv1[index][0]=ip0+ip1+ip2-min(min(ip0,ip1),ip2)-max(max(ip0,ip1),ip2);
img->mv1[index][1]=ip3+ip4+ip5-min(min(ip3,ip4),ip5)-max(max(ip3,ip4),ip5);
}
}
}
else
{
vec0_x=pic_block_x-1;
vec0_y=pic_block_y;
vec1_x=pic_block_x;
vec1_y=pic_block_y-1;
vec2_x=pic_block_x-1;
vec2_y=pic_block_y-1;
ip1=curr_mvx1[0];
ip4=curr_mvy1[0];
ip0=tmp_mv[vec0_y][vec0_x+4][0];
ip2=tmp_mv[vec2_y][vec2_x+4][0];
ip3=tmp_mv[vec0_y][vec0_x+4][1];
ip5=tmp_mv[vec2_y][vec2_x+4][1];
if(!intra_mb_pos[vec0_y][vec0_x+4])
{
img->mv1[index][0] = ip0;
img->mv1[index][1] = ip3;
}
else
{
if(intra_mb_pos[vec2_y][vec2_x+4])
{
img->mv1[index][0] = ip1;
img->mv1[index][1] = ip4;
}
else
{
img->mv1[index][0]=ip0+ip1+ip2-min(min(ip0,ip1),ip2)-max(max(ip0,ip1),ip2);
img->mv1[index][1]=ip3+ip4+ip5-min(min(ip3,ip4),ip5)-max(max(ip3,ip4),ip5);
}
}
}
ip0=img->mv1[index][0];
ip1=img->mv1[index][1];
offset=width*pic_pix_y+pic_pix_x;
curr=imgY_org + offset;
prev=ipol[0] + offset;
#ifndef FAST_INTEGER
tmp0=-ip0;
tmp1=-ip1;
current_inter_sad=(lambda*(img->mv_bituse[absm(tmp0)]+img->mv_bituse[absm(tmp1)]));
best_inter_sad[index] = SAD_Macroblock_sub(img,curr, prev, MAX_VALUE,current_inter_sad);
//best_inter_sad[index] -= lambda * 16;//is 16x16block,here should not
mvx0=0;
mvy0=0;
pos=0;
for (i = 1; i < sadTimes; i++)
{
sadTbl++;
x=x_curr+sadTbl->dx;
y=y_curr+sadTbl->dy;
//if((x<0)||(y<0)||(x>maxX)||(y>maxY))
// continue;
tmp0=(sadTbl->dx<<2)-ip0;
tmp1=(sadTbl->dy<<2)-ip1;
current_inter_sad=(lambda*(img->mv_bituse[absm(tmp0)]+img->mv_bituse[absm(tmp1)]));
//current_inter_sad+ = SAD_Macroblock_sub(img,prev+sadTbl->offset, curr, best_inter_sad[index],current_inter_sad);
current_inter_sad = SAD_Macroblock_sub(img,prev+sadTbl->offset, curr, best_inter_sad[index],current_inter_sad);
if (current_inter_sad < best_inter_sad[index])
{
pos=i;
best_inter_sad[index] = current_inter_sad;
}
}
mvx0 = sadTable[pos].dx;
mvy0 = sadTable[pos].dy;
offset+=sadTable[pos].offset;
x_curr+=mvx0;
y_curr+=mvy0;
#else
i_min_now = min(maxX,max(-4, x_curr+(ip0>>2)));
j_min_now = min(maxY,max(-4, y_curr+(ip1>>2)));
//i_min_now = x_curr;
//j_min_now = y_curr;
mvx0=i_min_now-x_curr;
mvy0=j_min_now-y_curr;
ioffset=width*mvy0+mvx0;
tmp0=(mvx0<<2)-ip0;
tmp1=(mvy0<<2)-ip1;
current_inter_sad=(lambda*(img->mv_bituse[absm(tmp0)]+img->mv_bituse[absm(tmp1)]));
best_inter_sad[index] = SAD_Macroblock_sub(img,curr, prev+j_min_now*width+i_min_now-offset, MAX_VALUE,current_inter_sad);
distortion_0 = distortion_1 = distortion_2 = 65536;
prev_AE1[0] = best_inter_sad[index];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -