码迷,mamicode.com
首页 > 其他好文 > 详细

HEVC代码追踪(二)

时间:2015-05-20 09:53:46      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:控制   lambda   代码   

R-lambda码率控制模型中的关于帧层,单元层的目标比特分配代码部分。求出各层的目标比特再除以该层的总像素数,得到Bpp用于后续的lambda和Qp的求解。
(1)帧层的目标比特代码部分

Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )//估计图像的目标比特数//类中的私有函数的定义
{
  Int targetBits        = 0;
  Int GOPbitsLeft       = encRCGOP->getBitsLeft();//GOP剩余比特数
  Int i;
  Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();//当前图片的位置
  Int currPicRatio    = encRCSeq->getBitRatio( currPicPosition );//当前图片的比重(当前图像的比重的分配在Void TEncRateCtrl::init中有详细的介绍)
  Int totalPicRatio   = 0;//定义总比重,初始值为0
  for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )//for循环累加,求出总比重
  {
    totalPicRatio += encRCSeq->getBitRatio( i );//第一步
  }

  targetBits  = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );//图像层的目标比特数(13)第二步

  if ( targetBits < 100 )//默认的目标比特大于100,当比特小于100的时候系统默认分配100比特
  {
    targetBits = 100;   // at least allocate 100 bits for one picture
  }

  if ( m_encRCSeq->getFramesLeft() > 16 )//剩余帧数大于16帧
  {
    targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );//
  }

  return targetBits;
}

这段代码中有几个值得指出的地方
①currPicRatio :这个整型变量相当于提案JCTVC-K0103中的公式(9)中的W,表示当前帧的复杂度(就是一种衡量的标准,可以理解为纹理复杂度)。currPicRatio / totalPicRatio表示当前帧在整个GOP中的比重。
②if ( targetBits < 100 ):就是人为规定了个帧的目标比特数不能小于100。

(2)单元层的目标比特分配

/*
下面这段程序的目的是为了获得LCU层的目标比特数Bpp,那么说先要获得图片层的各单元的总的目标比特数,再除以整个LCU层的总像素数。
分两种情况:I帧和非I帧。
(1)当为I帧时,考虑getLCU(LCUIdx).m_costIntra这个变量,他是表征各索引LCU块的costIntra(我的理解是帧内比重的意思),
在帧内又有两种情况,剩余的总的costIntra>0.1时,就要考虑各个LCU块的比重,并根据比重对各个LCU块分配比特。当剩余的比重小于0.1时,就对
剩余的块平均分配剩余的比特数。
(2)当为非I帧时,使用bitWeight表示各个LCU块的比重,求出各个块的分配到的比特数avgBits 。
两种情况的Bpp都是通过下面的公式求得:bpp = ( Double )avgBits/( Double )m_LCUs[ LCUIdx ].m_numberOfPixel;
*/
Double TEncRCPic::getLCUTargetBpp(SliceType eSliceType)//获得单元层的目标比特分配
{
  Int   LCUIdx    = getLCUCoded();//获得已经编码的单元数
  Double bpp      = -1.0;//为什么初始值为这个?
  Int avgBits     = 0;//平均比特

  if (eSliceType == I_SLICE)//如果编码帧为I帧
  {
    Int noOfLCUsLeft = m_numberOfLCU - LCUIdx + 1;//总单元数-已经编码的单元数+1 =剩余单元数
    Int bitrateWindow = min(4,noOfLCUsLeft);//比特率窗,最小为四,不能小于GOP的值
    Double MAD      = getLCU(LCUIdx).m_costIntra;//编号为LCUIdx的LCU块的比重值为MAD

    if (m_remainingCostIntra > 0.1 )//剩余帧内消耗比重
    {
      Double weightedBitsLeft = (m_bitsLeft*bitrateWindow+(m_bitsLeft-getLCU(LCUIdx).m_targetBitsLeft)*noOfLCUsLeft)/(Double)bitrateWindow;//剩余比特数
      avgBits = Int( MAD*weightedBitsLeft/m_remainingCostIntra );//就是剩余的比特数*当前块在总块中的比重
    }
    else//如果剩余的比重小于0.1
    {
      avgBits = Int( m_bitsLeft / m_LCULeft );//剩余的比特数/剩余的单元数作为当前编码块的平均比特数
    }
    m_remainingCostIntra -= MAD;//每一块的MAD相等,也就是没块的目标比特数相等了,所以剩余的比重就是总的减去上一块的,都相等(都为MAD)。
  }
  else//下面讨论不是帧内的情况
  {
    Double totalWeight = 0;
    for ( Int i=LCUIdx; i<m_numberOfLCU; i++ )
    {
      totalWeight += m_LCUs[i].m_bitWeight;
    }
    Int realInfluenceLCU = min( g_RCLCUSmoothWindowSize, getLCULeft() );//真正有影响的LCU块(平滑窗和剩余块数目的最小值)
    avgBits = (Int)( m_LCUs[LCUIdx].m_bitWeight - ( totalWeight - m_bitsLeft ) / realInfluenceLCU + 0.5 );
  }

  if ( avgBits < 1 )
  {
    avgBits = 1;
  }

  bpp = ( Double )avgBits/( Double )m_LCUs[ LCUIdx ].m_numberOfPixel;//总的比特数/总的像素数(bpp用于后面求lambda)
  m_LCUs[ LCUIdx ].m_targetBits = avgBits;

  return bpp;
}

这段代码中有几个值得指出的地方
①if (eSliceType == I_SLICE)
else//下面讨论不是帧内的情况
首先将整个过程分为两种情况:帧内和非帧内
②MAD = getLCU(LCUIdx).m_costIntra
这是提案JCTVC-K0103中单元层比特分配时用到的一个变量。用MAD的平方来表征当前快的复杂度。但是在代码中我并没有看到相应的MAD的平方用于求目标比特数:

avgBits = Int( MAD*weightedBitsLeft/m_remainingCostIntra );
avgBits = Int( m_bitsLeft / m_LCULeft );

这是I帧的两种情况,都不是我想要的那种代码。

上面是大致的关于帧层和单元层的目标比特代码分析。还有没看懂的地方,后续弄清楚了,再纠正。

HEVC代码追踪(二)

标签:控制   lambda   代码   

原文地址:http://blog.csdn.net/cpp12341234/article/details/45851175

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!