这篇博客写得不错,觉得对我对大家刚开始学习时会有帮助,于是转载之。原文地址:http://blog.csdn.net/hevc_cjl/article/details/8288584
- /** Calculate SAO statistics for non-cross-slice or non-cross-tile processing
- * \param pRecStart to-be-filtered block buffer pointer
- * \param pOrgStart original block buffer pointer
- * \param stride picture buffer stride
- * \param ppStat statistics buffer
- * \param ppCount counter buffer
- * \param width block width
- * \param height block height
- * \param pbBorderAvail availabilities of block border pixels
- */
- Void TEncSampleAdaptiveOffset::calcSaoStatsBlock( Pel* pRecStart, Pel* pOrgStart, Int stride, Int64** ppStats, Int64** ppCount, UInt width, UInt height, Bool* pbBorderAvail, Int iYCbCr)
- {
- Int64 *stats, *count;
- Int classIdx, posShift, startX, endX, startY, endY, signLeft,signRight,signDown,signDown1;
- Pel *pOrg, *pRec;
- UInt edgeType;
- Int x, y;
- Pel *pTableBo = (iYCbCr==0)?m_lumaTableBo:m_chromaTableBo; //!< band offset 的索引表,共32个bands
- //--------- Band offset-----------//
- stats = ppStats[SAO_BO];
- count = ppCount[SAO_BO];
- pOrg = pOrgStart;
- pRec = pRecStart;
- for (y=0; y< height; y++)
- {
- for (x=0; x< width; x++)
- {
- classIdx = pTableBo[pRec[x]]; //!< classIdx即查表得到的band对应的序号值(1~32)
- if (classIdx)
- {
- stats[classIdx] += (pOrg[x] - pRec[x]); //!< 对原始像素与重建像素的差值求和
- count[classIdx] ++; //!< 对应classIdx的统计值加1
- }
- }
- pOrg += stride;
- pRec += stride;
- }
- //---------- Edge offset 0--------------//
- stats = ppStats[SAO_EO_0];
- count = ppCount[SAO_EO_0];
- pOrg = pOrgStart;
- pRec = pRecStart;
- //!< 设置起始点和终点
- startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
- endX = (pbBorderAvail[SGU_R]) ? width : (width -1);
- for (y=0; y< height; y++)
- {
- signLeft = xSign(pRec[startX] - pRec[startX-1]); //!< 取 p - n0 的符号
- for (x=startX; x< endX; x++)
- {
- signRight = xSign(pRec[x] - pRec[x+1]); //!< 取 p - n1 的符号
- edgeType = signRight + signLeft + 2; //!< 计算符号类型,用于下面通过查表的方式确定EdgeIdx
- signLeft = -signRight;
- /*
- const UInt TComSampleAdaptiveOffset::m_auiEoTable[9] =
- {
- 1, //0
- 2, //1
- 0, //2
- 3, //3
- 4, //4
- 0, //5
- 0, //6
- 0, //7
- 0
- };
- */
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]); //!< 通过查表可以确定出真正的EdgeIdx,从而把统计值保存到对应的类型中去
- count[m_auiEoTable[edgeType]] ++;
- }
- pRec += stride;
- pOrg += stride;
- }
- //---------- Edge offset 1--------------//
- stats = ppStats[SAO_EO_1];
- count = ppCount[SAO_EO_1];
- pOrg = pOrgStart;
- pRec = pRecStart;
- startY = (pbBorderAvail[SGU_T]) ? 0 : 1;
- endY = (pbBorderAvail[SGU_B]) ? height : height-1;
- if (!pbBorderAvail[SGU_T]) //!< 如果上邻行不可用,则下移一行
- {
- pRec += stride;
- pOrg += stride;
- }
- for (x=0; x< width; x++) //!< 先计算第一行与其上一行的差值
- {
- m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-stride]); //!< 保存整一行 p - n0 的符号
- }
- for (y=startY; y<endY; y++)
- {
- for (x=0; x< width; x++)
- {
- signDown = xSign(pRec[x] - pRec[x+stride]); //!< 取 p - n1 的符号
- edgeType = signDown + m_iUpBuff1[x] + 2;
- m_iUpBuff1[x] = -signDown; //!< -signDown相当于是下一行的 p - n0 的符号,保存下来
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- pOrg += stride;
- pRec += stride;
- }
- //---------- Edge offset 2--------------//
- stats = ppStats[SAO_EO_2];
- count = ppCount[SAO_EO_2];
- pOrg = pOrgStart;
- pRec = pRecStart;
- posShift= stride + 1;
- startX = (pbBorderAvail[SGU_L]) ? 0 : 1 ;
- endX = (pbBorderAvail[SGU_R]) ? width : (width-1);
- //prepare 2nd line upper sign
- pRec += stride;
- for (x=startX; x< endX+1; x++) //!< 先计算第二行的 p - n0 的符号,并保存下来
- {
- m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
- }
- //1st line
- pRec -= stride; //!< 回到第一行
- if(pbBorderAvail[SGU_TL]) //!< Top Left available
- {
- x= 0;
- edgeType = xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2; //!< -m_iUpBuff1[x+1]是因为第二行的p - n0相当于第一行的n1 - p,且第二行的x+1的位置才是第一行的x位置
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- if(pbBorderAvail[SGU_T]) //!< Top available
- {
- for(x= 1; x< endX; x++)
- {
- edgeType = xSign(pRec[x] - pRec[x- posShift]) - m_iUpBuff1[x+1] + 2;
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- }
- pRec += stride;
- pOrg += stride;
- //middle lines
- for (y= 1; y< height-1; y++) //!< 除了第一行和最后一行的行
- {
- for (x=startX; x<endX; x++)
- {
- signDown1 = xSign(pRec[x] - pRec[x+ posShift]) ; //!< 取 p - n1 的符号
- edgeType = signDown1 + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1[x]正好就是p - n0 的符号
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- m_iUpBufft[x+1] = -signDown1; //!< 当前行的p - n1相当于下一行的p - n0 的相反数,且当前行的x,对应于下一行的x+1
- }
- m_iUpBufft[startX] = xSign(pRec[stride+startX] - pRec[startX-1]); //!< 取startX位置的p - n0的符号
- //!< m_iUpBuff1与m_iUpBufft交换,交换完成后,m_iUpBuff1将保存的是下一行的p - n0的符号
- ipSwap = m_iUpBuff1;
- m_iUpBuff1 = m_iUpBufft;
- m_iUpBufft = ipSwap;
- pRec += stride;
- pOrg += stride;
- }
- //last line
- if(pbBorderAvail[SGU_B]) //!< 最后一行,Bottom available
- {
- for(x= startX; x< width-1; x++)
- {
- edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1保存的就是最后一行的p - n0的符号
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- }
- if(pbBorderAvail[SGU_BR]) //!< Bottom Right available
- {
- x= width -1;
- edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- //---------- Edge offset 3--------------//
- stats = ppStats[SAO_EO_3];
- count = ppCount[SAO_EO_3];
- pOrg = pOrgStart;
- pRec = pRecStart;
- posShift = stride - 1;
- startX = (pbBorderAvail[SGU_L]) ? 0 : 1;
- endX = (pbBorderAvail[SGU_R]) ? width : (width -1);
- //prepare 2nd line upper sign
- pRec += stride;
- for (x=startX-1; x< endX; x++) //!< 先算第二行的p - n0的符号并保存到m_iUpBuff1中
- {
- m_iUpBuff1[x] = xSign(pRec[x] - pRec[x- posShift]);
- }
- //first line
- pRec -= stride; //!< 回到第一行
- if(pbBorderAvail[SGU_T]) //!< Top available
- {
- for(x= startX; x< width -1; x++)
- {
- edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;//!< -m_iUpBuff1[x-1]是因为第二行的p - n0相当于第一行的n1 - p,且第二行的x-1的位置才是第一行的x位置
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- }
- if(pbBorderAvail[SGU_TR]) //!< Top Right available
- {
- x= width-1;
- edgeType = xSign(pRec[x] - pRec[x- posShift]) -m_iUpBuff1[x-1] + 2;
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- pRec += stride;
- pOrg += stride;
- //middle lines
- for (y= 1; y< height-1; y++) //!< 除第一行和最后一行的行
- {
- for(x= startX; x< endX; x++)
- {
- signDown1 = xSign(pRec[x] - pRec[x+ posShift]) ;
- edgeType = signDown1 + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1就是当前行的p - n0的符号
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- m_iUpBuff1[x-1] = -signDown1; //!< 当前行的p - n1相当于下一行的p - n0 的相反数,且当前行的x,对应于下一行的x-1
- }
- m_iUpBuff1[endX-1] = xSign(pRec[endX-1 + stride] - pRec[endX]); //!< 保存下一行endX-1处的p - n0的符号
- pRec += stride;
- pOrg += stride;
- }
- //last line
- if(pbBorderAvail[SGU_BL]) //!< Bottom Left available
- {
- x= 0;
- edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2; //!< 此时m_iUpBuff1正好保存的是最后一行的x位置的p - n0的符号
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- if(pbBorderAvail[SGU_B]) //!< Bottom available
- {
- for(x= 1; x< endX; x++)
- {
- edgeType = xSign(pRec[x] - pRec[x+ posShift]) + m_iUpBuff1[x] + 2;
- stats[m_auiEoTable[edgeType]] += (pOrg[x] - pRec[x]);
- count[m_auiEoTable[edgeType]] ++;
- }
- }
- }