VTM碼率控制——代碼學習四

碼率分配參數更新

αnew=αold+δα×(lnαreallnαcomp)×αold \alpha_{new} = \alpha_{old} + \delta_{ \alpha } \times (\ln\alpha_{real}-\ln\alpha_{comp} ) \times \alpha_{old} βnew=βold+δβ×(lnαreallnαcomp)×lnbppreal\beta_{new} = \beta_{old} + \delta_{ \beta } \times (\ln\alpha_{real}-\ln\alpha_{comp} ) \times \ln{bpp_{real}}

幀之後的更新

void EncRCPic::updateAfterPicture( int actualHeaderBits, int actualTotalBits, double averageQP, double averageLambda, bool isIRAP)
{
  m_picActualHeaderBits = actualHeaderBits;
  m_picActualBits       = actualTotalBits;
  if ( averageQP > 0.0 )
  {
    m_picQP             = int( averageQP + 0.5 );
  }
  else
  {
    m_picQP             = g_RCInvalidQPValue;
  }
  m_picLambda           = averageLambda;

  double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
  double beta  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
  double skipRatio = 0;
  int numOfSkipPixel = 0;
  for (int LCUIdx = 0; LCUIdx < m_numberOfLCU; LCUIdx++)
  {
    numOfSkipPixel += int(m_encRCSeq->getLCUPara(m_frameLevel, LCUIdx).m_skipRatio*m_LCUs[LCUIdx].m_numberOfPixel);
  }
  skipRatio = (double)numOfSkipPixel / (double)m_numberOfPixel;

  if (isIRAP)
  {
    updateAlphaBetaIntra(&alpha, &beta);
  }
  else
  {
    // update parameters
    double picActualBits = ( double )m_picActualBits;
    double picActualBpp = picActualBits / (double)m_validPixelsInPic;
    double calLambda     = alpha * pow( picActualBpp, beta );
    double inputLambda   = m_picLambda;

    if ( inputLambda < 0.01 || calLambda < 0.01 || picActualBpp < 0.0001 )
    {
      alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );
      beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );

      alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
      beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );

      TRCParameter rcPara;
      rcPara.m_alpha = alpha;
      rcPara.m_beta  = beta;
      rcPara.m_skipRatio = skipRatio;
      double avgMSE = getPicMSE();
      double updatedK = picActualBpp * averageLambda / avgMSE;
      double updatedC = avgMSE / pow(picActualBpp, -updatedK);

      if (m_frameLevel > 0)  //only use for level > 0
      {
        rcPara.m_alpha = updatedC * updatedK;
        rcPara.m_beta = -updatedK - 1.0;
      }

      rcPara.m_validPix = m_validPixelsInPic;

      if (m_validPixelsInPic > 0)
      {
        m_encRCSeq->setPicPara(m_frameLevel, rcPara);
      }

      return;
    }

    calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );
    alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
    double lnbpp = log( picActualBpp );
    lnbpp = Clip3( -5.0, -0.1, lnbpp );

    beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;

    alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
    beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );
  }

  TRCParameter rcPara;
  rcPara.m_alpha = alpha;
  rcPara.m_beta  = beta;
  rcPara.m_skipRatio = skipRatio;
  double picActualBpp = (double)m_picActualBits / (double)m_validPixelsInPic;

  double avgMSE = getPicMSE();
  double updatedK = picActualBpp * averageLambda / avgMSE;
  double updatedC = avgMSE / pow(picActualBpp, -updatedK);
  if (m_frameLevel > 0)  //only use for level > 0
  {
    rcPara.m_alpha = updatedC * updatedK;
    rcPara.m_beta = -updatedK - 1.0;
  }

  rcPara.m_validPix = m_validPixelsInPic;

  if (m_validPixelsInPic > 0)
  {
    m_encRCSeq->setPicPara(m_frameLevel, rcPara);
  }

  if ( m_frameLevel == 1 )
  {
    double currLambda = Clip3( 0.1, 10000.0, m_picLambda );
    double updateLastLambda = g_RCWeightHistoryLambda * m_encRCSeq->getLastLambda() + g_RCWeightCurrentLambda * currLambda;
    m_encRCSeq->setLastLambda( updateLastLambda );
  }
}

