📄 ratectlquadratic.cpp
字号:
/*!
***************************************************************************
* \file rc_quadratic.c
*
* \brief
* Rate Control algorithm
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Siwei Ma <swma@jdl.ac.cn>
* - Zhengguo LI <ezgli@lit.a-star.edu.sg>
* - Athanasios Leontaris <aleon@dolby.com>
*
* \date
* 16 Jan. 2003
* 18 Mar. 2007
**************************************************************************
*/
#include "H264AVCEncoderLib.h"
#include "H264AVCCommonLib.h"
#include "RateCtlBase.h"
#include "RateCtlQuadratic.h"
using namespace h264;
jsvm_parameters *pcJSVMParams;
rc_generic *pcGenericRC;
rc_quadratic *pcQuadraticRC;
rc_quadratic::rc_quadratic( rc_generic *pcGenRC, jsvm_parameters *jsvm_params )
{
m_pcGenericRC = pcGenRC;
m_pcJSVMParams = jsvm_params;
m_fTHETA = 1.3636F;
m_fOMEGA = 0.9F;
m_fMINVALUE = 4.0F;
}
rc_quadratic::~rc_quadratic( void )
{
rc_free();
}
/*!
*************************************************************************************
* \brief
* Dynamically allocate memory needed for rate control
*
*************************************************************************************
*/
void rc_quadratic::rc_alloc( void )
{
int iRcBufSize = m_pcJSVMParams->FrameSizeInMbs / m_pcJSVMParams->basicunit;
m_dPreviousFrameMAD = 1.0;
m_dCurrentFrameMAD = 1.0;
m_i64PPrevBits = 0;
m_i64IPrevBits = 0;
m_iTarget = 0;
m_iTargetField = 0;
m_iLowerBound = 0;
m_iUpperBound1 = INT_MAX;
m_iUpperBound2 = INT_MAX;
m_dWp = 0.0;
m_dWb = 0.0;
m_iPAveFrameQP = m_pcJSVMParams->SetInitialQP;
m_iQc = m_iPAveFrameQP;
m_iFieldQPBuffer = m_iPAveFrameQP;
m_iFrameQPBuffer = m_iPAveFrameQP;
m_iPAverageQp = m_iPAveFrameQP;
m_iMyInitialQp = m_iPAveFrameQP;
m_iRCMaxQuant = m_pcJSVMParams->RCMaxQP;
m_iRCMinQuant = m_pcJSVMParams->RCMinQP; //-m_pcJSVMParams->bitdepth_luma_qp_scale;//clipping
m_pdBUPFMAD = (double *) calloc ((iRcBufSize), sizeof (double));
if (NULL == m_pdBUPFMAD)
{
fprintf(stderr, "rc_alloc: m_pdBUPFMAD");
assert(0); // some compilers do not compile assert in release/Ox mode
exit(1);
}
m_pdBUCFMAD = (double *) calloc ((iRcBufSize), sizeof (double));
if (NULL == m_pdBUCFMAD)
{
fprintf(stderr, "rc_alloc: m_pdBUCFMAD");
assert(0); // some compilers do not compile assert in release/Ox mode
exit(1);
}
m_pdFCBUCFMAD = (double *) calloc ((iRcBufSize), sizeof (double));
if (NULL == m_pdFCBUCFMAD)
{
fprintf(stderr, "rc_alloc: m_pdFCBUCFMAD");
assert(0); // some compilers do not compile assert in release/Ox mode
exit(1);
}
m_pdFCBUPFMAD = (double *) calloc ((iRcBufSize), sizeof (double));
if (NULL == m_pdFCBUPFMAD)
{
fprintf(stderr, "rc_alloc: m_pdFCBUPFMAD");
assert(0); // some compilers do not compile assert in release/Ox mode
exit(1);
}
}
/*!
*************************************************************************************
* \brief
* Free memory needed for rate control
*
*************************************************************************************
*/
void rc_quadratic::rc_free( void )
{
if (NULL != m_pdBUPFMAD)
{
free (m_pdBUPFMAD);
m_pdBUPFMAD = NULL;
}
if (NULL != m_pdBUCFMAD)
{
free (m_pdBUCFMAD);
m_pdBUCFMAD = NULL;
}
if (NULL != m_pdFCBUCFMAD)
{
free (m_pdFCBUCFMAD);
m_pdFCBUCFMAD = NULL;
}
if (NULL != m_pdFCBUPFMAD)
{
free (m_pdFCBUPFMAD);
m_pdFCBUPFMAD = NULL;
}
}
/*!
*************************************************************************************
* \brief
* Initialize rate control parameters
*
*************************************************************************************
*/
void rc_quadratic::rc_init_seq( void )
{
int i;
m_iXp=0;
m_iXb=0;
m_fBitRate = (float) m_pcJSVMParams->bit_rate;
m_fFrameRate = (m_pcJSVMParams->FrameRate *(float)(m_pcJSVMParams->successive_Bframe + 1)) / (float) (m_pcJSVMParams->jumpd + 1);
m_fPrevBitRate = m_fBitRate;
// compute the total number of MBs in a frame
if(m_pcJSVMParams->basicunit > m_pcJSVMParams->FrameSizeInMbs)
m_pcJSVMParams->basicunit = m_pcJSVMParams->FrameSizeInMbs;
if(m_pcJSVMParams->basicunit < m_pcJSVMParams->FrameSizeInMbs)
m_iTotalNumberofBasicUnit = m_pcJSVMParams->FrameSizeInMbs/m_pcJSVMParams->basicunit;
else
m_iTotalNumberofBasicUnit = 1;
// initialize the parameters of fluid flow traffic model
m_pcGenericRC->m_i64CurrentBufferFullness = 0;
m_dGOPTargetBufferLevel = (double) m_pcGenericRC->m_i64CurrentBufferFullness;
// initialize the previous window size
m_iWindowSize = 0;
m_iMADWindowSize = 0;
m_pcGenericRC->m_iNumberofCodedBFrame = 0;
m_iNumberofCodedPFrame = 0;
m_pcGenericRC->m_iNumberofGOP = 0;
// remaining # of bits in GOP
m_pcGenericRC->m_iRemainingBits = 0;
// control parameter
if(m_pcJSVMParams->successive_Bframe>0)
{
m_dGAMMAP=0.25;
m_dBETAP=0.9;
}
else
{
m_dGAMMAP=0.5;
m_dBETAP=0.5;
}
// quadratic rate-distortion model
m_iPPreHeader=0;
m_dPX1 = m_fBitRate * 1.0;
m_dPX2 = 0.0;
// linear prediction model for P picture
m_dPMADPictureC1 = 1.0;
m_dPMADPictureC2 = 0.0;
// Initialize values
for(i=0;i<21;i++)
{
m_dPRgQp[i] = 0;
m_dPRgRp[i] = 0.0;
m_dPPictureMAD[i] = 0.0;
}
// basic unit layer rate control
m_iPAveHeaderBits1 = 0;
m_iPAveHeaderBits3 = 0;
m_uiMBPerRow = m_pcJSVMParams->PicWidthInMbs;
// adaptive field/frame coding
m_pcGenericRC->m_iFieldControl=0;
}
/*!
*************************************************************************************
* \brief
* Initialize one GOP
*
*************************************************************************************
*/
void rc_quadratic::rc_init_GOP( int iNp, int iNb )
{
int iOverBits, iOverDuantQp;
int iAllocatedBits, iGOPDquant;
// check if the last GOP over uses its budget. If yes, the initial QP of the I frame in
// the coming GOP will be increased.
iOverBits=-m_pcGenericRC->m_iRemainingBits;
// initialize the lower bound and the upper bound for the target bits of each frame, HRD consideration
m_iLowerBound = (int)(m_pcGenericRC->m_iRemainingBits + m_fBitRate / m_fFrameRate);
m_iUpperBound1 = (int)(m_pcGenericRC->m_iRemainingBits + (m_fBitRate * 2.048));
// compute the total number of bits for the current GOP
iAllocatedBits = (int) floor((1 + iNp + iNb) * m_fBitRate / m_fFrameRate + 0.5);
m_pcGenericRC->m_iRemainingBits += iAllocatedBits;
m_iNp = iNp;
m_iNb = iNb;
iOverDuantQp=(int)(8 * iOverBits/iAllocatedBits+0.5);
m_bGOPOverdue=false;
// field coding
if ( !m_pcJSVMParams->PicInterlace && m_pcJSVMParams->MbInterlace && m_pcJSVMParams->basicunit == m_pcJSVMParams->FrameSizeInMbs )
m_pcGenericRC->m_iNoGranularFieldRC = 0;
else
m_pcGenericRC->m_iNoGranularFieldRC = 1;
// Compute InitialQp for each GOP
m_iTotalPFrame=iNp;
m_pcGenericRC->m_iNumberofGOP++;
if(m_pcGenericRC->m_iNumberofGOP==1)
{
m_iMyInitialQp = m_pcJSVMParams->SetInitialQP;
m_iCurrLastQP = m_iMyInitialQp - 1; //recent change -0;
m_iQPLastGOP = m_iMyInitialQp;
m_iPAveFrameQP = m_iMyInitialQp;
m_iQc = m_iPAveFrameQP;
m_iFieldQPBuffer = m_iPAveFrameQP;
m_iFrameQPBuffer = m_iPAveFrameQP;
m_iPAverageQp = m_iPAveFrameQP;
}
else
{
// adaptive field/frame coding
if( m_pcJSVMParams->PicInterlace == ADAPTIVE_CODING || m_pcJSVMParams->MbInterlace )
{
if (m_pcGenericRC->m_iFieldFrame == 1)
{
m_iTotalQpforPPicture += m_iFrameQPBuffer;
m_iQPLastPFrame = m_iFrameQPBuffer;
}
else
{
m_iTotalQpforPPicture += m_iFieldQPBuffer;
m_iQPLastPFrame = m_iFieldQPBuffer;
}
}
// compute the average QP of P frames in the previous GOP
m_iPAverageQp=(int)(1.0 * m_iTotalQpforPPicture / m_iNumberofPPicture+0.5);
iGOPDquant=(int)((1.0*(iNp+iNb+1)/15.0) + 0.5);
if(iGOPDquant>2)
iGOPDquant=2;
m_iPAverageQp -= iGOPDquant;
if (m_iPAverageQp > (m_iQPLastPFrame - 2))
m_iPAverageQp--;
// QP is constrained by QP of previous QP
m_iPAverageQp = iClip3(m_iQPLastGOP - 2, m_iQPLastGOP + 2, m_iPAverageQp);
// Also clipped within range.
m_iPAverageQp = iClip3(m_iRCMinQuant, m_iRCMaxQuant, m_iPAverageQp);
m_iMyInitialQp = m_iPAverageQp;
m_iPQp = m_iPAverageQp;
m_iPAveFrameQP = m_iPAverageQp;
m_iQPLastGOP = m_iMyInitialQp;
m_iPrevLastQP = m_iCurrLastQP;
m_iCurrLastQP = m_iMyInitialQp - 1;
}
m_iTotalQpforPPicture=0;
m_iNumberofPPicture=0;
m_iNumberofBFrames=0;
}
/*!
*************************************************************************************
* \brief
* Initialize one picture
*
*************************************************************************************
*/
void rc_quadratic::rc_init_pict( int iFieldPic, int iTopField, int iTargetComputation, float fMult )
{
int iTmpT;
// compute the total number of basic units in a frame
if(m_pcJSVMParams->MbInterlace)
m_iTotalNumberofBasicUnit = m_pcJSVMParams->FrameSizeInMbs / m_pcJSVMParams->BasicUnit;
else
m_iTotalNumberofBasicUnit = m_pcJSVMParams->FrameSizeInMbs / m_pcJSVMParams->basicunit;
m_pcJSVMParams->NumberofCodedMacroBlocks = 0;
// Normally, the bandwidth for the VBR case is estimated by
// a congestion control algorithm. A bandwidth curve can be predefined if we only want to
// test the proposed algorithm
if(m_pcJSVMParams->channel_type==1)
{
if(m_iNumberofCodedPFrame==58)
m_fBitRate *= 1.5;
else if(m_iNumberofCodedPFrame==59)
m_fPrevBitRate = m_fBitRate;
}
// predefine a target buffer level for each frame
if((iFieldPic||iTopField) && iTargetComputation)
{
if ( m_pcJSVMParams->type == P_SLICE || (m_pcJSVMParams->RCUpdateMode == RC_MODE_1 && (m_pcJSVMParams->number !=0)) )
{
// Since the available bandwidth may vary at any time, the total number of
// bits is updated picture by picture
if(m_fPrevBitRate!=m_fBitRate)
m_pcGenericRC->m_iRemainingBits +=(int) floor((m_fBitRate-m_fPrevBitRate)*(m_iNp + m_iNb)/m_fFrameRate+0.5);
// predefine the target buffer level for each picture.
// frame layer rate control
if(m_pcJSVMParams->BasicUnit == m_pcJSVMParams->FrameSizeInMbs)
{
if(m_iNumberofPPicture==1)
{
m_dTargetBufferLevel = (double) m_pcGenericRC->m_i64CurrentBufferFullness;
m_dDeltaP = (m_pcGenericRC->m_i64CurrentBufferFullness - m_dGOPTargetBufferLevel) / (m_iTotalPFrame-1);
m_dTargetBufferLevel -= m_dDeltaP;
}
else if(m_iNumberofPPicture>1)
m_dTargetBufferLevel -= m_dDeltaP;
}
// basic unit layer rate control
else
{
if(m_iNumberofCodedPFrame>0)
{
// adaptive frame/field coding
if(((m_pcJSVMParams->PicInterlace==ADAPTIVE_CODING)||(m_pcJSVMParams->MbInterlace))&&(m_pcGenericRC->m_iFieldControl==1))
memcpy((void *)m_pdFCBUPFMAD,(void *)m_pdFCBUCFMAD, m_iTotalNumberofBasicUnit * sizeof(double));
else
memcpy((void *)m_pdBUPFMAD,(void *)m_pdBUCFMAD, m_iTotalNumberofBasicUnit * sizeof(double));
}
if(m_pcGenericRC->m_iNumberofGOP==1)
{
if(m_iNumberofPPicture==1)
{
m_dTargetBufferLevel = (double) m_pcGenericRC->m_i64CurrentBufferFullness;
m_dDeltaP = (m_pcGenericRC->m_i64CurrentBufferFullness - m_dGOPTargetBufferLevel)/(m_iTotalPFrame - 1);
m_dTargetBufferLevel -= m_dDeltaP;
}
else if(m_iNumberofPPicture>1)
m_dTargetBufferLevel -= m_dDeltaP;
}
else if(m_pcGenericRC->m_iNumberofGOP>1)
{
if(m_iNumberofPPicture==0)
{
m_dTargetBufferLevel = (double) m_pcGenericRC->m_i64CurrentBufferFullness;
m_dDeltaP = (m_pcGenericRC->m_i64CurrentBufferFullness - m_dGOPTargetBufferLevel) / m_iTotalPFrame;
m_dTargetBufferLevel -= m_dDeltaP;
}
else if(m_iNumberofPPicture>0)
m_dTargetBufferLevel -= m_dDeltaP;
}
}
if(m_iNumberofCodedPFrame==1)
m_dAveWp = m_dWp;
if((m_iNumberofCodedPFrame<8)&&(m_iNumberofCodedPFrame>1))
m_dAveWp = (m_dAveWp + m_dWp * (m_iNumberofCodedPFrame-1))/m_iNumberofCodedPFrame;
else if(m_iNumberofCodedPFrame>1)
m_dAveWp = (m_dWp + 7 * m_dAveWp) / 8;
// compute the average iComplexity of B frames
if(m_pcJSVMParams->successive_Bframe>0)
{
// compute the target buffer level
m_dTargetBufferLevel += (m_dAveWp * (m_pcJSVMParams->successive_Bframe + 1)*m_fBitRate\
/(m_fFrameRate*(m_dAveWp+m_dAveWb*m_pcJSVMParams->successive_Bframe))-m_fBitRate/m_fFrameRate);
}
}
else if ( m_pcJSVMParams->type == B_SLICE )
{
// update the total number of bits if the bandwidth is changed
if(m_fPrevBitRate != m_fBitRate)
m_pcGenericRC->m_iRemainingBits +=(int) floor((m_fBitRate-m_fPrevBitRate) * (m_iNp + m_iNb) / m_fFrameRate+0.5);
if((m_iNumberofCodedPFrame==1)&&(m_pcGenericRC->m_iNumberofCodedBFrame==1))
{
m_dAveWp = m_dWp;
m_dAveWb = m_dWb;
}
else if(m_pcGenericRC->m_iNumberofCodedBFrame > 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -