碼率控制(五):流體流量模型
碼率控制的主要作用就是適應帶寬需求來壓縮碼率,防止網絡頻繁丟包
流體流量模型就是模擬比特數據在網絡和緩存器中的狀態,下面從解碼端的視角來說明。
HRD( hypothetical reference decoder)中的CPB(coded picture buffer)是用來緩存比特數據的,CPB的容量有限,如果CPB裝滿了則接下來的數據就會溢出造成數據丟失(上溢),如果CPB太空則造成浪費(下溢)。
CPB的狀態可以用三個量來刻畫,R、B、F。R表示網絡傳輸帶寬,B表示CPB容量,F表示CPB充盈度。下圖是一個CPB的狀態變化圖:
其中i表示第i幀圖像,bi表示第i幀圖像的比特數,f表示幀率。
什麼是上溢和下溢?
碼率控制算法的一個重要作用就是防止CPB上溢和下溢。
上面兩個公式分別描述了上溢和下溢發生的情況。
公式(1)表示在某個時刻從CPB中取出第i幀數據用於解碼,同時網絡向CPB中寫入R/f比特數據,此時CPB的比特數超過容量B發生了上溢。下圖是發生上溢的情況。
公式(2)表示在某個時刻從CPB中取出第i幀數據用於解碼,但CPB中數據不夠,發生了下溢。下圖是發生下溢的情況。
防止上溢和下溢
爲了防止上溢和下溢的發生,HM中實現了幀級的碼率調整,使CPB的充盈度保持在10%-90%。碼率調整在計算圖像lambda和QP之前完成。
如下圖所示:
上面的狀態圖可以用下面公式表示:
tbi是HM中碼率控制算法計算的第i幀的目標比特,如果發生上溢則將tbi設置爲Fi+R/f-Bx0.9,如果發生上溢則將tbi設置爲max(200,Fi-Bx0.1)。
參考代碼
#if U0132_TARGET_BITS_SATURATION
if (m_pcRateCtrl->getCpbSaturationEnabled() && frameLevel != 0)
{
Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate();
// prevent overflow
if (estimatedCpbFullness - estimatedBits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f))
{
estimatedBits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f);
}
estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate();
// prevent underflow
#if V0078_ADAPTIVE_LOWER_BOUND
if (estimatedCpbFullness - estimatedBits < m_pcRateCtrl->getRCPic()->getLowerBound())
{
estimatedBits = max(200, estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound());
}
#else
if (estimatedCpbFullness - estimatedBits < (Int)(m_pcRateCtrl->getCpbSize()*0.1f))
{
estimatedBits = max(200, estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.1f));
}
#endif
m_pcRateCtrl->getRCPic()->setTargetBits(estimatedBits);
}
#endif
參考
JCTVC-U0132
感興趣的請關注微信公衆號Video Coding