c_prei类的定义
class c_prei
{
fetch_req_t fetch_req;
fetch_t fetch_data;
//input var
param_t param;
rc_t prei_input;
//output var
prei_t prei_output;
int8_t mb_type;
//luma mode & split var
int8_t luma_64x64_mode;
int8_t luma_32x32_mode[4];
int8_t luma_16x16_mode[4][4];
int8_t luma_8x8_mode[4][4][4];
int8_t luma_4x4_mode[4][4][4][4];
/*****************************************
* private func *
*****************************************/
void init();
void load(param_t param_input, rc_t rc_frame);
void fetch(c_fetch u_fetch);
void run();
void update(prei_t &prei_out);
void org_pred8x8(int i, int j, int k, PIXEL orig[f_LCU_SIZE][f_LCU_SIZE], int *bestmode, int mode[35], int *data_tmp);
int compare16x16(int mode[35], int data_tmp);
int compare32x32(int mode[35], int data_tmp);
int compare64x64(int mode[35], int data_tmp);
public:
void prei_proc(param_t param_input, rc_t rc_frame, c_fetch u_fetch, prei_t &prei_out);
};
1.定义prei_proc函数
void c_prei::prei_proc**(param_t param_input, rc_t rc_frame, c_fetch u_fetch, prei_t &prei_out)
{
load(param_input, rc_frame);
fetch(u_fetch);
run();//得出从4×4到64×64的亮度最佳预测模式 : luma_N*N_mode=bestmode
update(prei_out);// prei_output.luma_N*N_mode = luma_N*N_mode;
}
2.初始化c_prei
void c_prei::init()
{
}
3.定义load函数
void c_prei::load(param_t param_input, rc_t rc_frame)
{
param = param_input;//将输入参数赋值给param参数;
prei_input = rc_frame;//将rc_frame赋值给 prei_input;
}
4.定义fetch函数
void c_prei::fetch(c_fetch u_fetch)
{
// 从fetch中加载pixel warning: keep the piepline fetch code, otherwise it will be wrong. todo: find the reason从fetch中加载pixel
fetch_req.x = prei_input.x;
fetch_req.y = prei_input.y;
fetch_data = u_fetch.fetch_mb_proc(param, fetch_req);
}
c_fetch类中的 fetch_mb_proc 定义
fetch_t c_fetch::fetch_mb_proc(param_t param, fetch_req_t req_input)
{
param_input = param;
fetch_output.cur_mb = fetch_cur_mb(req_input.x, req_input.y);
fetch_output.x = req_input.x;
fetch_output.y = req_input.y;
fetch_output.frame_num = param_input.frame_num;
return fetch_output;
}
5.定义run函数 最终得出从4×4到64×64的亮度最佳预测模式 : luma_N*N_mode=bestmode
void c_prei::run()
{
int i, j, k, m;
int bestmode = 0;//初始化bestmode为0
//初始化8×8,16×16,32×32,64×64块的35种角度预测模式
int mode[35];
int mode16[35];
int mode32[35];
int mode64[35];
//初始化gx与gy之和均为0
int data_tmp16 = 0;
int data_tmp32 = 0;
int data_tmp64 = 0;
int data_tmp = 0;
//初始化64*64块预测模式均为模式0
for (m = 0; m < 35; m++) {
mode64[m] = 0;
}
//初始化32*32块预测模式均为模式0
for (i = 0; i < 4; i++)//四次循环,将32*32的mode32相加4次赋值于64*64的mode64
{
for (m = 0; m < 35; m++) {
mode32[m] = 0;
}
data_tmp32 = 0;
//初始化16*16块预测模式均为模式0
for (j = 0; j < 4; j++)//四次循环,将16*16的mode16相加4次赋值于32*32的mode32
{
for (m = 0; m < 35; m++)
{
mode16[m] = 0;
}
data_tmp16 = 0;
//计算16*16的mode16
for (k = 0; k < 4; k++)//四次循环,将8*8的mode相加4次赋值于16*16的mode16
{
{
org_pred8x8(i, j, k, fetch_data.cur_mb.luma, &bestmode, mode, &data_tmp);
//计算8*8的最佳预测角度,4*4也将运用此角度
//fetch_data.cur_mb.luma为8*8和4*4的亮度像素
luma_8x8_mode[i][j][k] = bestmode;
luma_4x4_mode[i][j][k][0] = bestmode;
luma_4x4_mode[i][j][k][1] = bestmode;
luma_4x4_mode[i][j][k][2] = bestmode;
luma_4x4_mode[i][j][k][3] = bestmode;
for (m = 0; m < 35; m++)
{
mode16[m] += mode[m];//将16*16中的4个8*8的mode值相加得到mode16的值,k为0-3循环,所以一共相加计算4次
}
data_tmp16 += data_tmp;
}
luma_16x16_mode[i][j] = compare16x16(mode16, data_tmp16);
for (m = 0; m < 35; m++)
{
mode32[m] += mode16[m];
}
data_tmp32 += data_tmp16;
}
luma_32x32_mode[i] = compare32x32(mode32, data_tmp32);
for (m = 0; m < 35; m++)
{
mode64[m] += mode32[m];
}
data_tmp64 += data_tmp32;
}
luma_64x64_mode = compare64x64(mode64, data_tmp64);
}
6.定义update
void c_prei::update(prei_t &prei_out)
{
//--------------update output------------//
prei_output.name = "prei";
prei_output.x = prei_input.x;
prei_output.y = prei_input.y;
prei_output.qp = prei_input.qp;
prei_output.mb_type = INTRA_TYPE;
//mode
prei_output.luma_64x64_mode = luma_64x64_mode;
memcpy(prei_output.luma_32x32_mode, luma_32x32_mode, sizeof(prei_output.luma_32x32_mode));
memcpy(prei_output.luma_16x16_mode, luma_16x16_mode, sizeof(prei_output.luma_16x16_mode));
memcpy(prei_output.luma_8x8_mode, luma_8x8_mode, sizeof(prei_output.luma_8x8_mode));
memcpy(prei_output.luma_4x4_mode, luma_4x4_mode, sizeof(prei_output.luma_4x4_mode));
prei_out = prei_output;
}
7.定义org_pred8x8————最终得到bestmode
void c_prei::org_pred8x8(int i, int j, int k, PIXEL orig[f_LCU_SIZE][f_LCU_SIZE], int *bestmode, int mode[35], int *data_tmp)
//i,j,k分别表示块在64*64的CTB的四叉树中的位置,按Z字形排列,org为原始像素,data_tmp表示梯度x和梯度y之和。
{
int m;//定义模式变量m
int n;//定义在坐标中的位置
int l;//定义在坐标中的位置
int gx;
int gy;
int best_mode = 2;
for (m = 0; m < 35; m++) {
mode[m] = 0;
}
*data_tmp = 0;
n = (i % 2) * 32 + (j % 2) * 16 + (k % 2) * 8; //横向坐标
l = (i / 2) * 32 + (j / 2) * 16 + (k / 2) * 8;//纵向坐标
//不计算边缘像素的6*6块的梯度计算
for (i = l + 1; i < l + 7; i++) {
for (j = n + 1; j < n + 7; j++) {
gx = orig[i - 1][j - 1] + 2 * orig[i][j - 1] + orig[i + 1][j - 1]
- orig[i - 1][j + 1] - 2 * orig[i][j + 1] - orig[i + 1][j + 1];
gy = orig[i + 1][j - 1] + 2 * orig[i + 1][j] + orig[i + 1][j + 1]
- orig[i - 1][j - 1] - 2 * orig[i - 1][j] - orig[i - 1][j + 1];
//角度预测模式:计算模式2到模式33的像素不同角度平坦度
mode[2] += abs(90 * gx + 90 * gy);
mode[3] += abs(99 * gx + 81 * gy);
mode[4] += abs(107 * gx + 70 * gy);
mode[5] += abs(113 * gx + 60 * gy);
mode[6] += abs(118 * gx + 48 * gy);
mode[7] += abs(123 * gx + 35 * gy);
mode[8] += abs(126 * gx + 20 * gy);
mode[9] += abs(127 * gx + 8 * gy);
mode[10] += abs(128 * gx);
mode[11] += abs(127 * gx - 8 * gy);
mode[12] += abs(126 * gx - 20 * gy);
mode[13] += abs(123 * gx - 35 * gy);
mode[14] += abs(118 * gx - 48 * gy);
mode[15] += abs(113 * gx - 60 * gy);
mode[16] += abs(107 * gx - 70 * gy);
mode[17] += abs(99 * gx - 81 * gy);
mode[18] += abs(90 * gx - 90 * gy);
mode[19] += abs(81 * gx - 99 * gy);
mode[20] += abs(70 * gx - 107 * gy);
mode[21] += abs(60 * gx - 113 * gy);
mode[22] += abs(48 * gx - 118 * gy);
mode[23] += abs(35 * gx - 123 * gy);
mode[24] += abs(20 * gx - 126 * gy);
mode[25] += abs(8 * gx - 127 * gy);
mode[26] += abs(128 * gy);
mode[27] += abs(8 * gx + 127 * gy);
mode[28] += abs(20 * gx + 126 * gy);
mode[29] += abs(35 * gx + 123 * gy);
mode[30] += abs(48 * gx + 118 * gy);
mode[31] += abs(60 * gx + 113 * gy);
mode[32] += abs(70 * gx + 107 * gy);
mode[33] += abs(81 * gx + 99 * gy);
(*data_tmp) += abs(gx) + abs(gy);//用于计算整体像素的平坦度
}
}
for (i = 3; i < 34; i++) {
if (mode[i] < mode[best_mode])
best_mode = i;//将模式3到模式33梯度计算值与模式2相比较,将最小的模式赋值给best_mode
}
if ((*data_tmp) < 8 * 36)//8*36
best_mode = 1;//如果data_tmp很小,说明当前块所有像素使用同一个值,则使用DC模式,即模式1
else if (mode[best_mode] > 32 * (*data_tmp))
best_mode = 0;//如果不满足DC条件,但是data_tmp已经小于角度预测模式中的best_mode,则选用平面Planar模式,即模式0
*bestmode = best_mode;//最后比较完成,将上面的结果best_mode赋值给bestmode
}
8.定义compare16x16————返回bestmode
int c_prei::compare16x16(int mode[35], int data_tmp)//注意此时的mode为形参,下同
{
int i;
int bestmode = 2;
for (i = 3; i < 34; i++) {
if (mode[i] < mode[bestmode])
bestmode = i;
}
if (data_tmp < 8 * 144)//8*36*4
bestmode = 1;
else if (mode[bestmode] > 32 * data_tmp)
// if(data_tmp<16*144)
// bestmode=1;
// else
bestmode = 0;
return bestmode;
}
9.定义compare32x32————返回bestmode
int c_prei::compare32x32(int mode[35], int data_tmp)
{
int i;
int bestmode = 2;
for (i = 3; i < 34; i++) {
if (mode[i] < mode[bestmode])
bestmode = i;
}
if (data_tmp < 8 * 576)//8*36*4*4
bestmode = 1;
else if (mode[bestmode] > 32 * data_tmp)
// if(data_tmp<16*576)
// bestmode=1;
// else
bestmode = 0;
return bestmode;
}
10.定义compare64x64————返回bestmode
int c_prei::compare64x64(int mode[35], int data_tmp)
{
int i;
int bestmode = 2;
for (i = 3; i < 34; i++) {
if (mode[i] < mode[bestmode])
bestmode = i;
}
if(data_tmp<8*2304)//8*36*4*4*4
bestmode=1;
else if(mode[bestmode]>30*data_tmp)
// if(data_tmp<16*2304)
// bestmode=1;
// else
bestmode=0;
return bestmode;
}