HM代码-码控(1)-乱七八糟的初始化

参考大神传送门:
https://blog.csdn.net/NB_vol_1/article/details/55096464
https://blog.csdn.net/s1314_JHC/article/details/78113416
https://blog.csdn.net/HEVC_CJL/article/details/11115721
一、m_cRateCtrl.init()

Void TEncRateCtrl::init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry  GOPList[MAX_GOP] )
{
  destroy();

  Bool isLowdelay = true;//lowdelay的判断标志位
  for ( Int i=0; i<GOPSize-1; i++ )//GOPList[MAX_GOP]GOP列表,MAX_GOP是GOP分层结构大小的最大值,为64
  {
    if ( GOPList[i].m_POC > GOPList[i+1].m_POC )//.m_POC是GOPEntry结构体的成员。如果编码顺序对应的播放顺序大于下一帧的播放顺序,就不是lowdelay模式
    {
      isLowdelay = false;
      break;
    }
  }

  Int numberOfLevel = 1;
  Int adaptiveBit = 0;
  if ( keepHierBits > 0 )//分层结构
  {
    numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1;
  }
  if ( !isLowdelay && GOPSize == 8 )
  {
    numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1;
  }
  numberOfLevel++;    // intra picture帧内图片
  numberOfLevel++;    // non-reference picture非参考图片


  Int* bitsRatio;
  bitsRatio = new Int[ GOPSize ];//新建数组,指向第一个数据
  for ( Int i=0; i<GOPSize; i++ )
  {
    bitsRatio[i] = 10;
    if ( !GOPList[i].m_refPic )//如果是参考图片
    {
      bitsRatio[i] = 2;
    }
  }

  if ( keepHierBits > 0 )
  {
    Double bpp = (Double)( targetBitrate / (Double)( frameRate*picWidth*picHeight ) );//计算bpp
    if ( GOPSize == 4 && isLowdelay )//如果GOPSize==4并且是lowdelay模式,按照358页表12.1进行权值分配
    {
      if ( bpp > 0.2 )
      {
        bitsRatio[0] = 2;
        bitsRatio[1] = 3;
        bitsRatio[2] = 2;
        bitsRatio[3] = 6;
      }
      else if( bpp > 0.1 )
      {
        bitsRatio[0] = 2;
        bitsRatio[1] = 3;
        bitsRatio[2] = 2;
        bitsRatio[3] = 10;
      }
      else if ( bpp > 0.05 )
      {
        bitsRatio[0] = 2;
        bitsRatio[1] = 3;
        bitsRatio[2] = 2;
        bitsRatio[3] = 12;
      }
      else
      {
        bitsRatio[0] = 2;
        bitsRatio[1] = 3;
        bitsRatio[2] = 2;
        bitsRatio[3] = 14;
      }

      if ( keepHierBits == 2 )//若keepHierBits==2,adaptiveBit赋值为1
      {
        adaptiveBit = 1;
      }
    }
    else if ( GOPSize == 8 && !isLowdelay )//如果GOPSize==8并且不是lowdelay模式,按照358页表12.2进行权值分配
    {
      if ( bpp > 0.2 )
      {
        bitsRatio[0] = 15;
        bitsRatio[1] = 5;
        bitsRatio[2] = 4;
        bitsRatio[3] = 1;
        bitsRatio[4] = 1;
        bitsRatio[5] = 4;
        bitsRatio[6] = 1;
        bitsRatio[7] = 1;
      }
      else if ( bpp > 0.1 )
      {
        bitsRatio[0] = 20;
        bitsRatio[1] = 6;
        bitsRatio[2] = 4;
        bitsRatio[3] = 1;
        bitsRatio[4] = 1;
        bitsRatio[5] = 4;
        bitsRatio[6] = 1;
        bitsRatio[7] = 1;
      }
      else if ( bpp > 0.05 )
      {
        bitsRatio[0] = 25;
        bitsRatio[1] = 7;
        bitsRatio[2] = 4;
        bitsRatio[3] = 1;
        bitsRatio[4] = 1;
        bitsRatio[5] = 4;
        bitsRatio[6] = 1;
        bitsRatio[7] = 1;
      }
      else
      {
        bitsRatio[0] = 30;
        bitsRatio[1] = 8;
        bitsRatio[2] = 4;
        bitsRatio[3] = 1;
        bitsRatio[4] = 1;
        bitsRatio[5] = 4;
        bitsRatio[6] = 1;
        bitsRatio[7] = 1;
      }

      if ( keepHierBits == 2 )//若keepHierBits==2,adaptiveBit赋值为1
      {
        adaptiveBit = 2;
      }
    }
    else
    {
      printf( "\n hierarchical bit allocation is not support for the specified coding structure currently.\n" );
    }
  }

  Int* GOPID2Level = new Int[ GOPSize ];//根据在GOP中的id确定所属的分层
  for ( Int i=0; i<GOPSize; i++ )
  {
    GOPID2Level[i] = 1;
    if ( !GOPList[i].m_refPic )
    {
      GOPID2Level[i] = 2;
    }
  }

  if ( keepHierBits > 0 )
  {
    if ( GOPSize == 4 && isLowdelay )
    {
      GOPID2Level[0] = 3;
      GOPID2Level[1] = 2;
      GOPID2Level[2] = 3;
      GOPID2Level[3] = 1;
    }
    else if ( GOPSize == 8 && !isLowdelay )
    {
      GOPID2Level[0] = 1;
      GOPID2Level[1] = 2;
      GOPID2Level[2] = 3;
      GOPID2Level[3] = 4;
      GOPID2Level[4] = 4;
      GOPID2Level[5] = 3;
      GOPID2Level[6] = 4;
      GOPID2Level[7] = 4;
    }
  }

  if ( !isLowdelay && GOPSize == 8 )
  {
    GOPID2Level[0] = 1;
    GOPID2Level[1] = 2;
    GOPID2Level[2] = 3;
    GOPID2Level[3] = 4;
    GOPID2Level[4] = 4;
    GOPID2Level[5] = 3;
    GOPID2Level[6] = 4;
    GOPID2Level[7] = 4;
  }

  m_encRCSeq = new TEncRCSeq;
  m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit );
  //!< 序列级RC参数的初始化
  m_encRCSeq->initBitsRatio( bitsRatio );//!< 每幅picture的权值
  m_encRCSeq->initGOPID2Level( GOPID2Level );//设置GOP的Id到Level的映射
  m_encRCSeq->initPicPara();//帧级别的alpha,beta的参数设置
  if ( useLCUSeparateModel )
  {
    m_encRCSeq->initLCUPara();//LCU级别的alpha,beta的参数设置
  }

  delete[] bitsRatio;
  delete[] GOPID2Level;
}

