HEVC学习(十五) —— SAO函数解析之三

这篇博客写得不错,觉得对我对大家刚开始学习时会有帮助,于是转载之。原文地址:http://blog.csdn.net/hevc_cjl/article/details/8288584

 

 

  1. /** Calculate SAO statistics for non-cross-slice or non-cross-tile processing
  2. * \param pRecStart to-be-filtered block buffer pointer
  3. * \param pOrgStart original block buffer pointer
  4. * \param stride picture buffer stride
  5. * \param ppStat statistics buffer
  6. * \param ppCount counter buffer
  7. * \param width block width
  8. * \param height block height
  9. * \param pbBorderAvail availabilities of block border pixels
  10. */
  11. Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail, Int iYCbCr)
  12. {
  13. Int64 *stats, *count;
  14. Int classIdx, posShift, startX, endX, startY, endY, signLeft,signRight,signDown,signDown1;
  15. Pel *pOrg, *pRec;
  16. UInt edgeType;
  17. Int x, y;
  18. Pel *pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo; //!< band offset 的索引表,共32个bands
  19. //--------- Band offset-----------//
  20. stats = ppStats[SAO_BO];
  21. count = ppCount[SAO_BO];
  22. pOrg = pOrgStart;
  23. pRec = pRecStart;
  24. for (y=0; y< height; y++)
  25. {
  26. for (x=0; x< width; x++)
  27. {
  28. classIdx = pTableBo[pRec[x]]; //!< classIdx即查表得到的band对应的序号值(1~32)
  29. if (classIdx)
  30. {
  31. stats[classIdx] += (pOrg[x] - pRec[x]); //!< 对原始像素与重建像素的差值求和
  32. count[classIdx] ++; //!< 对应classIdx的统计值加1
  33. }
  34. }
  35. pOrg += stride;
  36. pRec += stride;
  37. }
  38. //---------- Edge offset 0--------------//
  39. stats = ppStats[SAO_EO_0];
  40. count = ppCount[SAO_EO_0];
  41. pOrg = pOrgStart;
  42. pRec = pRecStart;
  43. //!< 设置起始点和终点
  44. startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
  45. endX = (pbBorderAvail[SGU_R]) ? width : (width -1);
  46. for (y=0; y< height; y++)
  47. {
  48. signLeft = xSign(pRec[startX] - pRec[startX-1]); //!< 取 p - n0 的符号
  49. for (x=startX; x< endX; x++)
  50. {
  51. signRight = xSign(pRec[x] - pRec[x+1]); //!< 取 p - n1 的符号
  52. edgeType = signRight + signLeft + 2; //!< 计算符号类型,用于下面通过查表的方式确定EdgeIdx
  53. signLeft = -signRight;
  54. /*
  55. const UInt TComSampleAdaptiveOffset::m_auiEoTable[9] =
  56. {
  57. 1, //0
  58. 2, //1
  59. 0, //2
  60. 3, //3
  61. 4, //4
  62. 0, //5
  63. 0, //6
  64. 0, //7
  65. 0
  66. };
  67. */
  68. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]); //!< 通过查表可以确定出真正的EdgeIdx,从而把统计值保存到对应的类型中去
  69. count[m_auiEoTable[edgeType]] ++;
  70. }
  71. pRec += stride;
  72. pOrg += stride;
  73. }
  74. //---------- Edge offset 1--------------//
  75. stats = ppStats[SAO_EO_1];
  76. count = ppCount[SAO_EO_1];
  77. pOrg = pOrgStart;
  78. pRec = pRecStart;
  79. startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
  80. endY = (pbBorderAvail[SGU_B]) ? height : height-1;
  81. if (!pbBorderAvail[SGU_T]) //!< 如果上邻行不可用,则下移一行
  82. {
  83. pRec += stride;
  84. pOrg += stride;
  85. }
  86. for (x=0; x< width; x++) //!< 先计算第一行与其上一行的差值
  87. {
  88. m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]); //!< 保存整一行 p - n0 的符号
  89. }
  90. for (y=startY; y<endY; y++)
  91. {
  92. for (x=0; x< width; x++)
  93. {
  94. signDown = xSign(pRec[x] - pRec[x+stride]); //!< 取 p - n1 的符号
  95. edgeType = signDown + m_iUpBuff1[x] + 2;
  96. m_iUpBuff1[x] = -signDown; //!< -signDown相当于是下一行的 p - n0 的符号,保存下来
  97. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  98. count[m_auiEoTable[edgeType]] ++;
  99. }
  100. pOrg += stride;
  101. pRec += stride;
  102. }
  103. //---------- Edge offset 2--------------//
  104. stats = ppStats[SAO_EO_2];
  105. count = ppCount[SAO_EO_2];
  106. pOrg = pOrgStart;
  107. pRec = pRecStart;
  108. posShift= stride + 1;
  109. startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
  110. endX = (pbBorderAvail[SGU_R]) ? width : (width-1);
  111. //prepare 2nd line upper sign
  112. pRec += stride;
  113. for (x=startX; x< endX+1; x++) //!< 先计算第二行的 p - n0 的符号,并保存下来
  114. {
  115. m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
  116. }
  117. //1st line
  118. pRec -= stride; //!< 回到第一行
  119. if(pbBorderAvail[SGU_TL]) //!< Top Left available
  120. {
  121. x= 0;
  122. edgeType = xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2; //!< -m_iUpBuff1[x+1]是因为第二行的p - n0相当于第一行的n1 - p,且第二行的x+1的位置才是第一行的x位置
  123. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  124. count[m_auiEoTable[edgeType]] ++;
  125. }
  126. if(pbBorderAvail[SGU_T]) //!< Top available
  127. {
  128. for(x= 1; x< endX; x++)
  129. {
  130. edgeType = xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
  131. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  132. count[m_auiEoTable[edgeType]] ++;
  133. }
  134. }
  135. pRec += stride;
  136. pOrg += stride;
  137. //middle lines
  138. for (y= 1; y< height-1; y++) //!< 除了第一行和最后一行的行
  139. {
  140. for (x=startX; x<endX; x++)
  141. {
  142. signDown1 = xSign(pRec[x] - pRec[x+ posShift]) ; //!< 取 p - n1 的符号
  143. edgeType = signDown1 + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1[x]正好就是p - n0 的符号
  144. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  145. count[m_auiEoTable[edgeType]] ++;
  146. m_iUpBufft[x+1] = -signDown1; //!< 当前行的p - n1相当于下一行的p - n0 的相反数,且当前行的x,对应于下一行的x+1
  147. }
  148. m_iUpBufft[startX] = xSign(pRec[stride+startX] - pRec[startX-1]); //!< 取startX位置的p - n0的符号
  149. //!< m_iUpBuff1与m_iUpBufft交换,交换完成后,m_iUpBuff1将保存的是下一行的p - n0的符号
  150. ipSwap = m_iUpBuff1;
  151. m_iUpBuff1 = m_iUpBufft;
  152. m_iUpBufft = ipSwap;
  153. pRec += stride;
  154. pOrg += stride;
  155. }
  156. //last line
  157. if(pbBorderAvail[SGU_B]) //!< 最后一行,Bottom available
  158. {
  159. for(x= startX; x< width-1; x++)
  160. {
  161. edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1保存的就是最后一行的p - n0的符号
  162. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  163. count[m_auiEoTable[edgeType]] ++;
  164. }
  165. }
  166. if(pbBorderAvail[SGU_BR]) //!< Bottom Right available
  167. {
  168. x= width -1;
  169. edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
  170. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  171. count[m_auiEoTable[edgeType]] ++;
  172. }
  173. //---------- Edge offset 3--------------//
  174. stats = ppStats[SAO_EO_3];
  175. count = ppCount[SAO_EO_3];
  176. pOrg = pOrgStart;
  177. pRec = pRecStart;
  178. posShift = stride - 1;
  179. startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
  180. endX = (pbBorderAvail[SGU_R]) ? width : (width -1);
  181. //prepare 2nd line upper sign
  182. pRec += stride;
  183. for (x=startX-1; x< endX; x++) //!< 先算第二行的p - n0的符号并保存到m_iUpBuff1中
  184. {
  185. m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
  186. }
  187. //first line
  188. pRec -= stride; //!< 回到第一行
  189. if(pbBorderAvail[SGU_T]) //!< Top available
  190. {
  191. for(x= startX; x< width -1; x++)
  192. {
  193. edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;//!< -m_iUpBuff1[x-1]是因为第二行的p - n0相当于第一行的n1 - p,且第二行的x-1的位置才是第一行的x位置
  194. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  195. count[m_auiEoTable[edgeType]] ++;
  196. }
  197. }
  198. if(pbBorderAvail[SGU_TR]) //!< Top Right available
  199. {
  200. x= width-1;
  201. edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
  202. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  203. count[m_auiEoTable[edgeType]] ++;
  204. }
  205. pRec += stride;
  206. pOrg += stride;
  207. //middle lines
  208. for (y= 1; y< height-1; y++) //!< 除第一行和最后一行的行
  209. {
  210. for(x= startX; x< endX; x++)
  211. {
  212. signDown1 = xSign(pRec[x] - pRec[x+ posShift]) ;
  213. edgeType = signDown1 + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1就是当前行的p - n0的符号
  214. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  215. count[m_auiEoTable[edgeType]] ++;
  216. m_iUpBuff1[x-1] = -signDown1; //!< 当前行的p - n1相当于下一行的p - n0 的相反数,且当前行的x,对应于下一行的x-1
  217. }
  218. m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]); //!< 保存下一行endX-1处的p - n0的符号
  219. pRec += stride;
  220. pOrg += stride;
  221. }
  222. //last line
  223. if(pbBorderAvail[SGU_BL]) //!< Bottom Left available
  224. {
  225. x= 0;
  226. edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1正好保存的是最后一行的x位置的p - n0的符号
  227. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  228. count[m_auiEoTable[edgeType]] ++;
  229. }
  230. if(pbBorderAvail[SGU_B]) //!< Bottom available
  231. {
  232. for(x= 1; x< endX; x++)
  233. {
  234. edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
  235. stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
  236. count[m_auiEoTable[edgeType]] ++;
  237. }
  238. }
  239. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值