亚像素2之1/2插值过程 xExtDIFUpSamplingH

本文深入剖析亚像素插值中的1/2精度过程,重点讲解xExtDIFUpSamplingH函数。首先,函数进行水平整像素复制,接着调用filterHor进行水平插值,包括frac=0的特殊处理。然后,进行垂直方向的整像素和1/2像素插值,最终得到完整插值结果。
摘要由CSDN通过智能技术生成

通过前面一篇亚像素入口和过程的博客,分析了亚像素的入口和过程,这篇文章分析1/2插值的过程:

xExtDIFUpSamplingH 这个函数是进行1/2精度插值,首先对参考图像进行水平插值,整像素位置直接复制给了m_filteredBlockTmp[0],调用了filterHor这个函数进行水平插值

调用了m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0].getAddr(COMPONENT_Y), intStride, width + 1, height + filterSize, 0, false, chFmt, pattern->getBitDepthY());进行水平整像素复制给m_filteredBlockTmp[0]
filterHor这个函数分了三种情况:frac = 0、亮度和色度。frac = 0,即整数,不需要插值。,在进行整像素复制的时候有调用了filterCopy这个函数,

调用了filterCopy(bitDepth, src, srcStride, dst, dstStride, width, height, true, isLast );先看isFirst == true为第一次插值:Pel val = leftShift_round(src[col], shift);dst[col] = val - (Pel)IF_INTERNAL_OFFS;

再调用m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2].getAddr(COMPONENT_Y), intStride, width + 1, height + filterSize, 2, false, chFmt, pattern->getBitDepthY());进行1/2像素水平插值赋值给m_filteredBlockTmp[2]

水平整像素插值后的Y做垂直方向整像素插值,结果存储在m_filteredBlock[0][0]中,                                                              dstPtr = m_filteredBlock[0][0].getAddr(COMPONENT_Y);
m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0, false, true, chFmt, pattern->getBitDepthY());

水平1/2像素插值后的Y做垂直方向1/2像素插值,结果存储在m_filteredBlock[2][0]中
    intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + (halfFilterSize - 1) * intStride + 1;
    dstPtr = m_filteredBlock[2][0].getAddr(COMPONENT_Y);
    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 1, 2, false, true, chFmt, pattern->getBitDepthY());
    

/**
 * \brief Generate half-sample interpolated block
 *
 * \param pattern Reference picture ROI
 * \param biPred    Flag indicating whether block is for biprediction
 */
//产生1/2精度的插值像素块
Void TEncSearch::xExtDIFUpSamplingH(TComPattern* pattern)
{
	Int width = pattern->getROIYWidth();
	Int height = pattern->getROIYHeight();
	Int srcStride = pattern->getPatternLStride();
	//m_filteredBlockTmp[]是个临时的中间量。实际用于存储水平插值得到的各像素位置的YUV信息。[]中的数字指示水平插值的像素位置。
	//m_filteredBlock[][]在做完水平插值之后,会进行垂直插值,得到最终的数据,存储与m_filteredBlock[][]中。第一个[]中的数字指示垂直插值位置,第二个指示水平插值位置。 
	Int intStride = m_filteredBlockTmp[0].getStride(COMPONENT_Y);
	Int dstStride = m_filteredBlock[0][0].getStride(COMPONENT_Y);
	Pel *intPtr; 
	Pel *dstPtr;   //插值后的MV地址
	Int filterSize = NTAPS_LUMA;//8抽头
	Int halfFilterSize = (filterSize >> 1);//4
	Pel *srcPtr = pattern->getROIY() - halfFilterSize * srcStride - 1; //源MV地址

	const ChromaFormat chFmt = m_filteredBlock[0][0].getChromaFormat();

	//对参考图像进行水平插值,整像素位置直接复制给了m_filteredBlockTmp[0],1/2像素位置插值后给了m_filteredBlockTmp[2]。 
	m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0].getAddr(COMPONENT_Y), intStride, width + 1, height + filterSize, 0, false, chFmt, pattern->getBitDepthY());
	m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2].getAddr(COMPONENT_Y), intStride, width + 1, height + filterSize, 2, false, chFmt, pattern->getBitDepthY());

	水平整像素插值后的Y做垂直方向整像素插值,结果存储在m_filteredBlock[0][0]中
	intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + halfFilterSize * intStride + 1;
	dstPtr = m_filteredBlock[0][0].getAddr(COMPONENT_Y);
	m_if.filterVer(COMPONENT_Y, intP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值