帧内预测——initAdiPattern
来源:互联网 发布:蜗杆数控车床编程事例 编辑:程序博客网 时间:2024/05/16 09:04
近期开始接触HEVC,看了一些综述性的文章后开始看平台,可总感觉效果不佳,所以打算把每天看的东西都写一下,巩固巩固。首先是讲一下initAdiPattern这个函数,在看了hevc_cjl的博客: http://blog.csdn.net/hevc_cjl/article/details/8184276?reload 之后,受益良多。
首先分析下这个函数的用途:这个函数位于帧内预测的亮度预测estIntraPredQT中,主要是用于初始化帧内模式。
细化其功能:(1)检测当前的PU相邻点的可用性(2)参考样点的替换 (3)参考样点的平滑滤波
通过下面这幅图能很好地理解代码的信息。如:
// ----- 先进行样点值拷贝 Int l = 0; // left border from bottom to top【左下->左上,滤波前参考样点值拷贝】 for (i = 0; i < uiCuHeight2; i++) { piFilterBuf[l++] = piAdiTemp[uiWidth * (uiCuHeight2 - i)]; } // top left corner piFilterBuf[l++] = piAdiTemp[0]; //【左上角点, 拷贝】 // above border from left to right for (i=0; i < uiCuWidth2; i++) // 【上->右上, 拷贝】 { piFilterBuf[l++] = piAdiTemp[1 + i]; //l此时初始为uiCuHeight2+1 }
以上代码为样本点信息拷贝过程,拷贝的过程是自左下而上,过AboveLeft而向右的过程Void TComPattern::initAdiPattern( TComDataCU* pcCU, UInt uiZorderIdxInPart, UInt uiPartDepth, Int* piAdiBuf, Int iOrgBufStride, Int iOrgBufHeight, Bool& bAbove, Bool& bLeft, Bool bLMmode ) { Pel* piRoiOrigin;//piRoiOrgin指向重建Yuv图像对应于当前PU所在位置的首地址 Int* piAdiTemp; // UInt uiCuWidth = pcCU->getWidth(0) >> uiPartDepth; //CU宽 UInt uiCuHeight = pcCU->getHeight(0)>> uiPartDepth; //CU高 UInt uiCuWidth2 = uiCuWidth<<1;// uiCuWidth*2 UInt uiCuHeight2 = uiCuHeight<<1; UInt uiWidth; UInt uiHeight; Int iPicStride = pcCU->getPic()->getStride(); //图像跨度(原图像宽度 + 两边扩充的参考像素点) Int iUnitSize = 0; Int iNumUnitsInCu = 0; Int iTotalUnits = 0; Bool bNeighborFlags[4 * MAX_NUM_SPU_W + 1]; //!< 用于存放4个方向上的相邻样点值的【可用性】,4*32+1 Int iNumIntraNeighbor = 0; ////!< 给可用邻块进行计数 UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB; ////! 获取当前PU左上角LT,右上角RT以及左下角LB 以4x4块为单位的Z-order(Zscan) pcCU->deriveLeftRightTopIdxAdi( uiPartIdxLT, uiPartIdxRT, uiZorderIdxInPart, uiPartDepth ); pcCU->deriveLeftBottomIdxAdi ( uiPartIdxLB, uiZorderIdxInPart, uiPartDepth ); iUnitSize = g_uiMaxCUWidth >> g_uiMaxCUDepth; // 4 iNumUnitsInCu = uiCuWidth / iUnitSize; // 当前CU的宽/4 = 宽方向上,iUnitSize的个数 iTotalUnits = (iNumUnitsInCu << 2) + 1; //(iNumUnitsInCu*4) + 1 // (扫描顺序是从左下到左上,再从左上到右上) bNeighborFlags[iNumUnitsInCu*2] = isAboveLeftAvailable( pcCU, uiPartIdxLT ); iNumIntraNeighbor += (Int)(bNeighborFlags[iNumUnitsInCu*2]); iNumIntraNeighbor += isAboveAvailable ( pcCU, uiPartIdxLT, uiPartIdxRT, bNeighborFlags+(iNumUnitsInCu*2)+1 ); iNumIntraNeighbor += isAboveRightAvailable( pcCU, uiPartIdxLT, uiPartIdxRT, bNeighborFlags+(iNumUnitsInCu*3)+1 ); iNumIntraNeighbor += isLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, bNeighborFlags+(iNumUnitsInCu*2)-1 ); iNumIntraNeighbor += isBelowLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, bNeighborFlags+ iNumUnitsInCu -1 ); bAbove = true; //之前定义为FALSE bLeft = true; //同上 uiWidth=uiCuWidth2+1; uiHeight=uiCuHeight2+1; if (((uiWidth<<2)>iOrgBufStride)||((uiHeight<<2)>iOrgBufHeight)) //判定范围 { return; } //! piRoiOrigin指向当前PU左上角 piRoiOrigin = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), pcCU->getZorderIdxInCU()+uiZorderIdxInPart ); piAdiTemp = piAdiBuf; // 参考样点的替换(填补)过程 fillReferenceSamples (g_bitDepthY, piRoiOrigin, piAdiTemp, bNeighborFlags, iNumIntraNeighbor, iUnitSize, iNumUnitsInCu, iTotalUnits, uiCuWidth, uiCuHeight, uiWidth, uiHeight, iPicStride, bLMmode);
// **************************************************** //! 下面所进行的工作主要是对参考样点进行3抽头的滤波。 // piAdiBuf指向滤波前的参考样点的首地址,在滤波前,先将所有参考样点拷贝到piFilterBuf指向的区域, //! 经滤波后的样点值保存在piFilterBufN指向的区域,最终将滤波后的样点值拷贝到piFilterBuf1。 // 值得一提的是,最终的结果是,piAdiBuf指向的区域是未经滤波的样点值,而piFilterBuf1指向的区域是经过 //! 滤波的样点值,两者的地址相差uiWH = uiWidth * uiHeight = (uiCuWidth2 + 1) * (uiCuHeight2 + 1),这就解释了在进行 //! 真正的帧内预测时,在需要滤波时,指向piAdiBuf的指针需要加上uiWH的偏移量。 Int i; // generate filtered intra prediction samples Int iBufSize = uiCuHeight2 + uiCuWidth2 + 1; //结合图中信息比较 UInt uiWH = uiWidth * uiHeight; // number of elements in one buffer Int* piFilteredBuf1 = piAdiBuf + uiWH; // 1. filter buffer Int* piFilteredBuf2 = piFilteredBuf1 + uiWH; // 2. filter buffer Int* piFilterBuf = piFilteredBuf2 + uiWH; // buffer for 2. filtering (sequential) //piFilterBufN 存放的是参考样点经3抽头滤波后的值 Int* piFilterBufN = piFilterBuf + iBufSize; // buffer for 1. filtering (sequential) // ----- 先进行样点值拷贝 Int l = 0; // left border from bottom to top【左下->左上,滤波前参考样点值拷贝】 for (i = 0; i < uiCuHeight2; i++) { piFilterBuf[l++] = piAdiTemp[uiWidth * (uiCuHeight2 - i)]; } // top left corner piFilterBuf[l++] = piAdiTemp[0]; //【左上角点, 拷贝】 // above border from left to right for (i=0; i < uiCuWidth2; i++) // 【上->右上, 拷贝】 { piFilterBuf[l++] = piAdiTemp[1 + i]; } //对32*32的块进行 StrongIntraSmoothing if (pcCU->getSlice()->getSPS()->getUseStrongIntraSmoothing()) //cfg里面设置 { Int blkSize = 32; Int bottomLeft = piFilterBuf[0]; Int topLeft = piFilterBuf[uiCuHeight2]; Int topRight = piFilterBuf[iBufSize-1]; Int threshold = 1 << (g_bitDepthY - 5);//8 Bool bilinearLeft = abs(bottomLeft+topLeft-2*piFilterBuf[uiCuHeight]) < threshold; Bool bilinearAbove = abs(topLeft+topRight-2*piFilterBuf[uiCuHeight2+uiCuHeight]) < threshold; if (uiCuWidth>=blkSize && (bilinearLeft && bilinearAbove)) { Int shift = g_aucConvertToBit[uiCuWidth] + 3; // log2(uiCuHeight2) =7 piFilterBufN[0] = piFilterBuf[0]; piFilterBufN[uiCuHeight2] = piFilterBuf[uiCuHeight2]; piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1]; for (i = 1; i < uiCuHeight2; i++) { piFilterBufN[i] = ((uiCuHeight2-i)*bottomLeft + i*topLeft + uiCuHeight) >> shift; } for (i = 1; i < uiCuWidth2; i++) { piFilterBufN[uiCuHeight2 + i] = ((uiCuWidth2-i)*topLeft + i*topRight + uiCuWidth) >> shift; } } else { // 1. filtering with [1 2 1] piFilterBufN[0] = piFilterBuf[0]; piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1]; for (i = 1; i < iBufSize - 1; i++) { piFilterBufN[i] = (piFilterBuf[i - 1] + 2 * piFilterBuf[i]+piFilterBuf[i + 1] + 2) >> 2; // 最后 +2是为了四舍五入取整 } } } else { // 1. filtering with [1 2 1] piFilterBufN[0] = piFilterBuf[0]; piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1]; for (i = 1; i < iBufSize - 1; i++) { piFilterBufN[i] = (piFilterBuf[i - 1] + 2 * piFilterBuf[i]+piFilterBuf[i + 1] + 2) >> 2; } } // fill 1. filter buffer with filtered values l=0; for (i = 0; i < uiCuHeight2; i++) { piFilteredBuf1[uiWidth * (uiCuHeight2 - i)] = piFilterBufN[l++]; } piFilteredBuf1[0] = piFilterBufN[l++]; for (i = 0; i < uiCuWidth2; i++) { piFilteredBuf1[1 + i] = piFilterBufN[l++]; } }
- 帧内预测——initAdiPattern
- 帧内预测-函数initAdiPattern
- HEVC-帧内预测2: initAdiPattern 函数
- 帧内预测——fillReferenceSamples
- HM编码器代码阅读(38)——帧内预测(五)帧内预测之正式的预测操作
- 帧内预测模式预测
- H.264笔记之三——帧内预测
- homerHEVC代码阅读(41)——帧内预测
- 详细解析H.264——帧内预测
- HM编码器代码阅读(35)——帧内预测(二)帧内预测总流程
- HM编码器代码阅读(39)——帧内预测(六)帧内预测之色度色度的操作
- 帧内预测编码
- 帧内预测
- 帧内预测
- HEVC帧内预测
- hevc帧内预测
- x264帧内预测
- 帧内预测与帧间预测
- C++白盒测试最佳实践课程,3个免费名额火热申请中,31号前截止申请...
- Android实战技巧:深入解析AsyncTask与thread的区别 THREAD_POOL_EXECUTOR
- CentOS 6.3 发布 附ISO下载地址
- 问题定位:内存泄漏,踩内存。
- CSDN的博客积分计算规则及博客排名规则
- 帧内预测——initAdiPattern
- SQL查询操作
- Citrix 服务器虚拟化之八 Xenserver虚拟机模版
- 感悟--黄小琥的二十年的坚持
- hdu 1241 Oil Deposits (dfs)
- 单例模式
- maven-war-plugin
- SOJ 4299: component
- hdu 1856