主要参考作者hevc_cjl的博客:  http://blog.csdn.net/hevc_cjl/article/details/8184276?reload ,自己添加了更为细致的注解。

*  注: 带"1晨不变"的,为原作者的注解; 本文作者注解标 "wxl_125"

initAdiPattern 函数中,【Adi = arbitrary direction intra prediction  】这个概念提案中提到的。

贴代码之前先说一下整个帧内预测的框架:

                                    

/*
initAdiPattern函数【Adi = arbitrary direction intra prediction  】
(1晨不变)
(1)检测当前PU的相邻样点包括左上、上、右上、左、左下邻域样点值的可用性,或者说检查这些点是否存在;
(2)参考样点的替换过程,主要实现的是JCTVC-J1003即draft 8.4.4.2.2的内容,主要由函数fillReferenceSamples来完成,
这个在之前的文章已经讨论过了;
(3)相邻样点即参考样点的平滑滤波,主要实现draft 8.4.4.2.3的内容。
*/
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;
UInt  uiCuHeight2 = uiCuHeight<<1;
UInt  uiWidth;
UInt  uiHeight;
Int   iPicStride = pcCU->getPic()->getStride(); //图像跨度(原图像宽度 + 两边扩充的参考像素点)【wxl_125】
Int   iUnitSize = 0;   //变量解释见下面参数赋值【wxl_125】
Int   iNumUnitsInCu = 0;
Int   iTotalUnits = 0;
Bool  bNeighborFlags[4 * MAX_NUM_SPU_W + 1]; //!< 用于存放4个方向上的相邻样点值的【可用性】,4*32+1
Int   iNumIntraNeighbor = 0;                 !< 给可用邻块进行计数   【wxl_125:统计可以参考的领域块的数目】
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; // iTotalUnits = Top + RightTop + Left + LeftBottom + LeftTop
//                                            = iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + 1
//  wxl_125:统计可以使用的领域参考块的数目
// (扫描顺序是从左下到左上,再从左上到右上)
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;
//wxl_125: 参考样点的替换(填补)过程
fillReferenceSamples (g_bitDepthY, piRoiOrigin, piAdiTemp, bNeighborFlags, iNumIntraNeighbor, iUnitSize, iNumUnitsInCu, iTotalUnits, uiCuWidth, uiCuHeight, uiWidth, uiHeight, iPicStride, bLMmode);
// ****************************************************
//! (1晨)下面所进行的工作主要是对参考样点进行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;  // 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
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);
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)
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]【wxl_125:首尾直接保存,中间样点值进行3抽头[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++];
}
}

HEVC-帧内预测2: initAdiPattern 函数相关推荐

  1. 2.H.265/HEVC —— 帧内预测

    在H.265/HEVC中,35种预测模式是在PU的基础上定义的,而具体帧内预测过程的实现则是以TU为单位的.编撰规定PU可以以四叉树的形式划分TU,且一个PU内所有TU共享同一种预测模式的形式划分TU ...

  2. HEVC帧内预测参考相邻帧代码解析

    作者:66 (转载请注明出处) 参考链接:http://blog.csdn.net/hevc_cjl/article/details/8200793 亮度分量的帧内预测涉及到的模块比较多,CU-> ...

  3. VVC 帧内预测代码 xPredIntraAng()函数

    帧内预测中的initPredIntraParams()函数 (负参考方向处在跑代码时再看一遍)_青椒鸡汤的博客-CSDN博客 H.266/VVC-VTM代码学习-帧内预测05-Angular模式下计算 ...

  4. HEVC帧内预测参考像素检测获取和滤波

    作者:66 (转载请注明出处) 还是参考HEVC_CJL的博客,理论都清楚,跟着他的进度看代码,感谢前辈的分享,他的代码里没有强滤波过程,在此我稍加补充. 原文链接:http://blog.csdn. ...

  5. HEVC学习(五) —— 帧内预测系列之三

    由于研究的需要,现将一晨不变大神的关于HEVC帧内预测的相关博客进行转载,方便自己查阅.一直都看一晨不变大神的帖子,受益匪浅.原著博客地址:http://blog.csdn.net/HEVC_CJL/ ...

  6. 【HEVC代码阅读】帧内预测

    HEVC的帧内预测的架构分为三个步骤: ①构建参考像素数组:②生成预测像素:③后处理操作. HEVC标准将这三个步骤进行了精密设计,以求达到较高的编码效率,同时降低编码和解码端的运算要求.HEVC标准 ...

  7. HEVC学习(六) —— 帧内预测系列之四

    本文主要把实现亮度分量帧内预测的主函数的大体框架通过代码注释的方式介绍一下. [cpp]  view plain copy Void TEncSearch::estIntraPredQT( TComD ...

  8. HEVC算法和体系结构:预测编码之帧内预测

    预测编码之帧内预测(Intra-Picture Prediction) 预测编码(Prediction Coding)是视频编码的核心技术之一,指利用已编码的一个或几个样本值,根据某种模型或方法,对当 ...

  9. 关于帧内预测模式的视频隐写代码介绍

    关于帧内预测模式的视频隐写代码介绍 前言 一.H.265/HEVC的帧内预测过程 二.论文[1]的介绍以及如何复现 前言 在早期的基于帧内预测模式(IPM)的H.265/HEVC视频中,大多是基于自定 ...

  10. H.266帧内预测:位置决定的帧内预测组合(PDPC)

    PDPC核心思想是联合HEVC帧内预测中滤波边缘参考采样与未滤波边缘参考采样,进行加权预测. 注意:考虑到复杂度问题,PDPC只用于Planar模式. 在HEVC的帧内预测中,根据预测模式和块尺寸大小 ...

最新文章

  1. 27年前被Nature拒稿,如今斩获诺贝尔奖!学术投稿模式再引热议:都有神奇的评审2...
  2. 设计模式之:适配器模式
  3. Git版本回退之 reset 和 revert
  4. Python匿名函数——lambda表达式
  5. [源码]C# to SQL 的翻译器.net 1.1版
  6. Spark集群 + Akka + Kafka + Scala 开发(2) : 开发一个Spark应用
  7. 利用 Zabbix 监控数据库文件大小
  8. Java中 LocalDate、LocalTime、LocalDateTime三个时间工具类的使用介绍
  9. html 表格_HTML -- 表格结构
  10. Android IOS WebRTC 音视频开发总结(六三)-- 2016国内IM云服务行业分析
  11. 快递单中抽取关键信息【一】----基于BiGRU+CR+预训练的词向量优化
  12. 在多媒体计算机中静态媒体是指,《多媒体技术及应用》按章复习题
  13. activiti7---activiti7整合springboot
  14. 微信封号被限制的几种原因及解决方法
  15. python——实例详细弄懂if __name__ == ‘__main__‘用法
  16. 装机春天时刻,盘点4月高性价比国产SSD
  17. Android开发笔记(序)
  18. 打印机出现“你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问。
  19. 虚拟机安装Ubuntu 22.4
  20. python是一种面向____的高级语言_Python简介_语法_高薪Ptython系列专栏_2

热门文章

  1. echarts中折线图、柱状图之间的转换
  2. 微信公众号开发--普通表情与emoji表情的处理 (实用、超赞有图片资源)
  3. 新手拍短视频技术总结:真实 随性 用心
  4. GPS之MTK平台代码小结以及gps协议注释
  5. 亚马逊广告CPC优化技巧 投放就有效
  6. nmbd samba中文
  7. html中img显示图片的两种常用方式
  8. 推荐四个不错的公众号
  9. Trajectory Similarity Join in Spatial Networks
  10. 浏览器同源政策之ajax请求不能发送