LCU後的更新

void EncRCPic::updateAfterCTU(int LCUIdx, int bits, int QP, double lambda, double skipRatio, bool updateLCUParameter)
{
  m_LCUs[LCUIdx].m_actualBits = bits;
  m_LCUs[LCUIdx].m_QP         = QP;
  m_LCUs[LCUIdx].m_lambda     = lambda;
  m_LCUs[LCUIdx].m_actualSSE  = m_LCUs[LCUIdx].m_actualMSE * m_LCUs[LCUIdx].m_numberOfPixel;

  m_LCULeft--;
  m_bitsLeft   -= bits;
  m_pixelsLeft -= m_LCUs[LCUIdx].m_numberOfPixel;

  if ( !updateLCUParameter )
  {
    return;
  }

  if ( !m_encRCSeq->getUseLCUSeparateModel() )
  {
    return;
  }

  double alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha;
  double beta  = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta;

  int LCUActualBits   = m_LCUs[LCUIdx].m_actualBits;
  int LCUTotalPixels  = m_LCUs[LCUIdx].m_numberOfPixel;
  double bpp         = ( double )LCUActualBits/( double )LCUTotalPixels;
  double calLambda   = alpha * pow( bpp, beta );
  double inputLambda = m_LCUs[LCUIdx].m_lambda;

  if( inputLambda < 0.01 || calLambda < 0.01 || bpp < 0.0001 )
  {
    alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );
    beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );

    alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
    beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );

    TRCParameter rcPara;
    rcPara.m_alpha = alpha;
    rcPara.m_beta  = beta;
    rcPara.m_skipRatio = skipRatio;
    if (QP == g_RCInvalidQPValue && m_encRCSeq->getAdaptiveBits() == 1)
    {
      rcPara.m_validPix = 0;
    }
    else
    {
      rcPara.m_validPix = LCUTotalPixels;
    }

    double MSE = m_LCUs[LCUIdx].m_actualMSE;
    double updatedK = bpp * inputLambda / MSE;
    double updatedC = MSE / pow(bpp, -updatedK);
    rcPara.m_alpha = updatedC * updatedK;
    rcPara.m_beta = -updatedK - 1.0;

    if (bpp > 0 && updatedK > 0.0001)
    {
      m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
    }
    else
    {
      rcPara.m_alpha = Clip3(0.0001, g_RCAlphaMaxValue, rcPara.m_alpha);
      m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
    }

    return;
  }

  calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );
  alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
  double lnbpp = log( bpp );
  lnbpp = Clip3( -5.0, -0.1, lnbpp );
  beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;

  alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
  beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );

  TRCParameter rcPara;
  rcPara.m_alpha = alpha;
  rcPara.m_beta  = beta;
  rcPara.m_skipRatio = skipRatio;
  if (QP == g_RCInvalidQPValue && m_encRCSeq->getAdaptiveBits() == 1)
  {
    rcPara.m_validPix = 0;
  }
  else
  {
    rcPara.m_validPix = LCUTotalPixels;
  }

  double MSE = m_LCUs[LCUIdx].m_actualMSE;
  double updatedK = bpp * inputLambda / MSE;
  double updatedC = MSE / pow(bpp, -updatedK);
  rcPara.m_alpha = updatedC * updatedK;
  rcPara.m_beta = -updatedK - 1.0;

  if (bpp > 0 && updatedK > 0.0001)
  {
    m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
  }
  else
  {
    rcPara.m_alpha = Clip3(0.0001, g_RCAlphaMaxValue, rcPara.m_alpha);
    m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
  }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章