homerHEVC代码阅读(27)——CTU初始化函数init_ctu

init_ctu主要用来初始化CTU的坐标,长度等各个属性,还有重要的一步是获取当前CTU的邻居,并设置相应的标志。

// ctu初始化
ctu_info_t* init_ctu(henc_thread_t* et)
{
    ctu_info_t *ctu;
    int ctu_width, ctu_height;

    // 获取当前的cu
    ctu = &et->enc_engine->ctu_info[et->cu_current];//&et->curr_ctu_group_info[0];

    // 当前cu的索引
    ctu->ctu_number = et->cu_current;

    // et->cu_current_x是当前cu的坐标(并不是像素坐标,而是索引坐标)


    // 设置ctu三个分量的像素坐标
    ctu->x[Y_COMP] = et->cu_current_x*et->ctu_width[Y_COMP];
    ctu->y[Y_COMP] = et->cu_current_y*et->ctu_height[Y_COMP];


    ctu->x[U_COMP] = ctu->x[V_COMP] = et->cu_current_x*et->ctu_width[U_COMP];
    ctu->y[U_COMP] = ctu->y[V_COMP] = et->cu_current_y*et->ctu_height[U_COMP];

    // 设置CTU的尺寸,即LCU的尺寸64x64
    ctu->size = et->max_cu_size;

    // 设置ctu的划分数量
    ctu->num_part_in_ctu = et->num_partitions_in_cu;
    ctu->num_part_in_ctu = et->num_partitions_in_cu;

    //	ctu->partition_list = &et->partition_info[0];

    // ctu的宽和高,之所以这样设置的原因是为了防止有些图像的宽和高不是CTU的整数倍
    // ctu->x[Y_COMP] 表示CTU的起始位置(像素坐标),ctu->size表示CTU的宽和高(被设置为64x64)
    // ctu->x[Y_COMP]+ctu->size 就表示计算CTU最后一个像素的位置,用来判断当前的CTU(被设置为64x64)是否超出了图像的边界
    // 如果图像不是64x64的整数倍,那么某一个边缘的CTU必然会超出图像的边界,所以需要调整该边缘CTU的宽和高
    ctu_width = ((ctu->x[Y_COMP]+ctu->size) < et->pict_width[Y_COMP])?(ctu->size):et->pict_width[Y_COMP]-ctu->x[Y_COMP];
    ctu_height = ((ctu->y[Y_COMP]+ctu->size) < et->pict_height[Y_COMP])?(ctu->size):et->pict_height[Y_COMP]-ctu->y[Y_COMP];

    // 如果最后计算出来的宽和高不是64,那么需要调整CTU的宽和高
    if(ctu_width!=ctu->size || ctu_height!=ctu->size)
    {
        // 如果当前CTU被划分,那么每一个部分的宽度
        int width_in_partitions = ctu_width>>2;

        // 如果当前CTU被划分,那么每一个部分的高度
        int height_in_partitions = ctu_height>>2;

        // 如果当前CTU被划分,那么每一个部分的尺寸
        int cu_size_in_partitions = ctu->size>>2;
        //		if(height_in_partitions == cu_size_in_partitions)
        //			height_in_partitions = cu_size_in_partitions-1;
        //		else if(width_in_partitions == cu_size_in_partitions)

        height_in_partitions -= 1;

        // 最后一个有效的划分,raster2abs_table这个转换表是从像素地址转换为索引地址
        ctu->last_valid_partition =	et->enc_engine->raster2abs_table[height_in_partitions*cu_size_in_partitions+width_in_partitions-1];
    }
    else
    {
        // 最后一个有效的划分
        ctu->last_valid_partition = et->num_partitions_in_cu-1;
    }

    // 获取当前ctu的邻居
    CuGetNeighbors(et, ctu);//raster order
    return ctu;
}

// 取得cu的邻居
void CuGetNeighbors(henc_thread_t* et, ctu_info_t* ctu)
{
    // 如果CTU的横坐标是0,那么表示他的左边没有邻居
    if(ctu->x[Y_COMP]==0)
        ctu->ctu_left = NULL;
    else
    {
        // 否则有左邻居
        ctu->ctu_left = &et->enc_engine->ctu_info[ctu->ctu_number-1];
    }

    // 由于使用了wfpp的方式,一般认为左下角的邻居不存在
    ctu->ctu_left_bottom = NULL;//en raster order este no existe. En wavefront si

    // 如果ctu的纵坐标是0,表示它的上面、左上角、右上角的邻居为空
    if(ctu->y[Y_COMP]==0)
    {
        ctu->ctu_top = NULL;
        ctu->ctu_top_right = NULL;
        ctu->ctu_top_left = NULL;
    }
    // 如果纵坐标不为0
    else
    {
        ctu->ctu_top = &et->enc_engine->ctu_info[ctu->ctu_number-et->pict_width_in_ctu];

        // 但是横坐标为0,那么它的左上角不存在
        if(ctu->x[Y_COMP]==0)
            ctu->ctu_top_left = NULL;
        else
            ctu->ctu_top_left = &et->enc_engine->ctu_info[ctu->ctu_number-et->pict_width_in_ctu-1];

        // 判断是否存在右上角
        // 如果当前CTU位于帧的右边缘,那么它不存在右上角邻居
        if(et->cu_current_y==0 || ((et->cu_current_x % et->pict_width_in_ctu) == (et->pict_width_in_ctu-1)))
            ctu->ctu_top_right = NULL;
        else
        {
            ctu->ctu_top_right = &et->enc_engine->ctu_info[ctu->ctu_number-et->pict_width_in_ctu+1];
        }
    }
}


你可能感兴趣的:(h.265,视频编码,HEVC)