HEVC学习(十六) —— SAO函数解析之四

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

 

 

  1. Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
  2. {
  3. Int typeIdx;
  4. Int64 estDist;
  5. Int classIdx;
  6. Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)-8); //!< 0 for 8bit-depth
  7. Int64 bestDist;
  8. SaoLcuParam* saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
  9. SaoLcuParam* saoLcuParamNeighbor = NULL;
  10. resetSaoUnit(saoLcuParam);
  11. resetSaoUnit(&compSaoParam[0]); //!< 左邻块的SAO参数
  12. resetSaoUnit(&compSaoParam[1]); //!< 上邻块的SAO参数
  13. Double dCostPartBest = MAX_DOUBLE;
  14. Double bestRDCostTableBo = MAX_DOUBLE;
  15. Int bestClassTableBo = 0;
  16. Int currentDistortionTableBo[MAX_NUM_SAO_CLASS];
  17. Double currentRdCostTableBo[MAX_NUM_SAO_CLASS];
  18. SaoLcuParam saoLcuParamRdo;
  19. Double estRate = 0;
  20. resetSaoUnit(&saoLcuParamRdo);
  21. m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
  22. m_pcRDGoOnSbacCoder->resetBits();
  23. m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
  24. dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ;
  25. copySaoUnit(saoLcuParam, &saoLcuParamRdo );
  26. bestDist = 0;
  27. for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++) //!< 遍历所有的滤波类型
  28. {
  29. estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);//!< 得到当前滤波类型的失真值
  30. if( typeIdx == SAO_BO )
  31. {
  32. // Estimate Best Position
  33. Double currentRDCost = 0.0;
  34. for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
  35. {
  36. currentRDCost = 0.0;
  37. for(UInt uj = i; uj < i+SAO_BO_LEN; uj++) //!< 依次以4个band为单位进行RDcost计算
  38. {
  39. currentRDCost += currentRdCostTableBo[uj];
  40. }
  41. if( currentRDCost < bestRDCostTableBo) //!< 更新最佳值
  42. {
  43. bestRDCostTableBo = currentRDCost;
  44. bestClassTableBo = i;
  45. }
  46. }
  47. // Re code all Offsets
  48. // Code Center
  49. estDist = 0;
  50. for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++)
  51. {
  52. estDist += currentDistortionTableBo[classIdx];
  53. }
  54. } //!< if( typeIdx == SAO_BO )
  55. resetSaoUnit(&saoLcuParamRdo);
  56. saoLcuParamRdo.length = m_iNumClass[typeIdx];
  57. saoLcuParamRdo.typeIdx = typeIdx;
  58. saoLcuParamRdo.mergeLeftFlag = 0;
  59. saoLcuParamRdo.mergeUpFlag = 0;
  60. saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
  61. for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
  62. {
  63. saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
  64. }
  65. m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
  66. m_pcRDGoOnSbacCoder->resetBits();
  67. m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
  68. estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
  69. m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);
  70. if(m_dCost[yCbCr][typeIdx] < dCostPartBest) //!< 更新最佳值
  71. {
  72. dCostPartBest = m_dCost[yCbCr][typeIdx];
  73. copySaoUnit(saoLcuParam, &saoLcuParamRdo );
  74. bestDist = estDist;
  75. }
  76. } //!< for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
  77. compDistortion[0] += ((Double)bestDist/lambda);
  78. m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
  79. m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
  80. m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );
  81. // merge left or merge up
  82. for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++)
  83. {
  84. saoLcuParamNeighbor = NULL;
  85. if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0) //!< 左邻块可用
  86. {
  87. saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]); //!< 取左邻块的SAO参数
  88. }
  89. else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1) //!< 上邻块可用
  90. {
  91. saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]); //!< 取上邻块的SAO参数
  92. }
  93. if (saoLcuParamNeighbor!=NULL)
  94. {
  95. estDist = 0;
  96. typeIdx = saoLcuParamNeighbor->typeIdx;
  97. if (typeIdx>=0) //!< typeIdx为有效的
  98. {
  99. Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
  100. Int merge_iOffset;
  101. for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
  102. {
  103. merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
  104. estDist += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1], shift);
  105. }
  106. }
  107. else
  108. {
  109. estDist = 0;
  110. }
  111. copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
  112. compSaoParam[idxNeighbor].mergeUpFlag = idxNeighbor;
  113. compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;
  114. compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
  115. }
  116. }
  117. }
