帧内预测的主函数框架分析

来源:互联网 发布:c 语言中的删除文件 编辑:程序博客网 时间:2024/06/08 14:49
Void   TEncSearch::estIntraPredQT( TComDataCU* pcCU,                              TComYuv*    pcOrgYuv,                              TComYuv*    pcPredYuv,                              TComYuv*    pcResiYuv,                              TComYuv*    pcRecoYuv,                             UInt&       ruiDistC,                             Bool        bLumaOnly )  {    UInt    uiDepth        = pcCU->getDepth(0); //!< 当前CU的深度    UInt    uiNumPU        = pcCU->getNumPartInter(); //!< 当前CU的分割模式,(SIZE_2Nx2N:1, SIZE_2NxN:2, SIZE_Nx2N:2, SIZE_NxN:4 ... )    UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1; //!< 用于计算变换的深度,实际深度为该值+uiDepth    UInt    uiWidth        = pcCU->getWidth (0) >> uiInitTrDepth; //!< 当前PU的宽度,如果又分成4个子块,则宽度除以2    UInt    uiHeight       = pcCU->getHeight(0) >> uiInitTrDepth; //!< 当前PU的高度,如果又分成4个子块,则高度除以2    UInt    uiQNumParts    = pcCU->getTotalNumPart() >> 2; // 最小的分区是4x4大小的块,这里计算出以该4x4块为单位的分割数,这么做便于计算当前CU的Zorder坐标    UInt    uiWidthBit     = pcCU->getIntraSizeIdx(0);    UInt    uiOverallDistY = 0;    UInt    uiOverallDistC = 0;    UInt    CandNum;    Double  CandCostList[ FAST_UDI_MAX_RDMODE_NUM ];        //===== set QP and clear Cbf =====    if ( pcCU->getSlice()->getPPS()->getUseDQP() == true)    {      pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth );    }    else    {      pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth );    }        //===== loop over partitions =====    UInt uiPartOffset = 0; //!< 用于记录当前PU的Zorder坐标    for( UInt uiPU = 0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts ) //!< 对当前CU中的每个PU进行遍历    {      //===== init pattern for luma prediction =====      Bool bAboveAvail = false;      Bool bLeftAvail  = false;      pcCU->getPattern()->initPattern   ( pcCU, uiInitTrDepth, uiPartOffset ); // set parameters from CU data for accessing neighbouring pixels   // set luma parameters from CU data for accessing ADI data //!< 主要获取当前PU的邻域可用性,对参考样点进行设置及滤波      pcCU->getPattern()->initAdiPattern( pcCU, uiPartOffset, uiInitTrDepth, m_piYuvExt, m_iYuvExtStride, m_iYuvExtHeight, bAboveAvail, bLeftAvail );            //===== determine set of modes to be tested (using prediction signal only) =====      Int numModesAvailable     = 35; //total number of Intra modes      Pel* piOrg         = pcOrgYuv ->getLumaAddr( uiPU, uiWidth );      Pel* piPred        = pcPredYuv->getLumaAddr( uiPU, uiWidth );      UInt uiStride      = pcPredYuv->getStride();      UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];      Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ]; //!< MPM数目      //!< g_aucIntraModeNumFast[] = {3, 8, 8, 3, 3, 3, 3}; 2x2, 4x4, 8x8, 16x16, 32x32, 64x64, 128x128      Bool doFastSearch = (numModesForFullRD != numModesAvailable); //!< 此处doFastSearch恒为真      if (doFastSearch)      {        assert(numModesForFullRD < numModesAvailable);          for( Int i=0; i < numModesForFullRD; i++ )         {          CandCostList[ i ] = MAX_DOUBLE;        }        CandNum = 0;                for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) //!< 遍历35种帧内预测模式        {          UInt uiMode = modeIdx;    //! 调用亮度帧内预测函数          predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, pcCU, bAboveAvail, bLeftAvail );                    // use hadamard transform here          UInt uiSad = m_pcRdCost->calcHAD( piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );                    UInt   iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );          Double cost      = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();                    CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );        }        #if FAST_UDI_USE_MPM // UDI---Unified Directional Intra        Int uiPreds[3] = {-1, -1, -1};        Int iMode = -1;  //!< 如果三个MPMs的前两个相同,则iMode=1,否则iMode=2        Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode ); //!< 获取亮度帧内预测模式的三个MPMs        if( iMode >= 0 ) //!< iMode = 1 or 2,因此,numCand会被重新赋值为iMode        {          numCand = iMode;        }                for( Int j=0; j < numCand; j++)          {          Bool mostProbableModeIncluded = false;          Int mostProbableMode = uiPreds[j]; //!< 取出MPM                    for( Int i=0; i < numModesForFullRD; i++)          {            mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); //!< 检查MPMs是否被uiRdModeList所包含          }          if (!mostProbableModeIncluded)  //!< 如果没被包含,则将该MPM包含到uiRdModeList里          {            uiRdModeList[numModesForFullRD++] = mostProbableMode;          }        }  #endif // FAST_UDI_USE_MPM      } //!< if (doFastSearch)      else      {        for( Int i=0; i < numModesForFullRD; i++)        {          uiRdModeList[i] = i;        }      }            //===== check modes (using r-d costs) =====   //! 帧内预测模式最佳值的确定主要有以下几个步骤:1. 对numModesForFullRD种预测模式进行遍历,即对每种模式计算出   //! 对应的RD costs,但该步骤中,并不会把一个CU的所有分割都算一遍,而仅仅对于至多深度为1的分割进行遍历,这么做   //! 大大减少了运算量,提高速度;2. 在第1个步骤中,会粗略得到最佳预测模式(在HM9.0中会得到包括次优解在内的两个   //! 预测模式),存储下来,以供第3步使用;3. 在第2步的基础上,对最佳(及次优)预测模式的所有分割模式遍历一遍,   //! 得到最终的最佳结果  #if HHI_RQT_INTRA_SPEEDUP_MOD      UInt   uiSecondBestMode  = MAX_UINT;      Double dSecondBestPUCost = MAX_DOUBLE;  #endif            UInt    uiBestPUMode  = 0; //!< 存放最佳预测模式      UInt    uiBestPUDistY = 0; //!< 存放最佳预测模式对应的亮度失真值      UInt    uiBestPUDistC = 0; //!< 存放最佳预测模式对应的色度失真值      Double  dBestPUCost   = MAX_DOUBLE;  //!< 存放最佳预测模式对应的总代价      for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) //!< 遍历存储在uiRdModeList里的模式      {        // set luma prediction mode        UInt uiOrgMode = uiRdModeList[uiMode];                pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );                // set context models        if( m_bUseSBACRD )        {          m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );        }                // determine residual for partition        UInt   uiPUDistY = 0;  //!< 存放当前预测模式对应的亮度失真值        UInt   uiPUDistC = 0;  //!< 存放当前预测模式对应的色度失真值        Double dPUCost   = 0.0; //!< 存放当前预测模式对应的代价  #if HHI_RQT_INTRA_SPEEDUP //! 注意这个函数倒数第二个参数,此时为true        xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, true, dPUCost );  #else        xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, dPUCost );  #endif                // check r-d cost        if( dPUCost < dBestPUCost ) //!< 更新最佳预测模式相关参数        {  #if HHI_RQT_INTRA_SPEEDUP_MOD          uiSecondBestMode  = uiBestPUMode;          dSecondBestPUCost = dBestPUCost;  #endif          uiBestPUMode  = uiOrgMode;          uiBestPUDistY = uiPUDistY;          uiBestPUDistC = uiPUDistC;          dBestPUCost   = dPUCost;                    xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );                    UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );          ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );        }  #if HHI_RQT_INTRA_SPEEDUP_MOD        else if( dPUCost < dSecondBestPUCost )        {          uiSecondBestMode  = uiOrgMode;          dSecondBestPUCost = dPUCost;        }  #endif      } // Mode loop        #if HHI_RQT_INTRA_SPEEDUP  #if HHI_RQT_INTRA_SPEEDUP_MOD      for( UInt ui =0; ui < 2; ++ui )  #endif      {  #if HHI_RQT_INTRA_SPEEDUP_MOD        UInt uiOrgMode   = ui ? uiSecondBestMode  : uiBestPUMode;        if( uiOrgMode == MAX_UINT )        {          break;        }  #else        UInt uiOrgMode = uiBestPUMode; //!< 设置模式为最佳预测模式  #endif                pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );                // set context models        if( m_bUseSBACRD )        {          m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );        }                // determine residual for partition        UInt   uiPUDistY = 0;        UInt   uiPUDistC = 0;        Double dPUCost   = 0.0;     //! 注意该函数倒数第二个参数,此时为false        xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost );                // check r-d cost        if( dPUCost < dBestPUCost )        {          uiBestPUMode  = uiOrgMode;          uiBestPUDistY = uiPUDistY;          uiBestPUDistC = uiPUDistC;          dBestPUCost   = dPUCost;                    xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );                    UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );          ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );          ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );        }      } // Mode loop  #endif            //--- update overall distortion ---      uiOverallDistY += uiBestPUDistY;      uiOverallDistC += uiBestPUDistC;            //--- update transform index and cbf ---      UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );      ::memcpy( pcCU->getTransformIdx()       + uiPartOffset, m_puhQTTempTrIdx,  uiQPartNum * sizeof( UChar ) );      ::memcpy( pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, m_puhQTTempCbf[0], uiQPartNum * sizeof( UChar ) );      ::memcpy( pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, m_puhQTTempCbf[1], uiQPartNum * sizeof( UChar ) );      ::memcpy( pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, m_puhQTTempCbf[2], uiQPartNum * sizeof( UChar ) );      ::memcpy( pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, m_puhQTTempTransformSkipFlag[0], uiQPartNum * sizeof( UChar ) );      ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, m_puhQTTempTransformSkipFlag[1], uiQPartNum * sizeof( UChar ) );      ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, m_puhQTTempTransformSkipFlag[2], uiQPartNum * sizeof( UChar ) );      //--- set reconstruction for next intra prediction blocks ---      if( uiPU != uiNumPU - 1 )      {        Bool bSkipChroma  = false;        Bool bChromaSame  = false;        UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> ( pcCU->getDepth(0) + uiInitTrDepth ) ] + 2;        if( !bLumaOnly && uiLog2TrSize == 2 )        {          assert( uiInitTrDepth  > 0 );          bSkipChroma  = ( uiPU != 0 );          bChromaSame  = true;        }                UInt    uiCompWidth   = pcCU->getWidth ( 0 ) >> uiInitTrDepth;        UInt    uiCompHeight  = pcCU->getHeight( 0 ) >> uiInitTrDepth;        UInt    uiZOrder      = pcCU->getZorderIdxInCU() + uiPartOffset;        Pel*    piDes         = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), uiZOrder );        UInt    uiDesStride   = pcCU->getPic()->getPicYuvRec()->getStride();        Pel*    piSrc         = pcRecoYuv->getLumaAddr( uiPartOffset );        UInt    uiSrcStride   = pcRecoYuv->getStride();        for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )        {          for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )          {            piDes[ uiX ] = piSrc[ uiX ];          }        }        if( !bLumaOnly && !bSkipChroma )        {          if( !bChromaSame )          {            uiCompWidth   >>= 1;            uiCompHeight  >>= 1;          }          piDes         = pcCU->getPic()->getPicYuvRec()->getCbAddr( pcCU->getAddr(), uiZOrder );          uiDesStride   = pcCU->getPic()->getPicYuvRec()->getCStride();          piSrc         = pcRecoYuv->getCbAddr( uiPartOffset );          uiSrcStride   = pcRecoYuv->getCStride();          for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )          {            for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )            {              piDes[ uiX ] = piSrc[ uiX ];            }          }          piDes         = pcCU->getPic()->getPicYuvRec()->getCrAddr( pcCU->getAddr(), uiZOrder );          piSrc         = pcRecoYuv->getCrAddr( uiPartOffset );          for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )          {            for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )            {              piDes[ uiX ] = piSrc[ uiX ];            }          }        }      }            //=== update PU data ====      pcCU->setLumaIntraDirSubParts     ( uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth );      pcCU->copyToPic                   ( uiDepth, uiPU, uiInitTrDepth );    } // PU loop            if( uiNumPU > 1 )    { // set Cbf for all blocks      UInt uiCombCbfY = 0;      UInt uiCombCbfU = 0;      UInt uiCombCbfV = 0;      UInt uiPartIdx  = 0;      for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts )      {        uiCombCbfY |= pcCU->getCbf( uiPartIdx, TEXT_LUMA,     1 );        uiCombCbfU |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_U, 1 );        uiCombCbfV |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_V, 1 );      }      for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ )      {        pcCU->getCbf( TEXT_LUMA     )[ uiOffs ] |= uiCombCbfY;        pcCU->getCbf( TEXT_CHROMA_U )[ uiOffs ] |= uiCombCbfU;        pcCU->getCbf( TEXT_CHROMA_V )[ uiOffs ] |= uiCombCbfV;      }    }        //===== reset context models =====    if(m_bUseSBACRD)    {      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);    }        //===== set distortion (rate and r-d costs are determined later) =====    ruiDistC                   = uiOverallDistC;    pcCU->getTotalDistortion() = uiOverallDistY + uiOverallDistC;  }  

原创粉丝点击