H.265之三 -帧内预测(3)
来源:互联网 发布:yum命令搜索 编辑:程序博客网 时间:2024/04/29 15:52
今天主要介绍帧内预测一个很重要的函数initAdiPattern,它的主要功能有三个,(1)检测当前PU的相邻样点包括左上、上、右上、左、左下邻域样点值的可用性,或者说检查这些点是否存在;(2)参考样点的替换过程,主要实现的是JCTVC-J1003即draft 8.4.4.2.2的内容,主要由函数fillReferenceSamples来完成,这个在之前的文章已经讨论过了;(3)相邻样点即参考样点的平滑滤波,主要实现draft 8.4.4.2.3的内容。话不多说,下面给出initAdiPattern的实现和我个人的一些注释,供大家参考。
Void TComPattern::initAdiPattern( TComDataCU* pcCU, UInt uiZorderIdxInPart, UInt uiPartDepth, Int* piAdiBuf, Int iOrgBufStride, Int iOrgBufHeight, Bool& bAbove, Bool& bLeft, Bool bLMmode ){//! bLMmode is usually false Pel* piRoiOrigin; Int* piAdiTemp; UInt uiCuWidth = pcCU->getWidth(0) >> uiPartDepth; //!< CU的宽度 UInt uiCuHeight = pcCU->getHeight(0)>> uiPartDepth; //!< CU的高度 UInt uiCuWidth2 = uiCuWidth<<1; 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 x 32 + 1 Int iNumIntraNeighbor = 0; //!< 给可用邻块进行计数 UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB; //! 获取当前PU左上角LT,右上角RT以及左下角LB 以4x4块为单位的Zorder pcCU->deriveLeftRightTopIdxAdi( uiPartIdxLT, uiPartIdxRT, uiZorderIdxInPart, uiPartDepth ); pcCU->deriveLeftBottomIdxAdi ( uiPartIdxLB, uiZorderIdxInPart, uiPartDepth ); iUnitSize = g_uiMaxCUWidth >> g_uiMaxCUDepth; iNumUnitsInCu = uiCuWidth / iUnitSize; iTotalUnits = (iNumUnitsInCu << 2) + 1; // Top + RightTop + Left + LeftBottom + LeftTop = iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + 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; 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 ( pcCU, piRoiOrigin, piAdiTemp, bNeighborFlags, iNumIntraNeighbor, iUnitSize, iNumUnitsInCu, iTotalUnits, uiCuWidth, uiCuHeight, uiWidth, uiHeight, iPicStride, bLMmode); Int i; // generate filtered intra prediction samples Int iBufSize = uiCuHeight2 + uiCuWidth2 + 1; // left and left above border + above and above right border + top left corner = length of 3. filter buffer UInt uiWH = uiWidth * uiHeight; // number of elements in one buffer //! 下面所进行的工作主要是对参考样点进行3抽头的滤波。piAdiBuf指向滤波前的参考样点的首地址,在滤波前,先将所有参考样点 //! 拷贝到piFilterBuf指向的区域,经滤波后的样点值保存在piFilterBufN指向的区域,最终将滤波后的样点值拷贝到piFilterBuf1 //! 值得一提的是,最终的结果是,piAdiBuf指向的区域是未经滤波的样点值,而piFilterBuf1指向的区域是经过滤波的样点值, //! 两者的地址相差uiWH = uiWidth * uiHeight = (uiCuWidth2 + 1) * (uiCuHeight2 + 1),这就解释了在进行真正的帧内预测时, //! 在需要滤波时,指向piAdiBuf的指针需要加上uiWH的偏移量 Int* piFilteredBuf1 = piAdiBuf + uiWH; // 1. filter buffer Int* piFilteredBuf2 = piFilteredBuf1 + uiWH; // 2. filter buffer Int* piFilterBuf = piFilteredBuf2 + uiWH; // buffer for 2. filtering (sequential) Int* piFilterBufN = piFilterBuf + iBufSize; // buffer for 1. filtering (sequential) //!<存放的是参考样点经3抽头滤波后的值 // draft 8.4.4.2.3 Filtering process of neighbouring samples 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]; //!<上边界,存储顺序为从左往右 } // 1. filtering with [1 2 1] piFilterBufN[0] = piFilterBuf[0]; //!< 第1个点直接保存,不滤波 piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1]; //!< 最后一个点也直接保存,不滤波 for (i = 1; i < iBufSize - 1; i++) //!< 对中间样点值进行3抽头[1 2 1] / 4 的平滑滤波 { 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++]; // left border from bottom to top //!< 左边界 } piFilteredBuf1[0] = piFilterBufN[l++]; //!< 左上边界 for (i = 0; i < uiCuWidth2; i++) { piFilteredBuf1[1 + i] = piFilterBufN[l++]; // above border from left to right //!< 上边界 }}
最后附上图,以帮助大家更好地理解代码,我就不对图多作解释了,相信大家对着代码能比较容易看明白的。
(注,上图中,uiWidth和uiHeight实际上对应的是代码中的uiCUWidth和uiCUHeight,因画图的时候发生了遗漏,特此说明)
转自(http://blog.csdn.net/hevc_cjl/article/details/8184276)
- H.265之三 -帧内预测(3)
- H.265之三 帧内预测(1)
- H.265之三 -帧内预测(2)
- H.265之三 -帧内预测(4)
- H.264笔记之三——帧内预测
- 详解H.264之帧内预测
- 详解H.264之帧内预测
- H.264预测编码之帧内预测
- H.265帧内预测技术
- HEVC/H.265理论知识(3)——帧内预测
- H.264快速帧内预测算法
- H.266:帧内角度预测
- HEVC学习(五) —— 帧内预测系列之三
- [HEVC] HEVC学习(五) —— 帧内预测系列之三
- HEVC学习(五) —— 帧内预测系列之三
- HEVC学习(五) —— 帧内预测系列之三
- HEVC学习(五) —— 帧内预测系列之三
- HM编码器代码阅读(36)——帧内预测(三)帧内预测之参考像素块的预处理和滤波
- Keepalived配置及典型应用案例(已测试通过)
- 杭电acm 2023 求平均成绩
- 函数嵌套(c++)
- 第三章卡的开始
- 网页运行原理
- H.265之三 -帧内预测(3)
- 启动COM组件的三种机制
- 对mahout与hadoop的调用关系分析,以及建立统一化平台的思路
- linux下目录操作
- vmware中红帽linux的上网
- sql server触发器及存储过程
- 进程外COM组件的一个实例
- ios中的轮播图跟gridview的复用
- 代码测试之代码调试