HM编码器代码阅读(43)——样点自适应补偿SAO(二)收集像素块的统计信息

来源:互联网 发布:mac系统语言代码 编辑:程序博客网 时间:2024/06/06 17:03

收集像素块的统计信息



    在进行SAO之前,要对像素块的像素值进行归类,然后判断它们属于EO的那个种类或者BO的哪个边带



入口函数getStatistics



    getStatistics是收集像素统计信息的入口函数
    流程如下:
    1、遍历图像的每一个CTU
    2、对于每一个CTU,调用deriveLoopFilterBoundaryAvailibility,用来判断相邻CTU的有效性(是否存在)
    3、对于每个CTU的每一个颜色分量,调用getBlkStats,用来搜集该CTU中某个分量的像素的统计信息
    4、处理结束

/*** 收集像素块的统计信息,用于判断像素属于EO的那个种类/BO的哪个边带** 对整个图像进行处理,遍历图像的每一个CTU,对CTU的每一个分量,都调用 getBlkStats*/Void TEncSampleAdaptiveOffset::getStatistics(SAOStatData*** blkStats, TComPicYuv* orgYuv, TComPicYuv* srcYuv, TComPic* pPic#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK, Bool isCalculatePreDeblockSamples#endif){Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;for(Int ctu= 0; ctu < m_numCTUsPic; ctu++){Int yPos   = (ctu / m_numCTUInWidth)*m_maxCUHeight;Int xPos   = (ctu % m_numCTUInWidth)*m_maxCUWidth;Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;Int width  = (xPos + m_maxCUWidth  > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;// 判断相邻CTU的有效性(是否存在)pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);//NOTE: The number of skipped lines during gathering CTU statistics depends on the slice boundary availabilities.//For simplicity, here only picture boundaries are considered.isRightAvail      = (xPos + m_maxCUWidth  < m_picWidth );isBelowAvail      = (yPos + m_maxCUHeight < m_picHeight);isBelowRightAvail = (isRightAvail && isBelowAvail);isBelowLeftAvail  = ((xPos > 0) && (isBelowAvail));isAboveRightAvail = ((yPos > 0) && (isRightAvail));for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++){Bool isLuma     = (compIdx == SAO_Y);Int  formatShift= isLuma?0:1;Int  srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride();Pel* srcBlk    = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift);Int  orgStride  = isLuma?orgYuv->getStride():orgYuv->getCStride();Pel* orgBlk     = getPicBuf(orgYuv, compIdx)+ (yPos >> formatShift)*orgStride+ (xPos >> formatShift);// 搜集一个CTU中某个分量的像素的统计信息getBlkStats(compIdx, blkStats[ctu][compIdx]  , srcBlk, orgBlk, srcStride, orgStride, (width  >> formatShift), (height >> formatShift), isLeftAvail,  isRightAvail, isAboveAvail, isBelowAvail, isAboveLeftAvail, isAboveRightAvail, isBelowLeftAvail, isBelowRightAvail#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK, isCalculatePreDeblockSamples#endif);}}}



判断相邻CTU的有效性


    deriveLoopFilterBoundaryAvailibility用于判断相邻CTU的有效性(是否存在),这是为了下一步的像素统计做准备

/*** 判断相邻CTU的有效性(是否存在)*/Void TComPicSym::deriveLoopFilterBoundaryAvailibility(Int ctu,Bool& isLeftAvail,Bool& isRightAvail,Bool& isAboveAvail,Bool& isBelowAvail,Bool& isAboveLeftAvail,Bool& isAboveRightAvail,Bool& isBelowLeftAvail,Bool& isBelowRightAvail){isLeftAvail      = (ctu % m_uiWidthInCU != 0);isRightAvail     = (ctu % m_uiWidthInCU != m_uiWidthInCU-1);isAboveAvail     = (ctu >= m_uiWidthInCU );isBelowAvail     = (ctu <  m_uiNumCUsInFrame - m_uiWidthInCU);isAboveLeftAvail = (isAboveAvail && isLeftAvail);isAboveRightAvail= (isAboveAvail && isRightAvail);isBelowLeftAvail = (isBelowAvail && isLeftAvail);isBelowRightAvail= (isBelowAvail && isRightAvail);Bool isLoopFiltAcrossTilePPS = getCU(ctu)->getSlice()->getPPS()->getLoopFilterAcrossTilesEnabledFlag();{TComDataCU* ctuCurr  = getCU(ctu);TComDataCU* ctuLeft  = isLeftAvail ?getCU(ctu-1):NULL;TComDataCU* ctuRight = isRightAvail?getCU(ctu+1):NULL;TComDataCU* ctuAbove = isAboveAvail?getCU(ctu-m_uiWidthInCU):NULL;TComDataCU* ctuBelow = isBelowAvail?getCU(ctu+m_uiWidthInCU):NULL;TComDataCU* ctuAboveLeft  = isAboveLeftAvail ? getCU(ctu-m_uiWidthInCU-1):NULL;TComDataCU* ctuAboveRigtht= isAboveRightAvail? getCU(ctu-m_uiWidthInCU+1):NULL;TComDataCU* ctuBelowLeft  = isBelowLeftAvail ? getCU(ctu+m_uiWidthInCU-1):NULL;TComDataCU* ctuBelowRight = isBelowRightAvail? getCU(ctu+m_uiWidthInCU+1):NULL;{//leftif(ctuLeft != NULL){isLeftAvail = (ctuCurr->getSlice()->getSliceCurStartCUAddr() != ctuLeft->getSlice()->getSliceCurStartCUAddr())?ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag():true;}//aboveif(ctuAbove != NULL){isAboveAvail = (ctuCurr->getSlice()->getSliceCurStartCUAddr() != ctuAbove->getSlice()->getSliceCurStartCUAddr())?ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag():true;}//rightif(ctuRight != NULL){isRightAvail = (ctuCurr->getSlice()->getSliceCurStartCUAddr() != ctuRight->getSlice()->getSliceCurStartCUAddr())?ctuRight->getSlice()->getLFCrossSliceBoundaryFlag():true;}//belowif(ctuBelow != NULL){isBelowAvail = (ctuCurr->getSlice()->getSliceCurStartCUAddr() != ctuBelow->getSlice()->getSliceCurStartCUAddr())?ctuBelow->getSlice()->getLFCrossSliceBoundaryFlag():true;}//above-leftif(ctuAboveLeft != NULL){isAboveLeftAvail = (ctuCurr->getSlice()->getSliceCurStartCUAddr() != ctuAboveLeft->getSlice()->getSliceCurStartCUAddr())?ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag():true;}//below-rightif(ctuBelowRight != NULL){isBelowRightAvail = (ctuCurr->getSlice()->getSliceCurStartCUAddr() != ctuBelowRight->getSlice()->getSliceCurStartCUAddr())?ctuBelowRight->getSlice()->getLFCrossSliceBoundaryFlag():true;}//above-rightif(ctuAboveRigtht != NULL){Int curSliceStartEncOrder  = ctuCurr->getSlice()->getSliceCurStartCUAddr();Int aboveRigthtSliceStartEncOrder = ctuAboveRigtht->getSlice()->getSliceCurStartCUAddr();isAboveRightAvail = (curSliceStartEncOrder == aboveRigthtSliceStartEncOrder)?(true):((curSliceStartEncOrder > aboveRigthtSliceStartEncOrder)?(ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag()):(ctuAboveRigtht->getSlice()->getLFCrossSliceBoundaryFlag()));          }//below-leftif(ctuBelowLeft != NULL){Int curSliceStartEncOrder  = ctuCurr->getSlice()->getSliceCurStartCUAddr();Int belowLeftSliceStartEncOrder = ctuBelowLeft->getSlice()->getSliceCurStartCUAddr();isBelowLeftAvail = (curSliceStartEncOrder == belowLeftSliceStartEncOrder)?(true):((curSliceStartEncOrder > belowLeftSliceStartEncOrder)?(ctuCurr->getSlice()->getLFCrossSliceBoundaryFlag()):(ctuBelowLeft->getSlice()->getLFCrossSliceBoundaryFlag()));}        }if(!isLoopFiltAcrossTilePPS){      isLeftAvail      = (!isLeftAvail      ) ?false:(getTileIdxMap( ctuLeft->getAddr()         ) == getTileIdxMap( ctu ));isAboveAvail     = (!isAboveAvail     ) ?false:(getTileIdxMap( ctuAbove->getAddr()        ) == getTileIdxMap( ctu ));isRightAvail     = (!isRightAvail     ) ?false:(getTileIdxMap( ctuRight->getAddr()        ) == getTileIdxMap( ctu ));isBelowAvail     = (!isBelowAvail     ) ?false:(getTileIdxMap( ctuBelow->getAddr()        ) == getTileIdxMap( ctu ));isAboveLeftAvail = (!isAboveLeftAvail ) ?false:(getTileIdxMap( ctuAboveLeft->getAddr()    ) == getTileIdxMap( ctu ));isAboveRightAvail= (!isAboveRightAvail) ?false:(getTileIdxMap( ctuAboveRigtht->getAddr()  ) == getTileIdxMap( ctu ));isBelowLeftAvail = (!isBelowLeftAvail ) ?false:(getTileIdxMap( ctuBelowLeft->getAddr()    ) == getTileIdxMap( ctu ));isBelowRightAvail= (!isBelowRightAvail) ?false:(getTileIdxMap( ctuBelowRight->getAddr()   ) == getTileIdxMap( ctu ));}}}



搜集一个CTU分量的像素的统计信息


    getBlkStats用来搜集一个CTU中某个分量的像素的统计信息
    流程如下:
    1、遍历SAO除了merge之外的所有模式:SAO_TYPE_EO_0、SAO_TYPE_EO_90、SAO_TYPE_EO_135、SAO_TYPE_EO_45、SAO_TYPE_BO
    2、对于每一个SAO模式,都统计该模式下像素的信息
    3、最后的统计信息存放在SAOStatData中

/*** 搜集一个CTU中某个分量的像素的统计信息** 遍历SAO除了merge之外的所有类型:** SAO_TYPE_EO_0 ,** SAO_TYPE_EO_90,** SAO_TYPE_EO_135,** SAO_TYPE_EO_45,** SAO_TYPE_BO ** 对于每一种类型,都搜集像素的统计信息** 最后的统计信息存放在SAOStatData中*/Void TEncSampleAdaptiveOffset::getBlkStats(Int compIdx, SAOStatData* statsDataTypes  , Pel* srcBlk, Pel* orgBlk, Int srcStride, Int orgStride, Int width, Int height, Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail#if SAO_ENCODE_ALLOW_USE_PREDEBLOCK, Bool isCalculatePreDeblockSamples#endif){if(m_lineBufWidth != m_maxCUWidth){m_lineBufWidth = m_maxCUWidth;if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;m_signLineBuf1 = new Char[m_lineBufWidth+1]; if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;m_signLineBuf2 = new Char[m_lineBufWidth+1];}Int x,y, startX, startY, endX, endY, edgeType, firstLineStartX, firstLineEndX;Char signLeft, signRight, signDown;Int64 *diff, *count;Pel *srcLine, *orgLine;Int* skipLinesR = m_skipLinesR[compIdx];Int* skipLinesB = m_skipLinesB[compIdx];for(Int typeIdx=0; typeIdx< NUM_SAO_NEW_TYPES; typeIdx++){SAOStatData& statsData= statsDataTypes[typeIdx];statsData.reset();srcLine = srcBlk;orgLine = orgBlk;diff    = statsData.diff;count   = statsData.count;switch(typeIdx){case SAO_TYPE_EO_0:{diff +=2;count+=2;endY   = (isBelowAvail) ? (height - skipLinesB[typeIdx]) : height;#if SAO_ENCODE_ALLOW_USE_PREDEBLOCKstartX = (!isCalculatePreDeblockSamples) ? (isLeftAvail  ? 0 : 1): (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1));#elsestartX = isLeftAvail ? 0 : 1;#endif#if SAO_ENCODE_ALLOW_USE_PREDEBLOCKendX   = (!isCalculatePreDeblockSamples) ? (isRightAvail ? (width - skipLinesR[typeIdx]) : (width - 1)): (isRightAvail ? width : (width - 1));#elseendX   = isRightAvail ? (width - skipLinesR[typeIdx]): (width - 1);#endiffor (y=0; y<endY; y++){#if SAO_SGN_FUNCsignLeft = (Char)sgn(srcLine[startX] - srcLine[startX-1]);#elsesignLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];#endiffor (x=startX; x<endX; x++){#if SAO_SGN_FUNCsignRight =  (Char)sgn(srcLine[x] - srcLine[x+1]);#elsesignRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]]; #endifedgeType  =  signRight + signLeft;signLeft  = -signRight;diff [edgeType] += (orgLine[x] - srcLine[x]);count[edgeType] ++;}srcLine  += srcStride;orgLine  += orgStride;}#if SAO_ENCODE_ALLOW_USE_PREDEBLOCKif(isCalculatePreDeblockSamples){if(isBelowAvail){startX = isLeftAvail  ? 0 : 1;endX   = isRightAvail ? width : (width -1);for(y=0; y<skipLinesB[typeIdx]; y++){#if SAO_SGN_FUNCsignLeft = (Char)sgn(srcLine[startX] - srcLine[startX-1]);#elsesignLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];#endiffor (x=startX; x<endX; x++){#if SAO_SGN_FUNCsignRight =  (Char)sgn(srcLine[x] - srcLine[x+1]);#elsesignRight =  (Char)m_sign[srcLine[x] - srcLine[x+1]];#endifedgeType  =  signRight + signLeft;signLeft  = -signRight;diff [edgeType] += (orgLine[x] - srcLine[x]);count[edgeType] ++;}srcLine  += srcStride;orgLine  += orgStride;}}}#endif}break;case SAO_TYPE_EO_90:// 代码省略...break;case SAO_TYPE_EO_135:// 代码省略...break;case SAO_TYPE_EO_45:// 代码省略...break;case SAO_TYPE_BO:// 代码省略...break;default:{printf("Not a supported SAO types\n");assert(0);exit(-1);}}}}






0 0
原创粉丝点击