homerHEVC代码阅读(29)——创建当前CTU的划分块的邻居信息create_partition_ctu_neighbours

create_partition_ctu_neighbours的作用是计算当前CTU中的每一个CU的邻居存在的标志。

// 计算CTU下所有CU的邻居存在的标志
void create_partition_ctu_neighbours(henc_thread_t* et, ctu_info_t *ctu, cu_partition_info_t* curr_partition_info)
{
    // 父CU的分割信息
	cu_partition_info_t*	parent_part_info = curr_partition_info->parent;

    // 当前深度
	int curr_depth = curr_partition_info->depth;

    // 深度状态
	int depth_state[MAX_PARTITION_DEPTH] = {0,0,0,0,0};

	int cu_min_tu_size_shift = max((et->max_cu_size_shift - (et->max_pred_partition_depth+max(et->max_intra_tr_depth, et->max_inter_tr_depth)-1)), MIN_TU_SIZE_SHIFT);//(et->max_cu_size_shift - (et->max_pred_partition_depth+et->max_intra_tr_depth-1))>MIN_TU_SIZE_SHIFT?(et->max_cu_size_shift - (et->max_pred_partition_depth+et->max_intra_tr_depth)):MIN_TU_SIZE_SHIFT;//+ interSplitFlag + intraSplitFlag	//(part_size_type==SIZE_NxN));//

    int max_processing_depth = et->max_cu_size_shift-cu_min_tu_size_shift;

    // 一帧中ctu的行数
    int ctu_valid_lines = (ctu->y[Y_COMP]+ctu->size)>et->pict_height[Y_COMP]?(et->pict_height[Y_COMP]-ctu->y[Y_COMP]):ctu->size;//((ctu->y[Y_COMP]+ctu->size)>et->pict_height)?(et->pict_height-ctu->y[Y_COMP]):ctu->size;

    // 一帧中ctu的列数
    int ctu_valid_colums = (ctu->x[Y_COMP]+ctu->size)>et->pict_width[Y_COMP]?(et->pict_width[Y_COMP]-ctu->x[Y_COMP]):ctu->size;//((ctu->y[Y_COMP]+ctu->size)>et->pict_width)?(et->pict_width-ctu->y[Y_COMP]):ctu->size;


	while(curr_depth!=0 || depth_state[curr_depth]!=1)
	{
		curr_depth = curr_partition_info->depth;

        // ctu->y表示该CTU在帧中的坐标
        // y_position则表示CTU的某一个cu在该CTU中的坐标,两者相加可以得到cu的实际坐标

        // 这个标志就表示该cu的左上角是否仍然在帧内
        curr_partition_info->is_tl_inside_frame =
                (ctu->y[Y_COMP]+curr_partition_info->y_position < et->pict_height[Y_COMP])
                && (ctu->x[Y_COMP]+curr_partition_info->x_position < et->pict_width[Y_COMP]);

        // 这个标志表示该cu的底部是否仍然在帧内
        curr_partition_info->is_b_inside_frame =
                (ctu->y[Y_COMP]+curr_partition_info->y_position+curr_partition_info->size <= et->pict_height[Y_COMP]);


        // 这个标志表示该cu的右侧是否仍然在帧内
        curr_partition_info->is_r_inside_frame =
                (ctu->x[Y_COMP]+curr_partition_info->x_position+curr_partition_info->size <= et->pict_width[Y_COMP]);

        // 如果当前CU的左上角在帧内
		if(curr_partition_info->is_tl_inside_frame)
		{
            // 如果父亲cu的划分信息为空
			if(parent_part_info == NULL)//ctu
			{
				curr_partition_info->left_neighbour = ctu->ctu_left?1:0;
				curr_partition_info->top_neighbour = ctu->ctu_top?1:0;
				curr_partition_info->left_bottom_neighbour = ctu->ctu_left_bottom?1:0;
				curr_partition_info->top_right_neighbour = ctu->ctu_top_right?1:0; 
			}
			else
                // 如果父cu的划分信息不为空,获取CU的划分块的邻居信息
				cu_partition_get_neighbours(curr_partition_info, et->max_cu_size, ctu_valid_colums, ctu_valid_lines);
		}

        // 深度状态改变
		depth_state[curr_depth]++;
        
        // 如果当前的深度未到达最大的处理深度,而且 当前CU仍在帧的内部,那么继续按照四叉树的方式向下计算
		if(curr_depth<max_processing_depth && curr_partition_info->is_tl_inside_frame)//if tl is not inside the frame don't process the next depths
		{
			curr_depth++;
			parent_part_info = curr_partition_info;
		}
        // 如果上述两个条件中的一个不满足,即:当前深度达到了最大的处理深度,或者当前CU不在帧的内部
        // 同时当前深度的四个分区已经处理完毕,那么就从当前深度一直沿着四叉树的分支向上,直到遇到一个某一个深度状态不是4的CU,继续处理
		else if(depth_state[curr_depth]==4)
		{
			while(depth_state[curr_depth]==4)
			{
				depth_state[curr_depth] = 0;
				curr_depth--;
				parent_part_info = parent_part_info->parent;
			}
		}

        // 调整当前cu分割信息
		if(parent_part_info!=NULL)
			curr_partition_info = parent_part_info->children[depth_state[curr_depth]];
	}
}

cu_partition_get_neighbours的作用设置cu的邻居存在的标志

// 获取cu的划分(分割、分区)的邻居信息(不能用于CTU)
void cu_partition_get_neighbours(cu_partition_info_t *curr_part, int cu_size, int ctu_valid_colums, int ctu_valid_lines)
{
    // 获取当前cu的父亲cu
	cu_partition_info_t	*parent = curr_part->parent;

    // 如果父亲CU有左邻居或者当前CU的横坐标大于0,那么当前CU一定存在左邻居
	if(parent->left_neighbour || curr_part->x_position)
		curr_part->left_neighbour = 1;
	else
        // 否则不存在左邻居
		curr_part->left_neighbour = 0;

    // 如果父亲cu有上侧邻居 或者 当前cu的纵坐标大于0 ,那么当前CU一定存在上侧邻居
	if(parent->top_neighbour || curr_part->y_position)
		curr_part->top_neighbour = 1;
	else
		curr_part->top_neighbour = 0;

    // 同上判断是否存在左下角邻居
	if((parent->left_bottom_neighbour && curr_part->x_position == parent->x_position) ||
	  (parent->left_neighbour && curr_part->x_position == parent->x_position && curr_part->y_position == parent->y_position && ctu_valid_lines>curr_part->y_position+curr_part->size))// && parent->is_b_inside_frame))
		curr_part->left_bottom_neighbour = 1;
	else 
		curr_part->left_bottom_neighbour = 0;

    // 判断是否存在右上角邻居
	if((parent->top_right_neighbour && curr_part->y_position == parent->y_position) ||
	  (parent->top_neighbour && curr_part->x_position == parent->x_position && curr_part->y_position == parent->y_position && ctu_valid_colums>curr_part->x_position+curr_part->size) ||
	  (curr_part->x_position == parent->x_position && curr_part->y_position != parent->y_position && ctu_valid_colums>curr_part->x_position+curr_part->size))//parent->is_r_inside_frame))
		curr_part->top_right_neighbour = 1;
	else 
		curr_part->top_right_neighbour = 0;
}


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