最近调试HEVC中码率控制, 发现HM里面一个重大bug

时间:2023-03-08 16:32:30

最近调试HEVC中码率控制, 发现里面一个重大bug!

码率控制中有这么一个函数:

Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize ) {   Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() );   Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() );   Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture );   Int targetBits = currentTargetBitsPerPic * GOPSize;

if ( targetBits < 200 )   {     targetBits = 200;   // at least allocate 200 bits for one GOP   }

return targetBits; }

主要就是控制目标码率的范围!
         H.265 码率控制比H.264比较, 直观上增加了一个参与计算的参数就是编码帧数!也就是cfg里面的参数FramesToBeEncoded。

所以大家最好是变多少帧, 配置为对少帧,  但有些情况是不知道要编码多少帧, 有些同学就写一个最大值, 比如 999999, 表面上看没问题!

但是编码几帧后就会发现!上面这段程序会进入  targetBits = 200 , 导致QP一直是51, 从而码率控制失效, 设置不当还会导致 QP一直很小, 更是起不到码率控制的作用!

解决办法:

方法一1. 设置实际编码帧数, 这样控制最准, 当然不要导致Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture );这里溢出!

方法2.  修改代码, 防止溢出, 修改如下:

Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize )
{
Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() );
Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() );
Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - (Int64)averageTargetBitsPerPic * (Int64)(encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture );
Int targetBits = currentTargetBitsPerPic * GOPSize; if ( targetBits < 200 )
{
targetBits = 200; // at least allocate 200 bits for one GOP
} return targetBits;
}

方法3:  修改代码

修改参与计算的帧数, 比如以2000帧为单位做一次控制, 每2000帧重新配置下码率控制!这样来避免溢出!