SVAC-Intra-Prei 代码分析(帧内预测最佳预测角度的选择)

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*84*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中的48*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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值