HEVC学习(十一) —— 帧内预测系列之七

这个可以算是帧内预测中最为核心的一个部分了,不过相信有了前面那些基础积淀,这个部分看起来反而没有原来那么难了。下面直接给出代码及其相关注释:

[cpp]  view plain copy
  1. // Function for deriving the angular Intra predictions  
  2.   
  3. /** Function for deriving the simplified angular intra predictions. 
  4.  * \param pSrc pointer to reconstructed sample array 
  5.  * \param srcStride the stride of the reconstructed sample array 
  6.  * \param rpDst reference to pointer for the prediction sample array 
  7.  * \param dstStride the stride of the prediction sample array 
  8.  * \param width the width of the block 
  9.  * \param height the height of the block 
  10.  * \param dirMode the intra prediction mode index 
  11.  * \param blkAboveAvailable boolean indication if the block above is available 
  12.  * \param blkLeftAvailable boolean indication if the block to the left is available 
  13.  * 
  14.  * This function derives the prediction samples for the angular mode based on the prediction direction indicated by 
  15.  * the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and 
  16.  * the reference row above the block in the case of vertical prediction or displacement of the rightmost column 
  17.  * of the block and reference column left from the block in the case of the horizontal prediction. The displacement 
  18.  * is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples, 
  19.  * the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken 
  20.  * from the extended main reference. 
  21.  */  
  22. Void TComPrediction::xPredIntraAng( Int* pSrc, Int srcStride, Pel*& rpDst, Int dstStride, UInt width, UInt height, UInt dirMode, Bool blkAboveAvailable, Bool blkLeftAvailable, Bool bFilter )  
  23. {  
  24.   Int k,l;  
  25.   Int blkSize        = width;   //!< 当前PU的宽度  
  26.   Pel* pDst          = rpDst;   //!< 指向预测样点区域首地址  
  27.   
  28.   // Map the mode index to main prediction direction and angle  
  29.   assert( dirMode > 0 ); //!< no planar,保证不会出现Intra_Planar模式  
  30.   Bool modeDC        = dirMode < 2;  //!< DC mode,判断是否是DC预测模式  
  31.   Bool modeHor       = !modeDC && (dirMode < 18);        //!< mode 2 ~ 17,水平模式  
  32.   Bool modeVer       = !modeDC && !modeHor;     //!< mode 18 ~ 34,垂直模式  
  33.   Int intraPredAngle = modeVer ? (Int)dirMode - VER_IDX : modeHor ? -((Int)dirMode - HOR_IDX) : 0;  
  34.   Int absAng         = abs(intraPredAngle);  
  35.   Int signAng        = intraPredAngle < 0 ? -1 : 1;  
  36.   
  37.   // Set bitshifts and scale the angle parameter to block size  
  38.   Int angTable[9]    = {0,    2,    5,   9,  13,  17,  21,  26,  32};       // Table 8-4  
  39.   //! 先乘以256,等计算后将最终结果除以256,用定点数实现浮点数计算,保证精度  
  40.   Int invAngTable[9] = {0, 4096, 1638, 910, 630, 482, 390, 315, 256}; // (256 * 32) / Angle, Table 8-5  
  41.   Int invAngle       = invAngTable[absAng];  
  42.   absAng             = angTable[absAng];  
  43.   intraPredAngle     = signAng * absAng;  
  44.   
  45.   // Do the DC prediction  
  46.   if (modeDC)       // draft 8.4.4.2.5  
  47.   {  
  48.     Pel dcval = predIntraGetPredValDC(pSrc, srcStride, width, height, blkAboveAvailable, blkLeftAvailable);  
  49.   
  50.     for (k=0;k<blkSize;k++)  
  51.     {  
  52.       for (l=0;l<blkSize;l++)  
  53.       {  
  54.         pDst[k*dstStride+l] = dcval;      
  55.       }  
  56.     }  
  57.   }  
  58.   
  59.   // Do angular predictions  
  60.   //! 程序的想法是,先把角度都当成垂直预测方向的角度来算,到最后再做个判断,如果实际方向是水平方向,则对预测值做个翻转,以此减少代码冗余  
  61.   else      //!< draft 8.4.4.2.6  
  62.   {  
  63.     Pel* refMain;   //!< main reference  
  64.     Pel* refSide;   //!< side reference  
  65.     Pel  refAbove[2*MAX_CU_SIZE+1];  
  66.     Pel  refLeft[2*MAX_CU_SIZE+1];  
  67.   
  68.     //! Initialize the Main and Left reference array.  
  69.     if (intraPredAngle < 0)  //!< the intra prediction angle is negative   
  70.     {  
  71.       for (k=0;k<blkSize+1;k++)      //!< 式子(8-40)  
  72.       {  
  73.         refAbove[k+blkSize-1] = pSrc[k-srcStride-1];    //!< AboveLeft + Above,blkSize+1个点  
  74.       }  
  75.       for (k=0;k<blkSize+1;k++)      // 式子(8-48)  
  76.       {  
  77.         refLeft[k+blkSize-1] = pSrc[(k-1)*srcStride-1];     //!< AboveLeft + Left,blkSize+1个点  
  78.       }  
  79.       //! modeVer = true: refMain = refAbove + blkSize - 1; refSide = refLeft + blkSize - 1  
  80.       //! modeVer = false: refMain = refLeft + blkSize - 1; refSide = refAbove + blkSize - 1  
  81.       //! 加上blkSize-1这个偏移量是因为draft中ref[x]的x取值范围是-nT..2*nT,而实际的数组下标需从  
  82.       //! 0开始,因此,为了与draft相对应,先将refMain指向refAbove(refLeft)[blkSize-1],即ref[0],  
  83.       //! 这样保证了接下来代码中即使数组下标为负值也不会超出数组的内存范围  
  84.       refMain = (modeVer ? refAbove : refLeft) + (blkSize-1);  
  85.       refSide = (modeVer ? refLeft : refAbove) + (blkSize-1);  
  86.   
  87.       // Extend the Main reference to the left. //! 式子(8-41)复制side array样点到main array  
  88.       Int invAngleSum    = 128;       //!< rounding for (shift by 8)  
  89.       for (k=-1; k>blkSize*intraPredAngle>>5; k--)  
  90.       {  
  91.         invAngleSum += invAngle;    //!< 等价于k * invAngle,即求出在side reference上的截距  
  92.         refMain[k] = refSide[invAngleSum>>8];     //!< 根据计算出来的截距将side reference对应的样点值投影给main reference  
  93.       }  
  94.     }  
  95.     else    //!< intraPredAngle >= 0  
  96.     {  
  97.       for (k=0;k<2*blkSize+1;k++)        //!< 式子(8-42)  
  98.       {  
  99.         refAbove[k] = pSrc[k-srcStride-1];  
  100.       }  
  101.       for (k=0;k<2*blkSize+1;k++)        // 式子(8-50)  
  102.       {  
  103.         refLeft[k] = pSrc[(k-1)*srcStride-1];  
  104.       }  
  105.       //! 角度为正时,对于垂直方向的角度预测来说,只参考上方邻点的样点值;对于水平方向的角度预测来说,只参考左方邻点的样点值  
  106.       refMain = modeVer ? refAbove : refLeft;  
  107.       refSide = modeVer ? refLeft  : refAbove;  
  108.     }  
  109.   
  110.     if (intraPredAngle == 0)        //!< intraPredMode = 10 or 26  
  111.     {  
  112.       for (k=0;k<blkSize;k++)  
  113.       {  
  114.         for (l=0;l<blkSize;l++)  
  115.         {  
  116.           pDst[k*dstStride+l] = refMain[l+1];       //!< 对于Intra_Angular[10]或Intra_Angular[26]的情况,无需计算角度,直接对应点赋值即可,相当于H.264中的垂直预测、水平预测模式  
  117.         }  
  118.       }  
  119.   
  120.       if ( bFilter )    //!< true for luma while false for chroma  
  121.       {  
  122.         for (k=0;k<blkSize;k++)  //!< 式子(8-47)  
  123.         {//! 这个计算针对Intra_Angular[26]的情况,用之前角度预测得到的样点值、当前PU左上角的样点值与左邻点的样点值的差值加权平均作为滤波结果,起到平滑的作用  
  124.           pDst[k*dstStride] = Clip ( pDst[k*dstStride] + (( refSide[k+1] - refSide[0] ) >> 1) );  
  125.         }  
  126.       }  
  127.     }  
  128.     else  
  129.     {  
  130.       Int deltaPos=0;         
  131.       Int deltaInt;     //!< 坐标的整数部分  
  132.       Int deltaFract;   //!< 坐标的分数部分  
  133.       Int refMainIndex;  
  134.   
  135.       for (k=0;k<blkSize;k++)  
  136.       {  
  137.         deltaPos += intraPredAngle;     //!< 式子(8-43),每次循环加intraPredAngle,相当于(y+1)*intraPredAngle, y=0..nT-1  
  138.         deltaInt   = deltaPos >> 5;  
  139.         deltaFract = deltaPos & (32 - 1);   //!< 式子(8-44)  
  140.   
  141.         if (deltaFract)     //!< 非整像素  
  142.         {  
  143.           // Do linear filtering  
  144.           for (l=0;l<blkSize;l++)        //!< 式子(8-45)  
  145.           {  
  146.             refMainIndex        = l+deltaInt+1;     //!< 得到main reference中对应的整像素点位置  
  147.             //!< 用分数部分作为权值,对两个整像素点的样点值进行线性插值,作为预测值  
  148.             pDst[k*dstStride+l] = (Pel) ( ((32-deltaFract)*refMain[refMainIndex]+deltaFract*refMain[refMainIndex+1]+16) >> 5 );  
  149.           }  
  150.         }  
  151.         else    //!< 整像素  
  152.         {  
  153.           // Just copy the integer samples  
  154.           for (l=0;l<blkSize;l++)        //!< 式子(8-46)  
  155.           {  
  156.             pDst[k*dstStride+l] = refMain[l+deltaInt+1];    //!< 对于整像素点,不需要线性插值,直接拷贝过来作为预测值  
  157.           }  
  158.         }  
  159.       }  
  160.     }  
  161.   
  162.     // Flip the block if this is the horizontal mode //!< 即对该块进行转置,因为水平方向和垂直方向是对称的,减少代码冗余  
  163.     if (modeHor)  
  164.     {  
  165.       Pel  tmp;  
  166.       for (k=0;k<blkSize-1;k++)  
  167.       {  
  168.         for (l=k+1;l<blkSize;l++)  
  169.         {  
  170.           tmp                 = pDst[k*dstStride+l];  
  171.           pDst[k*dstStride+l] = pDst[l*dstStride+k];  
  172.           pDst[l*dstStride+k] = tmp;  
  173.         }  
  174.       }  
  175.     }  
  176.   }  
  177. }  

(转载请注明出处。)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值