homerHEVC代码阅读(10)——基础结构之picture_t、slice_t、ctu_info_t

picture_t表示一帧图像。注意到picture_t中只包含一个片。而实际的数据由video_frame_t对象来管理(或者说由video_frame_t对象来指向)。
slice_t表示图像中的片。

ctu_info_t表示一个CTU。

参考图像列表list0和list1的区别:
P帧只参考list0的图像。
B帧参考list0和list1的图像。

list0中可以包含,编码顺序在当前帧之前但是播放顺序在当前帧之后的图像(即后向帧),也包含前向帧。

在编码的过程中,一个帧只能被标志为:
1、不是参考帧
2、放在short-term中作为参考帧
3、放在long-term中作为参考帧
4、直接输出

list0中的帧可以是short-term也可以是long-term。

short-term中的图像,由自带的picnum(每个图像有一个变量),计算出一个值,然后从高到底排列在short-term中。
long-term也一样,但是它的次序是从低到高的。

每次编码完成一个帧,这个次序(short-term和long-term中帧的次序)都会变动。

正常情况下,编完一帧都是把它放到最近的short-term中,意味着最容易被参考到,如果编码器需要改动,就会把某一帧放到short-term的后面,就是long-term,这些都是按照long-term picnum和short-term picnum大的大小次序存放的。

总结帧间预测的过程就是:
1、从ListX=0(即list0)开始(即前向预测),将参考索引iRefIndex设置为0
2、在当前iRefIndex下,生成高级运动矢量预测(AMVP)候选列表,得到最佳的运动矢量和最小代价;
3、以步骤2中选中的AMVP为起始点,在当前的iRefIndex帧内,以SA(T)D+λpred*Bits为代价进行运动估计,得到最佳的运动矢量和最小代价
4、置 iRefIndex=iRefIndex+l,重复步骤2和3,得到当前 iReflndex下的最佳运动矢量和最小代价;直到参考帧队列ListX中的所有标记为“Used for Reference“的参考帧都完成最佳运动矢量和最小代价的计算,并从中挑选代价最小的iReflndex作为当前预测方向下,最佳的参考索引;
5、将ListX=1 (即后向预测),重复(2)到(4)步骤,并挑选代价最小的iReflndex作为当前预测方向下的最佳的参考索引;
6、固定以List0 (或者List1)中最佳的参考索引和运动矢量为双向预测中的其中之一,对List1(或者list0)中所有参考索引进行(2)到(4)步骤,并找到最佳的双向预测参考索引和运动矢量。
7、比较前向预测、后向预测以及双向预测的最小代价,选择出最佳的预测方向。

参考图像集中存放的实际是图像的poc。
参考图像集实际的作用是管理已编码的图像,为后续的帧提供参考的图像,参考图像列表中的帧是从参考图像集中选出的。

struct picture_t
{
    // 片,在目前的编码器中,一帧中只有一片
    slice_t	slice;

    // 将要编码的帧
    video_frame_t	*img2encode;
};

struct slice_t
{
    // 片的索引
    uint32_t slice_index; //indice en la lista de slices

    // 片的类型
    uint32_t slice_type;

    // nal类型
    uint32_t nalu_type;

    // 该片中第一个slice的开始地址
    uint32_t first_cu_address;//address of first coding tree block in the slice

    // 当前cu的地址
    uint32_t curr_cu_address;//address of current coding tree block in the slice

    // 该片中最后一个cu的地址
    uint32_t last_cu_address;//m_uiDependentSliceCurEndCUAddr - address of current coding tree block in the slice partition units (256 per CU)

    // 是否为依赖性片
    uint32_t is_dependent_slice;//
    uint32_t slice_temporal_layer_non_reference_flag;//

    // 时域层mvp标识
    uint32_t slice_temporal_mvp_enable_flag;

    // 去方块滤波标识
    uint32_t deblocking_filter_disabled_flag;
    uint32_t sao_luma_flag;
    uint32_t sao_chroma_flag;
    uint32_t slice_loop_filter_across_slices_enabled_flag;
    uint32_t slice_beta_offset_div2;
    uint32_t slice_tc_offset_div2;

    // merge模式的最大候选数量
    uint32_t max_num_merge_candidates;

    // 对应的序列参数集
    sps_t		*sps;

    // 对应的图像参数集
    pps_t		*pps;

    // 量化步长
    int qp;

