HEVC代码学习6:filterHor和filterVer函数
来源:互联网 发布:js正则匹配指定字符串 编辑:程序博客网 时间:2024/06/05 17:31
帧间预测分为运动估计ME和运动补偿MV,其中用到了MV的亚像素搜索,需要使用filterHor和filterVer进行插值。
这里使用的是HM16,在之前版本中分为filterHorLuma、filterHorChroma和filterHorLuma、filterVerChroma。HM16中已经将亮度和色度插值滤波器整合。
我们来从最底层插值滤波器函数filter看起。filter函数代码如下,对同一亚像素位置(如1/4处)处进行插值,插值后的MV存在dst中。
/** 插值滤波器 * \brief Apply FIR filter to a block of samples * * \tparam N Number of taps 抽头数 * \tparam isVertical Flag indicating filtering along vertical direction * \tparam isFirst Flag indicating whether it is the first filtering operation * \tparam isLast Flag indicating whether it is the last filtering operation * \param bitDepth Bit depth of samples * \param src Pointer to source samples 源MV地址 * \param srcStride Stride of source samples * \param dst Pointer to destination samples 插值后的MV地址 * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param coeff Pointer to filter taps 抽头系数 */template<Int N, Bool isVertical, Bool isFirst, Bool isLast>Void TComInterpolationFilter::filter(Int bitDepth, Pel const *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, TFilterCoeff const *coeff){ Int row, col; Pel c[8]; //系数数组 c[0] = coeff[0]; //抽头0系数 c[1] = coeff[1]; //抽头1系数 if ( N >= 4 ) //N≥4时,取抽头2和3系数(UV分量) { c[2] = coeff[2]; c[3] = coeff[3]; } if ( N >= 6 ) //N≥6时,取抽头4和5系数 { c[4] = coeff[4]; c[5] = coeff[5]; } if ( N == 8 ) //N=8时,取抽头6和7系数(Y分量) { c[6] = coeff[6]; c[7] = coeff[7]; } Int cStride = ( isVertical ) ? srcStride : 1; //垂直情况下步长为srcStride,水平情况下为1 src -= ( N/2 - 1 ) * cStride; //找到前面N/2-1个整数点 Int offset; Pel maxVal; Int headRoom = std::max<Int>(2, (IF_INTERNAL_PREC - bitDepth)); Int shift = IF_FILTER_PREC; // with the current settings (IF_INTERNAL_PREC = 14 and IF_FILTER_PREC = 6), though headroom can be // negative for bit depths greater than 14, shift will remain non-negative for bit depths of 8->20 assert(shift >= 0); if ( isLast ) { shift += (isFirst) ? 0 : headRoom; offset = 1 << (shift - 1); offset += (isFirst) ? 0 : IF_INTERNAL_OFFS << IF_FILTER_PREC; maxVal = (1 << bitDepth) - 1; } else { shift -= (isFirst) ? headRoom : 0; offset = (isFirst) ? -IF_INTERNAL_OFFS << shift : 0; maxVal = 0; } for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { Int sum; //从N/2-1个整数点开始,取N个整数点乘对应的抽头系数求和。 sum = src[ col + 0 * cStride] * c[0]; sum += src[ col + 1 * cStride] * c[1]; if ( N >= 4 ) { sum += src[ col + 2 * cStride] * c[2]; sum += src[ col + 3 * cStride] * c[3]; } if ( N >= 6 ) { sum += src[ col + 4 * cStride] * c[4]; sum += src[ col + 5 * cStride] * c[5]; } if ( N == 8 ) { sum += src[ col + 6 * cStride] * c[6]; sum += src[ col + 7 * cStride] * c[7]; } Pel val = ( sum + offset ) >> shift; if ( isLast ) { val = ( val < 0 ) ? 0 : val; //保证不小于0 val = ( val > maxVal ) ? maxVal : val; //保证不越界 } dst[col] = val; //存储插值后的MV } src += srcStride; dst += dstStride; }}
再来看上一层的函数,函数代码如下。是一个分类处理,分为普通操作、第一次操作和最后一次操作,分别传入不同参数调用底层filter函数进行插值。这里直接通过N来区分是亮度插值和色度插值。
/** * \brief Filter a block of samples (horizontal) * * \tparam N Number of taps 抽头数:Y-8,UV-4 * \param bitDepth Bit depth of samples * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param isLast Flag indicating whether it is the last filtering operation * \param coeff Pointer to filter taps 抽头系数 */template<Int N> //插值Void TComInterpolationFilter::filterHor(Int bitDepth, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isLast, TFilterCoeff const *coeff){ if ( isLast ) { filter<N, false, true, true>(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else { filter<N, false, true, false>(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); }}template<Int N>Void TComInterpolationFilter::filterVer(Int bitDepth, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Bool isFirst, Bool isLast, TFilterCoeff const *coeff){ if ( isFirst && isLast ) { filter<N, true, true, true>(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else if ( isFirst && !isLast ) { filter<N, true, true, false>(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else if ( !isFirst && isLast ) { filter<N, true, false, true>(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); } else { filter<N, true, false, false>(bitDepth, src, srcStride, dst, dstStride, width, height, coeff); }}
最后来看最上层的filterHor和filterVer,代码如下,也是一个分类处理,调用下层函数处理。分了三种情况:frac = 0、亮度和色度。frac = 0,即整数,不需要插值。
/** * \brief Filter a block of Luma/Chroma samples (horizontal) * * \param compID Chroma component ID * \param src Pointer to source samples * \param srcStride Stride of source samples * \param dst Pointer to destination samples * \param dstStride Stride of destination samples * \param width Width of block * \param height Height of block * \param frac Fractional sample offset 分数偏移 * \param isLast Flag indicating whether it is the last filtering operation * \param fmt Chroma format * \param bitDepth Bit depth */Void TComInterpolationFilter::filterHor(const ComponentID compID, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Int frac, Bool isLast, const ChromaFormat fmt, const Int bitDepth ){ if ( frac == 0 ) //整数直接复制 { filterCopy(bitDepth, src, srcStride, dst, dstStride, width, height, true, isLast ); } else if (isLuma(compID)) //Y分量小数插值 { assert(frac >= 0 && frac < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterHor<NTAPS_LUMA>(bitDepth, src, srcStride, dst, dstStride, width, height, isLast, m_lumaFilter[frac]); } else { const UInt csx = getComponentScaleX(compID, fmt); assert(frac >=0 && csx<2 && (frac<<(1-csx)) < CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterHor<NTAPS_CHROMA>(bitDepth, src, srcStride, dst, dstStride, width, height, isLast, m_chromaFilter[frac<<(1-csx)]); }}Void TComInterpolationFilter::filterVer(const ComponentID compID, Pel *src, Int srcStride, Pel *dst, Int dstStride, Int width, Int height, Int frac, Bool isFirst, Bool isLast, const ChromaFormat fmt, const Int bitDepth ){ if ( frac == 0 ) { filterCopy(bitDepth, src, srcStride, dst, dstStride, width, height, isFirst, isLast ); } else if (isLuma(compID)) { assert(frac >= 0 && frac < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterVer<NTAPS_LUMA>(bitDepth, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_lumaFilter[frac]); } else { const UInt csy = getComponentScaleY(compID, fmt); assert(frac >=0 && csy<2 && (frac<<(1-csy)) < CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS); filterVer<NTAPS_CHROMA>(bitDepth, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_chromaFilter[frac<<(1-csy)]); }}
0 0
- HEVC代码学习6:filterHor和filterVer函数
- HEVC代码学习2:TAppEncTop::encode函数
- HEVC代码学习3:TEncTop::encode函数
- HEVC代码学习7:xPatternSearchFracDIF函数
- HEVC代码学习8:xMotionEstimation函数
- HEVC代码学习9:getInterMergeCandidates函数
- HEVC代码学习11:xCompressCU函数
- HEVC代码学习12:xCheckRDCostInter函数
- HEVC代码学习13:predInterSearch函数
- HEVC代码学习14:motionCompensation函数
- HEVC代码学习15:AMVP相关函数
- HEVC代码学习20:xPatternSearchFast函数
- HEVC代码学习21:xTZSearch函数
- HEVC代码学习22:xTZSearchHelp函数
- HEVC代码学习23:xTZ8PointDiamondSearch函数
- HEVC代码学习24:encodeResAndCalcRdInterCU函数
- HEVC代码学习25:xDecompressCU函数
- HEVC代码学习27:calcRdCost函数
- android-architecture学习——todo‑mvp
- Mysql跨表更新 多表update sql语句总结
- construct2在ios下播放声音
- Java版本历史和特性介绍
- javascript能干什么?
- HEVC代码学习6:filterHor和filterVer函数
- 【Arquillian】Incorrect Summary
- 关于Android LCD和键盘背光亮度
- Bitmap、Matrix使用
- 批量删除QQ空间说说
- 数据结构学习笔记--栈结构
- 作为一个新手的Oracle(DBA)学习笔记
- 微信公众号开发之对接微信公众平台
- Ubuntu下"sshd:unrecognized service"