HM代码-码控(4)-关于参数更新

一、Void TEncRCPic中的更新函数
(1)updateAfterLCU()

Void TEncRCPic::updateAfterLCU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter )
{
  m_LCUs[LCUIdx].m_actualBits = bits;//对当前的LCU的实际编码比特、QP和lambda进行初始化
  m_LCUs[LCUIdx].m_QP         = QP;
  m_LCUs[LCUIdx].m_lambda     = lambda;

  m_LCULeft--;//当前LCU已经编码完成,未编码LCU数目=原数目-1
  m_bitsLeft   -= bits;//剩余比特=原剩余比特-当前LCU的实际编码比特
  m_pixelsLeft -= m_LCUs[LCUIdx].m_numberOfPixel;//剩余像素=原剩余像素-当前LCU的像素

  if ( !updateLCUParameter )//如果LCU的参数不需要更新,直接返回
  {
    return;
  }

  if ( !m_encRCSeq->getUseLCUSeparateModel() )//如果LCU的参数不是独立的,直接返回
  {
    return;
  }

  Double alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha;//新建alpha、beta变量并初始化
  Double beta  = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta;

  Int LCUActualBits   = m_LCUs[LCUIdx].m_actualBits;//获得当前LCU的实际编码比特
  Int LCUTotalPixels  = m_LCUs[LCUIdx].m_numberOfPixel;//获得当前LCU的实际像素数
  Double bpp         = ( Double )LCUActualBits/( Double )LCUTotalPixels;//获得当前LCU的实际Bpp
  Double calLambda   = alpha * pow( bpp, beta );//实际lambda
  Double inputLambda = m_LCUs[LCUIdx].m_lambda;//获得当前LCU的lambda,即原来(old)的lambda

  if( inputLambda < 0.01 || calLambda < 0.01 || bpp < 0.0001 )//三种情况有一种出现
  {
    alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );//对alpha和beta更新
    beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );

    alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );//对alpha进行修正
	//const Double g_RCAlphaMinValue = 0.05;const Double g_RCAlphaMaxValue = 500.0;
    beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );//对beta进行修正
	//const Double g_RCBetaMinValue  = -3.0;const Double g_RCBetaMaxValue  = -0.1;

    TRCParameter rcPara;
    rcPara.m_alpha = alpha;
    rcPara.m_beta  = beta;
    m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara );//传参返回

    return;
  }

  calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );//对lambda进行修正
  alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
  //P360页更新公式

  Double lnbpp = log( bpp );
  lnbpp = Clip3( -5.0, -0.1, lnbpp );
  beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;
  //P360页更新公式

  alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha ); //对alpha进行修正
  	//const Double g_RCAlphaMinValue = 0.05;const Double g_RCAlphaMaxValue = 500.0;
  beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );//对beta进行修正
	//const Double g_RCBetaMinValue  = -3.0;const Double g_RCBetaMaxValue  = -0.1;

  TRCParameter rcPara;
  rcPara.m_alpha = alpha;
  rcPara.m_beta  = beta;
  m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara );//传参返回

}

①其中调用了m_encRCSeq->getAlphaUpdate()来获得alpha的更新值

  Double getAlphaUpdate()               { return m_alphaUpdate; }

②其中调用了m_encRCSeq->getBetaUpdate()来获得beta的更新值

  Double getBetaUpdate()                { return m_betaUpdate; }

(2)updateAfterPicture()

Void TEncRCPic::updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, SliceType eSliceType)
{
  m_picActualHeaderBits = actualHeaderBits;//新建并初始化该图像的头信息比特和实际编码比特
  m_picActualBits       = actualTotalBits;
  if ( averageQP > 0.0 )//若传入的QP>0,
  {
    m_picQP             = Int( averageQP + 0.5 );//QP=QP+0.5
  }
  else//否则
  {
    m_picQP             = g_RCInvalidQPValue;//QP=-99
  }
  m_picLambda           = averageLambda;//新建该帧的lambda并初始化

  Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;//获得原来的alpha个beta的值
  Double beta  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;

  if (eSliceType == I_SLICE)//如果是I帧,利用update函数进行更新
  {
    updateAlphaBetaIntra(&alpha, &beta);
  }
  else//如果不是I帧
  {
    // update parameters
    Double picActualBits = ( Double )m_picActualBits;//获得图像实际编码比特、Bpp
    Double picActualBpp  = picActualBits/(Double)m_numberOfPixel;
    Double calLambda     = alpha * pow( picActualBpp, beta );//实际的lambda
    Double inputLambda   = m_picLambda;//old 的lambda

    if ( inputLambda < 0.01 || calLambda < 0.01 || picActualBpp < 0.0001 )//三种情况有一种出现
    {
      alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );//对alpha和beta更新
      beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );

      alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );//对alpha进行修正
      beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );//对beta进行修正

      TRCParameter rcPara;
      rcPara.m_alpha = alpha;
      rcPara.m_beta  = beta;
      m_encRCSeq->setPicPara( m_frameLevel, rcPara );//传参返回

      return;
    }

    calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );//对实际的lambda进行修正
    alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
	 //P360页更新公式
    Double lnbpp = log( picActualBpp );
    lnbpp = Clip3( -5.0, -0.1, lnbpp );//获得实际的Bpp并修正

    beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;
	  //P360页更新公式
    alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );//对alpha进行修正
    beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );//对beta进行修正
  }

  TRCParameter rcPara;
  rcPara.m_alpha = alpha;
  rcPara.m_beta  = beta;

  m_encRCSeq->setPicPara( m_frameLevel, rcPara );//传参返回

  if ( m_frameLevel == 1 )//如果framelevel==1
  {
    Double currLambda = Clip3( 0.1, 10000.0, m_picLambda );//获得当前lambda并修正
    Double updateLastLambda = g_RCWeightHistoryLambda * m_encRCSeq->getLastLambda() + g_RCWeightCurrentLambda * currLambda;
	//利用该公式获得lastlambda,并传递更新
    m_encRCSeq->setLastLambda( updateLastLambda );
  }
}