    // 图像计数
    uint32_t poc;

    // 深度
    uint32_t depth;

    // 子时域层
    uint32_t sublayer;//TLayer

    // 被参考的计数
    uint32_t referenced;

    // 参考的图像的索引数组
    uint32_t num_ref_idx[2];

    // 使用的参考图像集的索引
    uint32_t ref_pic_set_index;
    
    // 参考图像集中存放的实际是图像的poc
    // 参考图像集实际的作用是管理已编码的图像
    // 为后续的帧提供参考的图像
    // 参考图像列表中的帧是从参考图像集中选出的
    ref_pic_set_t	*ref_pic_set;

    // 参考的图像列表
    // 即list0和list1,P帧使用list0,B帧使用list0和list1
    video_frame_t	*ref_pic_list[2][MAX_NUM_REF];

    // 两个参考图像列表的长度,即ref_pic_list的长度
    int				ref_pic_list_cnt[2];
};

struct ctu_info_t 
{
    // cut编号
    int				ctu_number;
    // 该ctu在帧中的坐标(yuv三个分量)
    int				x[3],y[3];//global coordinates in frame
    // 尺寸
    int				size;
    // 该ctu被分成了多少个部分
    int				num_part_in_ctu;
    // 最后一个有效的分区
    int				last_valid_partition;
    // 失真
    uint32_t		distortion;

    // 分区信息列表
    cu_partition_info_t	*partition_list;

    uint8_t			*cbf[NUM_PICT_COMPONENTS];//[MAX_NUM_PARTITIONS];

    // 帧内预测模式
    uint8_t			*intra_mode[NUM_PICT_COMPONENTS-1];//[MAX_NUM_PARTITIONS];

    // 帧间预测模式
    uint8_t			*inter_mode;//[MAX_NUM_PARTITIONS];
    // 四叉树的索引
    uint8_t			*tr_idx;//[MAX_NUM_PARTITIONS];

    // 预测的深度
    uint8_t			*pred_depth;//[MAX_NUM_PARTITIONS];

    // 对ctu分割时的类型NxN还是2NxN等
    uint8_t			*part_size_type;//[MAX_NUM_PARTITIONS];
    // 预测模式
    uint8_t			*pred_mode;//[MAX_NUM_PARTITIONS];//intra or inter

    // skip模式
    uint8_t			*skipped;//[MAX_NUM_PARTITIONS];

    // merge模式
    uint8_t			*merge;
    // merge模式的索引
    uint8_t			*merge_idx;

    // 量化步长
    uint8_t			*qp;

    // 系数窗口
    wnd_t			*coeff_wnd;

    //inter

    // 参考的两个运动向量
    motion_vector_t		*mv_ref[2];
    // 运动向量的索引(不知到作用是什么)
    int8_t				*mv_ref_idx[2];
    // 运动向量的残差
    motion_vector_t		*mv_diff[2];
    // 运动向量残差的索引(不知道作用是什么)
    uint8_t				*mv_diff_ref_idx[2];

    //	uint8_t				*ref_idx1;

    // 当前ctu左边的ctu
    ctu_info_t		*ctu_left;
    // 左下角的ctu
    ctu_info_t		*ctu_left_bottom;
    // 上方的ctu
    ctu_info_t		*ctu_top;
    // 右上角的ctu
    ctu_info_t		*ctu_top_right;
    // 左上角的ctu
    ctu_info_t		*ctu_top_left;

    // 上方的啥?/左边的啥?
    int				top;
    int				left;

    //sao
    //	sao_stat_data_t (*stat_data)[NUM_PICT_COMPONENTS][NUM_SAO_NEW_TYPES];//to save memory this can be allocated in a wpp thread basis when processing is distributed (COMPUTE_AS_HM undefined)
    // sao的数据
    sao_stat_data_t stat_data[NUM_PICT_COMPONENTS][NUM_SAO_NEW_TYPES];//to save memory this can be allocated in a wpp thread basis when processing is distributed (COMPUTE_AS_HM undefined)

    // sao重建的参数
    sao_blk_param_t recon_params;

    // sao编码的参数
    sao_blk_param_t coded_params;
    //quant
    //	int				/*qp, */qp_chroma;/*, prev_qp, prev_dqp*/
    //    int				per;//, per_chroma;
    //    int				rem;//, rem_chroma;
    //    int				qpbits;
    //	uint			variance;
};


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