在这里插入图片描述
其中有两个比较重要的函数
(1)m_encRCSeq->create()** 序列级RC参数的初始化**

Void TEncRCSeq::create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit )
{
  destroy();
  m_totalFrames         = totalFrames;
  m_targetRate          = targetBitrate;
  m_frameRate           = frameRate;
  m_GOPSize             = GOPSize;
  m_picWidth            = picWidth;
  m_picHeight           = picHeight;
  m_LCUWidth            = LCUWidth;
  m_LCUHeight           = LCUHeight;
  m_numberOfLevel       = numberOfLevel;
  m_useLCUSeparateModel = useLCUSeparateModel;

  m_numberOfPixel   = m_picWidth * m_picHeight;
  m_targetBits      = (Int64)m_totalFrames * (Int64)m_targetRate / (Int64)m_frameRate;!< 序列总码率(输出码流总大小)
  m_seqTargetBpp = (Double)m_targetRate / (Double)m_frameRate / (Double)m_numberOfPixel;//每个像素被分配的目标比特
  
  //!< m_alphaUpdata和m_betaUpdate这两个变量用于在接下来更新lamda的参数值
  if ( m_seqTargetBpp < 0.03 )
  {
    m_alphaUpdate = 0.01;
    m_betaUpdate  = 0.005;
  }
  else if ( m_seqTargetBpp < 0.08 )
  {
    m_alphaUpdate = 0.05;
    m_betaUpdate  = 0.025;
  }
  else if ( m_seqTargetBpp < 0.2 )
  {
    m_alphaUpdate = 0.1;
    m_betaUpdate  = 0.05;
  }
  else if ( m_seqTargetBpp < 0.5 )
  {
    m_alphaUpdate = 0.2;
    m_betaUpdate  = 0.1;
  }
  else
  {
    m_alphaUpdate = 0.4;
    m_betaUpdate  = 0.2;
  }

  m_averageBits     = (Int)(m_targetBits / totalFrames);//!< 平均每帧占用的比特数
  Int picWidthInBU  = ( m_picWidth  % m_LCUWidth  ) == 0 ? m_picWidth  / m_LCUWidth  : m_picWidth  / m_LCUWidth  + 1;
  Int picHeightInBU = ( m_picHeight % m_LCUHeight ) == 0 ? m_picHeight / m_LCUHeight : m_picHeight / m_LCUHeight + 1;
  m_numberOfLCU     = picWidthInBU * picHeightInBU;//!< 一帧picture中包含的LCU数目

  m_bitsRatio   = new Int[m_GOPSize];
  for ( Int i=0; i<m_GOPSize; i++ )
  {
    m_bitsRatio[i] = 1;
  }

  m_GOPID2Level = new Int[m_GOPSize];
  for ( Int i=0; i<m_GOPSize; i++ )
  {
    m_GOPID2Level[i] = 1;
  }

  m_picPara = new TRCParameter[m_numberOfLevel];//TRCParameter结构体中包含.m_alpha和.m_beta两个成员
  for ( Int i=0; i<m_numberOfLevel; i++ )//对参数进行初始化
  {
    m_picPara[i].m_alpha = 0.0;
    m_picPara[i].m_beta  = 0.0;
  }

  if ( m_useLCUSeparateModel )//!< 是否每个LCU的alpha和beta都有各自的值
  {
    m_LCUPara = new TRCParameter*[m_numberOfLevel];//对参数进行初始化
    for ( Int i=0; i<m_numberOfLevel; i++ )
    {
      m_LCUPara[i] = new TRCParameter[m_numberOfLCU];
      for ( Int j=0; j<m_numberOfLCU; j++)
      {
        m_LCUPara[i][j].m_alpha = 0.0;
        m_LCUPara[i][j].m_beta  = 0.0;
      }
    }
  }

  m_framesLeft = m_totalFrames;//!< 剩余的待编码帧数
  m_bitsLeft   = m_targetBits;//!< 剩余可用的比特数
  m_adaptiveBit = adaptiveBit;
  m_lastLambda = 0.0;
}