①其中调用了updateAlphaBetaIntra(&alpha, &beta);对帧内的alpha和beta进行更新

Void TEncRCPic::updateAlphaBetaIntra(Double *alpha, Double *beta)
{
  Double lnbpp = log(pow(m_totalCostIntra / (Double)m_numberOfPixel, BETA1));//计算lnBpp
  Double diffLambda = (*beta)*(log((Double)m_picActualBits)-log((Double)m_targetBits));//计算diffLambda

  diffLambda = Clip3(-0.125, 0.125, 0.25*diffLambda);//对diffLambda进行修正
  *alpha    =  (*alpha) * exp(diffLambda);//计算更新后的alpha和beta值
  *beta     =  (*beta) + diffLambda / lnbpp;
}

二、TEncRCGOP更新函数

Void TEncRCGOP::updateAfterPicture( Int bitsCost )
{
  m_bitsLeft -= bitsCost;
  m_picLeft--;//更新剩余比特和剩余图片数
}

三、TEncRCSeq更新函数

Void TEncRCSeq::updateAfterPic ( Int bits )
{
  m_bitsLeft -= bits;//更新剩余比特和帧数
  m_framesLeft--;
}

四、何处调用?
1、在TEncSlice.cpp中的CompressSlice()中

    if ( m_pcCfg->getUseRateCtrl() )
    {
      Int actualQP        = g_RCInvalidQPValue;//=-999
      Double actualLambda = m_pcRdCost->getLambda();//新建变量并初始化
      Int actualBits      = pcCU->getTotalBits();//获得实际编码比特
      Int numberOfEffectivePixels    = 0;//新建有影响的像素点个数
      for ( Int idx = 0; idx < rpcPic->getNumPartInCU(); idx++ )//遍历整个帧的所有CU以4x4为单位
      {
        if ( pcCU->getPredictionMode( idx ) != NUMBER_OF_PREDICTION_MODES && ( !pcCU->isSkipped( idx ) ) )
			//CU的预测模式是帧内或者帧间并且不是skip模式
        {
          numberOfEffectivePixels = numberOfEffectivePixels + 16;//有用像素点个数16++
          break;
        }
      }

      if ( numberOfEffectivePixels == 0 )//如果所有像素点均为无用
      {
        actualQP = g_RCInvalidQPValue;//=-999
      }
      else//否则
      {
        actualQP = pcCU->getQP( 0 );//实际像素选取第一个QP值
      }
      m_pcRdCost->setLambda(oldLambda);
	  // Void setLambda(Double dLambda) { m_dLambda = dLambda;}对m_dLambda进行设置
      m_pcRateCtrl->getRCPic()->updateAfterLCU( m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,
        pcCU->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );//LCU编码完成后进行参数更新
    }

    m_uiPicTotalBits += pcCU->getTotalBits();//对帧的编码总比特更新
    m_dPicRdCost     += pcCU->getTotalCost();//对帧的率失真更新
    m_uiPicDist      += pcCU->getTotalDistortion();//对帧的失真更新
  }

2、在TEncGOP.cpp中的CompressGOP()中

 if ( m_pcCfg->getUseRateCtrl() )
    {
      Double avgQP     = m_pcRateCtrl->getRCPic()->calAverageQP();//获取当前图片的平均QP
      Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();//获取当前图片的平均lambda
      if ( avgLambda < 0.0 )
      {
        avgLambda = lambda;//对平均lambda进行修正
      }

      m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());
	  //对当前帧编码完成后,帧层的参数更新
      m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() );
	  //把当前帧加入到已经编码完成的帧链表

      m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits );
	  //对序列层进行参数更新
      if ( pcSlice->getSliceType() != I_SLICE )//判断当前帧是否为I帧
      {
        m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );//若不是I帧,传入实际编码比特数进行GOP层的参数更新
      }
      else    // for intra picture, the estimated bits are used to update the current status in the GOP
      {
        m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );//若为I帧,传入估计比特数进行GOP层的参数更新
      }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值