最近調試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幀重新配置下碼率控制!這樣來避免溢出!