(2)m_encRCSeq->initPicPara()帧级别的alpha,beta的参数设置

Void TEncRCSeq::initPicPara( TRCParameter* picPara )
{
  assert( m_picPara != NULL );

  if ( picPara == NULL )
  {
    for ( Int i=0; i<m_numberOfLevel; i++ )
    {
      if (i>0)
      {
        m_picPara[i].m_alpha = 3.2003;
        m_picPara[i].m_beta  = -1.367;
      }
      else
      {
        m_picPara[i].m_alpha = ALPHA;//i=0时,赋给初始值
        m_picPara[i].m_beta  = BETA2;
      }
    }
  }
  else
  {
    for ( Int i=0; i<m_numberOfLevel; i++ )
    {
      m_picPara[i] = picPara[i];
    }
  }
}

二、Void TEncRateCtrl::initRCGOP( Int numberOfPictures )

Void TEncRateCtrl::initRCGOP( Int numberOfPictures )
{
  m_encRCGOP = new TEncRCGOP;
  m_encRCGOP->create( m_encRCSeq, numberOfPictures );//创建新的GOP层的类,传递序列层和一个GOP中的帧数
}

(1)其中调用了一个m_encRCGOP->create()函数

Void TEncRCGOP::create( TEncRCSeq* encRCSeq, Int numPic )
{
  destroy();
  Int targetBits = xEstGOPTargetBits( encRCSeq, numPic );//获得GOP层的目标总比特数;

  if ( encRCSeq->getAdaptiveBits() > 0 && encRCSeq->getLastLambda() > 0.1 )//采用自适应比特分配并且序列的最后一个lambda的值大于0.1
  {
    Double targetBpp = (Double)targetBits / encRCSeq->getNumPixel();//得到目标bpp
    Double basicLambda = 0.0;
    Double* lambdaRatio = new Double[encRCSeq->getGOPSize()];//分别新建存储lambda、alpha、beta 的值
    Double* equaCoeffA = new Double[encRCSeq->getGOPSize()];
    Double* equaCoeffB = new Double[encRCSeq->getGOPSize()];

    if ( encRCSeq->getAdaptiveBits() == 1 )   // for GOP size =4, low delay case在lowdelay模式下, encRCSeq->getAdaptiveBits() == 1 
    {
      if ( encRCSeq->getLastLambda() < 120.0 )//对每一帧的lambda的权值进行赋值
      {
        lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.5793;
        lambdaRatio[0] = 1.3 * lambdaRatio[1];
        lambdaRatio[2] = 1.3 * lambdaRatio[1];
        lambdaRatio[3] = 1.0;
      }
      else
      {
        lambdaRatio[0] = 5.0;
        lambdaRatio[1] = 4.0;
        lambdaRatio[2] = 5.0;
        lambdaRatio[3] = 1.0;
      }
    }
    else if ( encRCSeq->getAdaptiveBits() == 2 )  // for GOP size = 8, random access case在random access模式下, encRCSeq->getAdaptiveBits() == 2 
    {
      if ( encRCSeq->getLastLambda() < 90.0 )
      {
        lambdaRatio[0] = 1.0;
        lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.7963;
        lambdaRatio[2] = 1.3 * lambdaRatio[1];
        lambdaRatio[3] = 3.25 * lambdaRatio[1];
        lambdaRatio[4] = 3.25 * lambdaRatio[1];
        lambdaRatio[5] = 1.3  * lambdaRatio[1];
        lambdaRatio[6] = 3.25 * lambdaRatio[1];
        lambdaRatio[7] = 3.25 * lambdaRatio[1];
      }
      else
      {
        lambdaRatio[0] = 1.0;
        lambdaRatio[1] = 4.0;
        lambdaRatio[2] = 5.0;
        lambdaRatio[3] = 12.3;
        lambdaRatio[4] = 12.3;
        lambdaRatio[5] = 5.0;
        lambdaRatio[6] = 12.3;
        lambdaRatio[7] = 12.3;
      }
    }

    xCalEquaCoeff( encRCSeq, lambdaRatio, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() );
    basicLambda = xSolveEqua( targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() );
    encRCSeq->setAllBitRatio( basicLambda, equaCoeffA, equaCoeffB );

    delete []lambdaRatio;
    delete []equaCoeffA;
    delete []equaCoeffB;
  }

  m_picTargetBitInGOP = new Int[numPic];//GOP中的图片目标比特
  Int i;
  Int totalPicRatio = 0;
  Int currPicRatio = 0;
  for ( i=0; i<numPic; i++ )//遍历整个GOP
  {
    totalPicRatio += encRCSeq->getBitRatio( i );//得到整个GOP所有图片的比特数
  }
  for ( i=0; i<numPic; i++ )
  {
    currPicRatio = encRCSeq->getBitRatio( i );//得到当前图像的比特率
    m_picTargetBitInGOP[i] = (Int)( ((Double)targetBits) * currPicRatio / totalPicRatio );//得到当前GOP中的每一帧的目标比特
  }

  m_encRCSeq    = encRCSeq;
  m_numPic       = numPic;
  m_targetBits   = targetBits;
  m_picLeft      = m_numPic;
  m_bitsLeft     = m_targetBits;
}

