homerHEVC代码阅读(28)——mem_transfer_move_curr_ctu_group、mem_transfer_intra_refs

mem_transfer_move_curr_ctu_group把数据从原始帧复制到当前宏块窗口,目的是留下一个备份,将来会用到。

mem_transfer_intra_refs把数据从解码宏块窗口中复制到当前引用的参考帧上,用作帧内预测.

// 把MBs从图像中移动到当前的MB窗口,把数据从原始帧复制到当前宏块窗口的目的是留下一个备份,将来会用到
void mem_transfer_move_curr_ctu_group(henc_thread_t* et, int i, int j)//i,j are cu indexes
{
	int width, height, component;

    // 目标窗口:MBs窗口(curr_mbs_wnd不知道是否可以看作是当前的宏块窗口)
	wnd_t* dst_wnd = &et->curr_mbs_wnd;
	byte * src;
	byte * dst;
	int src_stride, dst_stride;

    // 针对三个分量分别进行处理
	for(component=Y_COMP;component<=V_COMP;component++)
	{
        // 源数据就是当前帧
		src = WND_POSITION_2D(byte *, et->enc_engine->current_pict.img2encode->img, component, (i*et->ctu_width[component]), (j*et->ctu_height[component]), 0, et->ctu_width);

        // 目标缓存区就是当前宏块窗口
        dst = WND_POSITION_2D(byte *, *dst_wnd, component, 0, 0, 0, et->ctu_width);

		src_stride =  WND_STRIDE_2D(et->enc_engine->current_pict.img2encode->img, component);
		dst_stride =  WND_STRIDE_2D(*dst_wnd, component);

		width = ((i+1)*et->ctu_width[component]<et->pict_width[component])?et->ctu_width[component]:(et->pict_width[component]-(i*et->ctu_width[component]));
		height = ((j+1)*et->ctu_height[component]<et->pict_height[component])?et->ctu_height[component]:(et->pict_height[component]-(j*et->ctu_height[component]));

        // 把源数据复制到当前宏宽窗口
		mem_transfer_2d2d(src, dst, width, height, src_stride, dst_stride);
	}
}

// 用于帧内参考
// 把数据从解码宏块窗口中复制到当前引用的参考帧上,以用于帧内预测
void mem_transfer_intra_refs(henc_thread_t* et, ctu_info_t* ctu)
{
	int l;

    // 源窗口:参考帧
	wnd_t *decoded_src_wnd = &et->enc_engine->curr_reference_frame->img;

    // 目标窗口:解码宏块窗口
	wnd_t *decoded_dst_wnd = et->decoded_mbs_wnd[0];

	int component = Y_COMP;

    // 长度
	int src_stride = et->pict_width[component];
	int dst_stride;

    // 源解码缓存
	int16_t *decoded_buff_src;

    // 目标解码缓存
	int16_t * decoded_buff_dst;

    // ctu的尺寸
	int cu_size = ctu->size;
	int left_copy = 0, top_copy = 0;


    // 如果当前CTU的左边和上边都不存在,那么直接返回
	if(!ctu->ctu_left && !ctu->ctu_top)
		return;

    // 对于每一个解码窗口(NUM_DECODED_WNDS == 7)
	for(l=0;l<NUM_DECODED_WNDS;l++)
	{
        // 对于该解码窗口中的每一个分量
		for(component=Y_COMP;component<=V_COMP;component++)
		{
			int i, j;

            // 目标窗口就是解码的宏块窗口
			decoded_dst_wnd = et->decoded_mbs_wnd[l];

            // 长度
			src_stride = WND_STRIDE_2D(*decoded_src_wnd, component);
			dst_stride = WND_STRIDE_2D(*decoded_dst_wnd, component);

			decoded_buff_src = WND_POSITION_2D(int16_t *, *decoded_src_wnd, component, ctu->x[component], ctu->y[component], 0, et->ctu_width);
			decoded_buff_dst = WND_POSITION_2D(int16_t *, *decoded_dst_wnd, component, 0, 0, 0, et->ctu_width);

			cu_size = et->ctu_width[component];

            // 调整复制的长度
			left_copy = top_copy = 0;

			if(ctu->ctu_left)
				left_copy += cu_size;

			if(ctu->ctu_left_bottom)
				left_copy += cu_size;

			if(ctu->ctu_top)
				top_copy += cu_size;

			if(ctu->ctu_top_right)
				top_copy += cu_size;


			if(left_copy>(et->pict_height[component]-ctu->y[component]))
				left_copy=(et->pict_height[component]-ctu->y[component]);

			if(top_copy>(et->pict_width[component]-ctu->x[component]))
				top_copy=(et->pict_width[component]-ctu->x[component]);

			decoded_buff_src-=(src_stride+1);
			decoded_buff_dst-=(dst_stride+1);
	
			//top-left square
			if(ctu->ctu_left && ctu->ctu_top)
			{
				*decoded_buff_dst = *decoded_buff_src;
			}

			decoded_buff_src++;
			decoded_buff_dst++;


			//bottom line
            // 复制底部的一行
			for(i=0;i<top_copy;i++)
				decoded_buff_dst[i] = decoded_buff_src[i];
			//memcpy(decoded_buff_dst, decoded_buff_src, top_copy*sizeof(decoded_buff_src[0]));

            // right column
            // 复制右边的一列
			decoded_buff_src+=src_stride-1;
			decoded_buff_dst+=dst_stride-1;
			for(j=0;j<left_copy;j++)
			{
				decoded_buff_dst[j*dst_stride] = decoded_buff_src[j*src_stride];
			}
		}
	}
}


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