Void TEncSampleAdaptiveOffset::saoComponentParamDist(Int allowMergeLeft, Int allowMergeUp, SAOParam *saoParam, Int addr, Int addrUp, Int addrLeft, Int yCbCr, Double lambda, SaoLcuParam *compSaoParam, Double *compDistortion)
{
  Int typeIdx;

  Int64 estDist;
  Int classIdx;
  Int shift = 2 * DISTORTION_PRECISION_ADJUSTMENT(((yCbCr==0)?g_bitDepthY:g_bitDepthC)-8); //!< 0 for 8bit-depth
  Int64 bestDist;

  SaoLcuParam*  saoLcuParam = &(saoParam->saoLcuParam[yCbCr][addr]);
  SaoLcuParam*  saoLcuParamNeighbor = NULL; 

  resetSaoUnit(saoLcuParam);
  resetSaoUnit(&compSaoParam[0]); //!< 左邻块的SAO参数
  resetSaoUnit(&compSaoParam[1]); //!< 上邻块的SAO参数


  Double dCostPartBest = MAX_DOUBLE;

  Double  bestRDCostTableBo = MAX_DOUBLE;
  Int     bestClassTableBo    = 0;
  Int     currentDistortionTableBo[MAX_NUM_SAO_CLASS];
  Double  currentRdCostTableBo[MAX_NUM_SAO_CLASS];


  SaoLcuParam   saoLcuParamRdo;   
  Double   estRate = 0;

  resetSaoUnit(&saoLcuParamRdo);

  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
  m_pcRDGoOnSbacCoder->resetBits();
 m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);
  
  dCostPartBest = m_pcEntropyCoder->getNumberOfWrittenBits()*lambda ; 
  copySaoUnit(saoLcuParam, &saoLcuParamRdo );
  bestDist = 0;
  


  for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++) //!< 遍历所有的滤波类型
  {
    estDist = estSaoTypeDist(yCbCr, typeIdx, shift, lambda, currentDistortionTableBo, currentRdCostTableBo);//!< 得到当前滤波类型的失真值

    if( typeIdx == SAO_BO )
    {
      // Estimate Best Position
      Double currentRDCost = 0.0;

      for(Int i=0; i< SAO_MAX_BO_CLASSES -SAO_BO_LEN +1; i++)
      {
        currentRDCost = 0.0;
        for(UInt uj = i; uj < i+SAO_BO_LEN; uj++) //!< 依次以4个band为单位进行RDcost计算
        {
          currentRDCost += currentRdCostTableBo[uj];
        }

        if( currentRDCost < bestRDCostTableBo) //!< 更新最佳值
        {
          bestRDCostTableBo = currentRDCost;
          bestClassTableBo  = i;
        }
      }

      // Re code all Offsets
      // Code Center
      estDist = 0;
      for(classIdx = bestClassTableBo; classIdx < bestClassTableBo+SAO_BO_LEN; classIdx++) 
      {
        estDist += currentDistortionTableBo[classIdx];
      }
    } //!< if( typeIdx == SAO_BO )
    resetSaoUnit(&saoLcuParamRdo);
    saoLcuParamRdo.length = m_iNumClass[typeIdx];
    saoLcuParamRdo.typeIdx = typeIdx;
    saoLcuParamRdo.mergeLeftFlag = 0;
    saoLcuParamRdo.mergeUpFlag   = 0;
    saoLcuParamRdo.subTypeIdx = (typeIdx == SAO_BO) ? bestClassTableBo : 0;
    for (classIdx = 0; classIdx < saoLcuParamRdo.length; classIdx++)
    {
      saoLcuParamRdo.offset[classIdx] = (Int)m_iOffset[yCbCr][typeIdx][classIdx+saoLcuParamRdo.subTypeIdx+1];
    }
    m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
    m_pcRDGoOnSbacCoder->resetBits();
    m_pcEntropyCoder->encodeSaoOffset(&saoLcuParamRdo, yCbCr);

    estRate = m_pcEntropyCoder->getNumberOfWrittenBits();
    m_dCost[yCbCr][typeIdx] = (Double)((Double)estDist + lambda * (Double) estRate);

    if(m_dCost[yCbCr][typeIdx] < dCostPartBest) //!< 更新最佳值
    {
      dCostPartBest = m_dCost[yCbCr][typeIdx];
      copySaoUnit(saoLcuParam, &saoLcuParamRdo );
      bestDist = estDist;       
    }
  } //!< for (typeIdx=0; typeIdx<MAX_NUM_SAO_TYPE; typeIdx++)
  compDistortion[0] += ((Double)bestDist/lambda);
  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[0][CI_TEMP_BEST]);
 m_pcEntropyCoder->encodeSaoOffset(saoLcuParam, yCbCr);
  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_TEMP_BEST] );


  // merge left or merge up

  for (Int idxNeighbor=0;idxNeighbor<2;idxNeighbor++) 
  {
    saoLcuParamNeighbor = NULL;
    if (allowMergeLeft && addrLeft>=0 && idxNeighbor ==0) //!< 左邻块可用
    {
      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrLeft]); //!< 取左邻块的SAO参数
    }
    else if (allowMergeUp && addrUp>=0 && idxNeighbor ==1) //!< 上邻块可用
    {
      saoLcuParamNeighbor = &(saoParam->saoLcuParam[yCbCr][addrUp]); //!< 取上邻块的SAO参数
    }
    if (saoLcuParamNeighbor!=NULL)
    {
      estDist = 0;
      typeIdx = saoLcuParamNeighbor->typeIdx;
      if (typeIdx>=0) //!< typeIdx为有效的 
      {
        Int mergeBandPosition = (typeIdx == SAO_BO)?saoLcuParamNeighbor->subTypeIdx:0;
        Int   merge_iOffset;
        for(classIdx = 0; classIdx < m_iNumClass[typeIdx]; classIdx++)
        {
          merge_iOffset = saoLcuParamNeighbor->offset[classIdx];
          estDist   += estSaoDist(m_iCount [yCbCr][typeIdx][classIdx+mergeBandPosition+1], merge_iOffset, m_iOffsetOrg[yCbCr][typeIdx][classIdx+mergeBandPosition+1],  shift);
        }
      }
      else
      {
        estDist = 0;
      }

      copySaoUnit(&compSaoParam[idxNeighbor], saoLcuParamNeighbor );
      compSaoParam[idxNeighbor].mergeUpFlag   = idxNeighbor;
      compSaoParam[idxNeighbor].mergeLeftFlag = !idxNeighbor;

      compDistortion[idxNeighbor+1] += ((Double)estDist/lambda);
    } 
  } 
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值