①其中调用了xEstGOPTargetBits( encRCSeq, numPic )函数对GOP的目标比特进行预测,返回预测的目标比特数。

Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize )//传递进来码控序列和GOP的大小即一个GOP中的帧数
{
  Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() );//获得实际的平滑窗口大小
  Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() );//获得平均每帧的目标比特
  Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture );
  //当前每帧的目标比特=(视频序列剩余比特数-平均每帧目标比特*(未编码帧数-平滑窗口SW))/平滑窗口SW
  Int targetBits = currentTargetBitsPerPic * GOPSize;//当前GOP的目标比特数=当前每帧的目标比特数*一个GOP中的帧数

  if ( targetBits < 200 )
  {
    targetBits = 200;   // at least allocate 200 bits for one GOP每个GOP至少分配200个比特
  }

  return targetBits;
}

②其中调用了xCalEquaCoeff( encRCSeq, lambdaRatio, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() )来计算系数A和B

Void TEncRCGOP::xCalEquaCoeff( TEncRCSeq* encRCSeq, Double* lambdaRatio, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize )
{
  for ( Int i=0; i<GOPSize; i++ )//遍历整个GOP 
  {
    Int frameLevel = encRCSeq->getGOPID2Level(i);//调用映射函数得到帧所对应的level
    Double alpha   = encRCSeq->getPicPara(frameLevel).m_alpha;//根据framelevel调用getPicPara()函数来得到对应的alpha和beta
    Double beta    = encRCSeq->getPicPara(frameLevel).m_beta;
    equaCoeffA[i] = pow( 1.0/alpha, 1.0/beta ) * pow( lambdaRatio[i], 1.0/beta );//根据alpha和beta计算系数A和B
    equaCoeffB[i] = 1.0/beta;
  }
}

