HM模型学习(三)
来源:互联网 发布:网络女作家富豪行榜 编辑:程序博客网 时间:2024/06/11 00:09
原文出处:http://blog.csdn.net/hevc_cjl/article/details/8184276
今天主要介绍帧内预测一个很重要的函数initAdiPattern,它的主要功能有三个,(1)检测当前PU的相邻样点包括左上、上、右上、左、左下邻域样点值的可用性,或者说检查这些点是否存在;(2)参考样点的替换过程,主要实现的是JCTVC-J1003即draft 8.4.4.2.2的内容,主要由函数fillReferenceSamples来完成,这个在之前的文章已经讨论过了;(3)相邻样点即参考样点的平滑滤波,主要实现draft 8.4.4.2.3的内容。话不多说,下面给出initAdiPattern的实现和我个人的一些注释,供大家参考。
在HM16.9中,该部分函数被拆分成两个函数对应于工程中的:
其中主要是最下面的函数,上面的函数作用是给出是否滤波的布尔值,然后该值作为参数传入下面的函数中。
对应的HM16.9的解释如下,有些地方不能很好地理解。9.0可参考原文出处。
Void TComPrediction::initIntraPatternChType( TComTU &rTu, const ComponentID compID, const Bool bFilterRefSamples DEBUG_STRING_FN_DECLARE(sDebug)){ const ChannelType chType = toChannelType(compID); TComDataCU *pcCU=rTu.getCU(); const TComSPS &sps = *(pcCU->getSlice()->getSPS()); const UInt uiZorderIdxInPart=rTu.GetAbsPartIdxTU(); const UInt uiTuWidth = rTu.getRect(compID).width;//!< CU的宽度 const UInt uiTuHeight = rTu.getRect(compID).height;//!< CU的高度 const UInt uiTuWidth2 = uiTuWidth << 1; const UInt uiTuHeight2 = uiTuHeight << 1; const Int iBaseUnitSize = sps.getMaxCUWidth() >> sps.getMaxTotalCUDepth(); const Int iUnitWidth = iBaseUnitSize >> pcCU->getPic()->getPicYuvRec()->getComponentScaleX(compID); const Int iUnitHeight = iBaseUnitSize >> pcCU->getPic()->getPicYuvRec()->getComponentScaleY(compID); const Int iTUWidthInUnits = uiTuWidth / iUnitWidth; const Int iTUHeightInUnits = uiTuHeight / iUnitHeight; const Int iAboveUnits = iTUWidthInUnits << 1;//上方相邻unit个数 const Int iLeftUnits = iTUHeightInUnits << 1;//左方相邻unit个数 const Int bitDepthForChannel = sps.getBitDepth(chType); assert(iTUHeightInUnits > 0 && iTUWidthInUnits > 0); //! 获取当前PU左上角LT,右上角RT以及左下角LB 以4x4块为单位的Zorder const Int iPartIdxStride = pcCU->getPic()->getNumPartInCtuWidth(); const UInt uiPartIdxLT = pcCU->getZorderIdxInCtu() + uiZorderIdxInPart; const UInt uiPartIdxRT = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] + iTUWidthInUnits - 1 ]; const UInt uiPartIdxLB = g_auiRasterToZscan[ g_auiZscanToRaster[ uiPartIdxLT ] + ((iTUHeightInUnits - 1) * iPartIdxStride)]; Int iPicStride = pcCU->getPic()->getStride(compID); Bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; //!< 用于存放4个方向上的相邻样点值的可用性, 4 x 32 + 1 Int iNumIntraNeighbor = 0; //!< 给可用邻块进行计数 //! 扫描顺序是从左下到左上,再从左上到右上 bNeighborFlags[iLeftUnits] = isAboveLeftAvailable( pcCU, uiPartIdxLT );//为每个邻块的可用性进行 iNumIntraNeighbor += bNeighborFlags[iLeftUnits] ? 1 : 0;//邻块可用则+1计数 iNumIntraNeighbor += isAboveAvailable ( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1) ); iNumIntraNeighbor += isAboveRightAvailable( pcCU, uiPartIdxLT, uiPartIdxRT, (bNeighborFlags + iLeftUnits + 1 + iTUWidthInUnits ) ); iNumIntraNeighbor += isLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1) ); iNumIntraNeighbor += isBelowLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, (bNeighborFlags + iLeftUnits - 1 - iTUHeightInUnits) ); const UInt uiROIWidth = uiTuWidth2+1; const UInt uiROIHeight = uiTuHeight2+1; // number of elements in one buffer assert(uiROIWidth*uiROIHeight <= m_iYuvExtSize);//assert作用是如果它的条件返回错误,则终止程序执行#if DEBUG_STRING std::stringstream ss(stringstream::out);#endif { Pel *piIntraTemp = m_piYuvExt[compID][PRED_BUF_UNFILTERED]; Pel *piRoiOrigin = pcCU->getPic()->getPicYuvRec()->getAddr(compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu()+uiZorderIdxInPart); //! piRoiOrigin指向当前PU左上角 #if O0043_BEST_EFFORT_DECODING const Int bitDepthForChannelInStream = sps.getStreamBitDepth(chType); fillReferenceSamples (bitDepthForChannelInStream, bitDepthForChannelInStream - bitDepthForChannel,#else fillReferenceSamples (bitDepthForChannel,#endif piRoiOrigin, piIntraTemp, bNeighborFlags, iNumIntraNeighbor, iUnitWidth, iUnitHeight, iAboveUnits, iLeftUnits, uiROIWidth, uiROIHeight, iPicStride);//填充参考样点#if DEBUG_STRING if (DebugOptionList::DebugString_Pred.getInt()&DebugStringGetPredModeMask(MODE_INTRA)) { ss << "###: generating Ref Samples for channel " << compID << " and " << rTu.getRect(compID).width << " x " << rTu.getRect(compID).height << "\n"; for (UInt y=0; y<uiROIHeight; y++) { ss << "###: - "; for (UInt x=0; x<uiROIWidth; x++) { if (x==0 || y==0) { ss << piIntraTemp[y*uiROIWidth + x] << ", ";// if (x%16==15) ss << "\nPart size: ~ "; } } ss << "\n"; } }#endif if (bFilterRefSamples)//需要进行滤波处理 { // generate filtered intra prediction samples Int stride = uiROIWidth; const Pel *piSrcPtr = piIntraTemp + (stride * uiTuHeight2); // bottom left Pel *piDestPtr = m_piYuvExt[compID][PRED_BUF_FILTERED] + (stride * uiTuHeight2); // bottom left //------------------------------------------------ Bool useStrongIntraSmoothing = isLuma(chType) && sps.getUseStrongIntraSmoothing(); const Pel bottomLeft = piIntraTemp[stride * uiTuHeight2]; const Pel topLeft = piIntraTemp[0]; const Pel topRight = piIntraTemp[uiTuWidth2];//左下/左侧、左上、上侧/右上的 filter buffer if (useStrongIntraSmoothing) {#if O0043_BEST_EFFORT_DECODING const Int threshold = 1 << (bitDepthForChannelInStream - 5);#else const Int threshold = 1 << (bitDepthForChannel - 5);//强滤波阈值#endif const Bool bilinearLeft = abs((bottomLeft + topLeft ) - (2 * piIntraTemp[stride * uiTuHeight])) < threshold; //difference between the const Bool bilinearAbove = abs((topLeft + topRight) - (2 * piIntraTemp[ uiTuWidth ])) < threshold; //ends and the middle解释看参考书CA CE方向进行滤波 if ((uiTuWidth < 32) || (!bilinearLeft) || (!bilinearAbove))//只针对32*32,并且满足上述两个条件才需要进行强滤波 { useStrongIntraSmoothing = false; } } //顺序执行,从左下到右上进行滤波,需要对每个点判断是否需要进行强滤波,且第一个点即左下和最后一个点右上不需要进行滤波 *piDestPtr = *piSrcPtr; // bottom left is not filtered piDestPtr -= stride; piSrcPtr -= stride; //------------------------------------------------ //left column (bottom to top) if (useStrongIntraSmoothing) { const Int shift = g_aucConvertToBit[uiTuHeight] + 3; //log2(uiTuHeight2) for(UInt i=1; i<uiTuHeight2; i++, piDestPtr-=stride) { *piDestPtr = (((uiTuHeight2 - i) * bottomLeft) + (i * topLeft) + uiTuHeight) >> shift; } piSrcPtr -= stride * (uiTuHeight2 - 1); } else { for(UInt i=1; i<uiTuHeight2; i++, piDestPtr-=stride, piSrcPtr-=stride) { *piDestPtr = ( piSrcPtr[stride] + 2*piSrcPtr[0] + piSrcPtr[-stride] + 2 ) >> 2;//!< 对中间样点值进行3抽头[1 2 1] / 4 的平滑滤波 } } //------------------------------------------------ //top-left if (useStrongIntraSmoothing) { *piDestPtr = piSrcPtr[0]; } else { *piDestPtr = ( piSrcPtr[stride] + 2*piSrcPtr[0] + piSrcPtr[1] + 2 ) >> 2; } piDestPtr += 1; piSrcPtr += 1; //------------------------------------------------ //top row (left-to-right) if (useStrongIntraSmoothing) { const Int shift = g_aucConvertToBit[uiTuWidth] + 3; //log2(uiTuWidth2) for(UInt i=1; i<uiTuWidth2; i++, piDestPtr++) { *piDestPtr = (((uiTuWidth2 - i) * topLeft) + (i * topRight) + uiTuWidth) >> shift; } piSrcPtr += uiTuWidth2 - 1; } else { for(UInt i=1; i<uiTuWidth2; i++, piDestPtr++, piSrcPtr++) { *piDestPtr = ( piSrcPtr[1] + 2*piSrcPtr[0] + piSrcPtr[-1] + 2 ) >> 2; } } //------------------------------------------------ *piDestPtr=*piSrcPtr; // far right is not filtered
最后附上图,以帮助大家更好地理解代码,我就不对图多作解释了,相信大家对着代码能比较容易看明白的。
(注,上图中,uiWidth和uiHeight实际上对应的是代码中的uiCUWidth和uiCUHeight,因画图的时候发生了遗漏,特此说明)
阅读全文
0 0
- HM模型学习(三)
- HM模型学习(一)
- HM模型学习(二)
- HEVC学习(一)HM模型代码下载,HEVC协议下载,HM模型运行
- HEVC解码器HM源码阅读(三)读取一个NALU
- HM学习二
- HM学习一
- HEVC学习(一) —— HM的使用
- HEVC学习(一) —— HM的使用
- HEVC学习(一) —— HM的使用
- HEVC学习(一) —— HM的使用
- HEVC学习(一) —— HM的使用
- HEVC学习(一) —— HM的使用
- HEVC学习(一)—— HM的使用
- HEVC学习(一) —— HM的使用
- HEVC学习(一) —— HM的使用
- HEVC学习(一) —— HM的使用
- 隐马尔科夫模型HMM学习(三)
- Log4J日志详解配置
- 一不小心把win10的秘钥卸载了解决方法
- 键盘老是隐藏, 搜索框与RecylerView的时候 数据一刷新 键盘就隐藏
- selected选中后显示和隐藏div
- instanceof
- HM模型学习(三)
- Access denied for user 'user'@'localhost' (using password: YES)
- react 小记
- 继承与多态的区别
- 六大设计原则(概念)
- E
- Radar Installation(贪心。 区间选点)
- js中的一些方法总结
- eclipse 安装 python 开发插件 pydev