在这里插入图片描述
在这里插入图片描述
③然后调用xSolveEqua( targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() )计算初始λ的值

Double TEncRCGOP::xSolveEqua( Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize )
{
  Double solution = 100.0;//首先对参与运算的三个变量进行初始化
  Double minNumber = 0.1;
  Double maxNumber = 10000.0;
  for ( Int i=0; i<g_RCIterationNum; i++ )//const Int g_RCIterationNum = 20;循环20次
  {
    Double fx = 0.0;//新建变量fx作为计算的bpp,并且初始化
    for ( Int j=0; j<GOPSize; j++ )//遍历整个GOP
    {
      fx += equaCoeffA[j] * pow( solution, equaCoeffB[j] );//fx+=系数A*lambda的系数B次方,累加过后为一个GOP的计算Bpp
    }

    if ( fabs( fx - targetBpp ) < 0.000001 )//若fx - targetBpp的绝对值小于0.000001,满足精度跳出循环
    {
      break;
    }

    if ( fx > targetBpp )//若fx大于targetBpp,将solution赋给min,并从solution—max进行二分赋给solution
    {
      minNumber = solution;
      solution = ( solution + maxNumber ) / 2.0;
    }
    else//若fx小于targetBpp,将solution赋给max,并从min—solution进行二分赋给solution
    {
      maxNumber = solution;
      solution = ( solution + minNumber ) / 2.0;
    }
  }

  solution = Clip3( 0.1, 10000.0, solution );//最后结果为min(10000,max(0.1,solution))
  return solution;//返回solution作为lambda的起始值
}

fbas(x)为求浮点数的绝对值
clip3(A,B.C)=min(B,max(A,C))
在这里插入图片描述
④最后调用setAllBitRatio( basicLambda, equaCoeffA, equaCoeffB )计算比特率并且将得到的比特率赋值给m_bitsRatio[i],对它进行初始化

Void TEncRCSeq::setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB )
{
  Int* bitsRatio = new Int[m_GOPSize];//新建数组计算最终的比特率
  for ( Int i=0; i<m_GOPSize; i++ )
  {
    bitsRatio[i] = (Int)( equaCoeffA[i] * pow( basicLambda, equaCoeffB[i] ) * m_numberOfPixel );//第i帧的比特率=Bpp*总像素数
  }
  initBitsRatio( bitsRatio );//遍历整个GOP,利用 m_bitsRatio[i] = bitsRatio[i]对 m_bitsRatio进行初始化
  delete[] bitsRatio;
}

三、Void TEncRateCtrl::initRCPic( Int frameLevel )

Void TEncRateCtrl::initRCPic( Int frameLevel )
{
  m_encRCPic = new TEncRCPic;
  m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );//创建新的PIC层的类,传递序列、GOP、framelevel和m_listRCPictures
}

(1)其中调用了m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );来进行帧层的码控初始化

Void TEncRCPic::create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures )
{
  destroy();
  m_encRCSeq = encRCSeq;//首先对序列层和GOP层进行赋值初始化
  m_encRCGOP = encRCGOP;

  Int targetBits    = xEstPicTargetBits( encRCSeq, encRCGOP );//调用函数对帧层的目标比特进行预测并赋值给变量targetBits
  Int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel );//调用函数对帧层的头文件比特进行预测并赋值给变量estHeaderBits

  if ( targetBits < estHeaderBits + 100 )
  {
    targetBits = estHeaderBits + 100;   // at least allocate 100 bits for picture data每帧至少分配100个比特
  }

  m_frameLevel       = frameLevel;//帧的level初始化
  m_numberOfPixel    = encRCSeq->getNumPixel();//像素的数目
  m_numberOfLCU      = encRCSeq->getNumberOfLCU();//LCU的个数
  m_estPicLambda     = 100.0;//预测图片的初始lambda为100
  m_targetBits       = targetBits;//将目标比特和头文件比特初始化
  m_estHeaderBits    = estHeaderBits;
  m_bitsLeft         = m_targetBits;//剩余比特,即和目标比特相等
  Int picWidth       = encRCSeq->getPicWidth();//得到图片的宽高
  Int picHeight      = encRCSeq->getPicHeight();
  Int LCUWidth       = encRCSeq->getLCUWidth();//得到LCU的宽高
  Int LCUHeight      = encRCSeq->getLCUHeight();
  Int picWidthInLCU  = ( picWidth  % LCUWidth  ) == 0 ? picWidth  / LCUWidth  : picWidth  / LCUWidth  + 1;//宽上面的LCU个数
  Int picHeightInLCU = ( picHeight % LCUHeight ) == 0 ? picHeight / LCUHeight : picHeight / LCUHeight + 1;//高上面的LCU个数

  m_LCULeft         = m_numberOfLCU;//剩余的LCU个数
  m_bitsLeft       -= m_estHeaderBits;//剩余比特数目=m_bitsLeft-m_estHeaderBits
  m_pixelsLeft      = m_numberOfPixel;//剩余像素个数

  m_LCUs           = new TRCLCU[m_numberOfLCU];//新建结构体TRCLCU存储LCU的信息
  Int i, j;
  Int LCUIdx;
  for ( i=0; i<picWidthInLCU; i++ )
  {
    for ( j=0; j<picHeightInLCU; j++ )
    {
      LCUIdx = j*picWidthInLCU + i;//确定一个LCU在帧的位置,LCUIdx为索引,对每个LCU的成员进行初始化
      m_LCUs[LCUIdx].m_actualBits = 0;
      m_LCUs[LCUIdx].m_QP         = 0;
      m_LCUs[LCUIdx].m_lambda     = 0.0;
      m_LCUs[LCUIdx].m_targetBits = 0;
      m_LCUs[LCUIdx].m_bitWeight  = 1.0;
      Int currWidth  = ( (i == picWidthInLCU -1) ? picWidth  - LCUWidth *(picWidthInLCU -1) : LCUWidth  );
      Int currHeight = ( (j == picHeightInLCU-1) ? picHeight - LCUHeight*(picHeightInLCU-1) : LCUHeight );
      m_LCUs[LCUIdx].m_numberOfPixel = currWidth * currHeight;
    }
  }
  m_picActualHeaderBits = 0;
  m_picActualBits       = 0;
  m_picQP               = 0;
  m_picLambda           = 0.0;
}

①其中调用了xEstPicTargetBits( encRCSeq, encRCGOP )来计算帧层的目标比特
在这里插入图片描述

Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )
{
  Int targetBits        = 0;//定义目标比特并且初始化
  Int GOPbitsLeft       = encRCGOP->getBitsLeft();//获得当前的剩余比特

  Int i;
  Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();//总的帧数-剩余未编码的帧数=当前帧在序列中的位置
  Int currPicRatio    = encRCSeq->getBitRatio( currPicPosition );//利用当前帧的位置求得当前帧的比特率
  Int totalPicRatio   = 0;//定义全部图片比特率并初始化
  for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )//从当前帧位置进行遍历
  {
    totalPicRatio += encRCSeq->getBitRatio( i );//所有帧的比特率之和等于剩余未编码帧的比特率之和
  }

  targetBits  = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );//求出当前帧的目标比特=GOP剩余比特*(当前帧比特率/全部帧比特率)

  if ( targetBits < 100 )
  {
    targetBits = 100;   // at least allocate 100 bits for one picture一帧的目标比特至少为100
  }

  if ( m_encRCSeq->getFramesLeft() > 16 )//如果剩余未编码帧的数目大于16
  {
    targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );
	//目标比特=0.1*目标比特+0.9*当前帧在GOP中的目标比特
  }

  return targetBits;//返回目标比特
}

②调用了xEstPicHeaderBits( listPreviousPictures, frameLevel )对头文件比特进行估计

Int TEncRCPic::xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel )
{
  Int numPreviousPics   = 0;
  Int totalPreviousBits = 0;

  list<TEncRCPic*>::iterator it;
  for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )//遍历已经编码的帧
  {
    if ( (*it)->getFrameLevel() == frameLevel )//如果已编码帧和当前帧为同一个level
    {
      totalPreviousBits += (*it)->getPicActualHeaderBits();//将已编码帧的实际头文件比特数进行累加得到totalPreviousBits
      numPreviousPics++;
    }
  }

  Int estHeaderBits = 0;
  if ( numPreviousPics > 0 )//如果不是第一帧
  {
    estHeaderBits = totalPreviousBits / numPreviousPics;//当前帧的头文件预测比特=已经编码帧的头文件比特总数/已经编码的帧数
  }

  return estHeaderBits;//返回头文件预测比特
}

本博文仅作小白学习记录使用,所有文章出处均在开头链接处可见,所有疑惑点均作了标注。欢迎各位大佬交流批评指正,侵删。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值