📄 rc_quadratic.c
字号:
return ((int) floor(nbits * prc->m_Qc + 0.5));
}
return 0;
}
void updatePparams( rc_quadratic *prc, int complexity )
{
prc->Xp = complexity;
prc->Np--;
prc->Wp = prc->Xp;
prc->Pm_Hp = generic_RC->NumberofHeaderBits;
prc->NumberofCodedPFrame++;
prc->NumberofPPicture++;
}
void updateBparams( rc_quadratic *prc, int complexity )
{
prc->Xb = complexity;
prc->Nb--;
prc->Wb = prc->Xb / THETA;
prc->NumberofBFrames++;
generic_RC->NumberofCodedBFrame++;
}
/*!
*************************************************************************************
* \brief
* update after frame encoding
*
* \param nbits
* number of bits used for frame
*
*************************************************************************************
*/
void rc_update_pict_frame(rc_quadratic *prc, int nbits)
{
/* update the complexity weight of I, P, B frame */
int complexity = 0;
switch( input->RCUpdateMode )
{
case RC_MODE_0:
case RC_MODE_2:
default:
complexity = updateComplexity( prc, (Boolean) (img->type == P_SLICE), nbits );
if ( img->type == P_SLICE )
{
if( generic_RC->NoGranularFieldRC == 0 || generic_RC->FieldControl == 0 )
updatePparams( prc, complexity );
else
generic_RC->NoGranularFieldRC = 0;
}
else if ( img->type == B_SLICE )
updateBparams( prc, complexity );
break;
case RC_MODE_1:
complexity = updateComplexity( prc, (Boolean) (img->number != 0), nbits );
if ( img->number != 0 )
{
if( generic_RC->NoGranularFieldRC == 0 || generic_RC->FieldControl == 0 )
updatePparams( prc, complexity );
else
generic_RC->NoGranularFieldRC = 0;
}
break;
case RC_MODE_3:
complexity = updateComplexity( prc, (Boolean) (img->type == P_SLICE), nbits );
if (img->type == I_SLICE && (img->number != 0))
generic_RC->NIslice--;
if ( img->type == P_SLICE )
{
if( generic_RC->NoGranularFieldRC == 0 || generic_RC->FieldControl == 0 )
{
updatePparams( prc, complexity );
generic_RC->NPslice--;
}
else
generic_RC->NoGranularFieldRC = 0;
}
else if ( img->type == B_SLICE )
{
updateBparams( prc, complexity );
generic_RC->hierNb[ input->HierarchicalCoding ? (generic_RC->temporal_levels - 1 - gop_structure[img->b_frame_to_code-1].hierarchy_layer) : 0 ]--;
}
break;
}
}
/*!
*************************************************************************************
* \brief
* update the parameters of quadratic R-D model
*
*************************************************************************************
*/
void updateRCModel (rc_quadratic *prc)
{
int n_windowSize;
int i;
double std = 0.0, threshold;
int m_Nc = prc->NumberofCodedPFrame;
Boolean MADModelFlag = FALSE;
static Boolean m_rgRejected[RC_MODEL_HISTORY];
static double error [RC_MODEL_HISTORY];
if( img->type == P_SLICE || (input->RCUpdateMode == RC_MODE_1 && (img->number != 0)) )
{
/*frame layer rate control*/
if(img->BasicUnit == img->FrameSizeInMbs)
{
prc->CurrentFrameMAD = ComputeFrameMAD();
m_Nc=prc->NumberofCodedPFrame;
}
/*basic unit layer rate control*/
else
{
/*compute the MAD of the current basic unit*/
prc->CurrentFrameMAD = (double) ((generic_RC->TotalMADBasicUnit >> 8)/img->BasicUnit);
generic_RC->TotalMADBasicUnit=0;
/* compute the average number of header bits*/
prc->CodedBasicUnit=prc->TotalNumberofBasicUnit-prc->NumberofBasicUnit;
if(prc->CodedBasicUnit > 0)
{
prc->PAveHeaderBits1=(int)((double)(prc->PAveHeaderBits1*(prc->CodedBasicUnit-1)+
generic_RC->NumberofBasicUnitHeaderBits)/prc->CodedBasicUnit+0.5);
if(prc->PAveHeaderBits3 == 0)
prc->PAveHeaderBits2 = prc->PAveHeaderBits1;
else
{
prc->PAveHeaderBits2 = (int)((double)(prc->PAveHeaderBits1 * prc->CodedBasicUnit+
prc->PAveHeaderBits3 * prc->NumberofBasicUnit)/prc->TotalNumberofBasicUnit+0.5);
}
}
/*update the record of MADs for reference*/
if(((input->PicInterlace == ADAPTIVE_CODING) || (input->MbInterlace)) && (generic_RC->FieldControl == 1))
prc->FCBUCFMAD[prc->TotalNumberofBasicUnit-1-prc->NumberofBasicUnit]=prc->CurrentFrameMAD;
else
prc->BUCFMAD[prc->TotalNumberofBasicUnit-1-prc->NumberofBasicUnit]=prc->CurrentFrameMAD;
if(prc->NumberofBasicUnit != 0)
m_Nc = prc->NumberofCodedPFrame * prc->TotalNumberofBasicUnit + prc->CodedBasicUnit;
else
m_Nc = (prc->NumberofCodedPFrame-1) * prc->TotalNumberofBasicUnit + prc->CodedBasicUnit;
}
if(m_Nc > 1)
MADModelFlag=TRUE;
prc->PPreHeader = generic_RC->NumberofHeaderBits;
for (i = (RC_MODEL_HISTORY-2); i > 0; i--)
{// update the history
prc->Pm_rgQp[i] = prc->Pm_rgQp[i - 1];
prc->m_rgQp[i] = prc->Pm_rgQp[i];
prc->Pm_rgRp[i] = prc->Pm_rgRp[i - 1];
prc->m_rgRp[i] = prc->Pm_rgRp[i];
}
prc->Pm_rgQp[0] = QP2Qstep(prc->m_Qc); //*1.0/prc->CurrentFrameMAD;
/*frame layer rate control*/
if(img->BasicUnit == img->FrameSizeInMbs)
prc->Pm_rgRp[0] = generic_RC->NumberofTextureBits*1.0/prc->CurrentFrameMAD;
/*basic unit layer rate control*/
else
prc->Pm_rgRp[0] = generic_RC->NumberofBasicUnitTextureBits*1.0/prc->CurrentFrameMAD;
prc->m_rgQp[0] = prc->Pm_rgQp[0];
prc->m_rgRp[0] = prc->Pm_rgRp[0];
prc->m_X1 = prc->Pm_X1;
prc->m_X2 = prc->Pm_X2;
/*compute the size of window*/
n_windowSize = (prc->CurrentFrameMAD>prc->PreviousFrameMAD)
? (int)(prc->PreviousFrameMAD/prc->CurrentFrameMAD * (RC_MODEL_HISTORY-1) )
: (int)(prc->CurrentFrameMAD/prc->PreviousFrameMAD *(RC_MODEL_HISTORY-1));
n_windowSize=iClip3(1, m_Nc, n_windowSize);
n_windowSize=imin(n_windowSize,prc->m_windowSize+1);
n_windowSize=imin(n_windowSize,(RC_MODEL_HISTORY-1));
/*update the previous window size*/
prc->m_windowSize=n_windowSize;
for (i = 0; i < (RC_MODEL_HISTORY-1); i++)
{
m_rgRejected[i] = FALSE;
}
// initial RD model estimator
RCModelEstimator (prc, n_windowSize, m_rgRejected);
n_windowSize = prc->m_windowSize;
// remove outlier
for (i = 0; i < (int) n_windowSize; i++)
{
error[i] = prc->m_X1 / prc->m_rgQp[i] + prc->m_X2 / (prc->m_rgQp[i] * prc->m_rgQp[i]) - prc->m_rgRp[i];
std += error[i] * error[i];
}
threshold = (n_windowSize == 2) ? 0 : sqrt (std / n_windowSize);
for (i = 0; i < (int) n_windowSize; i++)
{
if (fabs(error[i]) > threshold)
m_rgRejected[i] = TRUE;
}
// always include the last data point
m_rgRejected[0] = FALSE;
// second RD model estimator
RCModelEstimator (prc, n_windowSize, m_rgRejected);
if( MADModelFlag )
updateMADModel(prc);
else if( img->type == P_SLICE || (input->RCUpdateMode == RC_MODE_1 && (img->number != 0)) )
prc->PPictureMAD[0] = prc->CurrentFrameMAD;
}
}
/*!
*************************************************************************************
* \brief
* Model Estimator
*
*************************************************************************************
*/
void RCModelEstimator (rc_quadratic *prc, int n_windowSize, Boolean *m_rgRejected)
{
int n_realSize = n_windowSize;
int i;
double oneSampleQ = 0;
double a00 = 0.0, a01 = 0.0, a10 = 0.0, a11 = 0.0, b0 = 0.0, b1 = 0.0;
double MatrixValue;
Boolean estimateX2 = FALSE;
for (i = 0; i < n_windowSize; i++)
{// find the number of samples which are not rejected
if (m_rgRejected[i])
n_realSize--;
}
// default RD model estimation results
prc->m_X1 = prc->m_X2 = 0.0;
for (i = 0; i < n_windowSize; i++)
{
if (!m_rgRejected[i])
oneSampleQ = prc->m_rgQp[i];
}
for (i = 0; i < n_windowSize; i++)
{// if all non-rejected Q are the same, take 1st order model
if ((prc->m_rgQp[i] != oneSampleQ) && !m_rgRejected[i])
estimateX2 = TRUE;
if (!m_rgRejected[i])
prc->m_X1 += (prc->m_rgQp[i] * prc->m_rgRp[i]) / n_realSize;
}
// take 2nd order model to estimate X1 and X2
if ((n_realSize >= 1) && estimateX2)
{
for (i = 0; i < n_windowSize; i++)
{
if (!m_rgRejected[i])
{
a00 = a00 + 1.0;
a01 += 1.0 / prc->m_rgQp[i];
a10 = a01;
a11 += 1.0 / (prc->m_rgQp[i] * prc->m_rgQp[i]);
b0 += prc->m_rgQp[i] * prc->m_rgRp[i];
b1 += prc->m_rgRp[i];
}
}
// solve the equation of AX = B
MatrixValue=a00*a11-a01*a10;
if(fabs(MatrixValue) > 0.000001)
{
prc->m_X1 = (b0 * a11 - b1 * a01) / MatrixValue;
prc->m_X2 = (b1 * a00 - b0 * a10) / MatrixValue;
}
else
{
prc->m_X1 = b0 / a00;
prc->m_X2 = 0.0;
}
}
if( img->type == P_SLICE || (input->RCUpdateMode == RC_MODE_1 && (img->number != 0)) )
{
prc->Pm_X1 = prc->m_X1;
prc->Pm_X2 = prc->m_X2;
}
}
/*!
*************************************************************************************
* \brief
* update the parameters of linear prediction model
*
*************************************************************************************
*/
void updateMADModel (rc_quadratic *prc)
{
int n_windowSize;
int i;
double std = 0.0, threshold;
int m_Nc = prc->NumberofCodedPFrame;
static Boolean PictureRejected[RC_MODEL_HISTORY];
static double error [RC_MODEL_HISTORY];
if(prc->NumberofCodedPFrame>0)
{
//assert (img->type!=P_SLICE);
/*frame layer rate control*/
if(img->BasicUnit == img->FrameSizeInMbs)
m_Nc = prc->NumberofCodedPFrame;
else // basic unit layer rate control
m_Nc=prc->NumberofCodedPFrame*prc->TotalNumberofBasicUnit+prc->CodedBasicUnit;
for (i = (RC_MODEL_HISTORY-2); i > 0; i--)
{// update the history
prc->PPictureMAD[i] = prc->PPictureMAD[i - 1];
prc->PictureMAD[i] = prc->PPictureMAD[i];
prc->ReferenceMAD[i] = prc->ReferenceMAD[i-1];
}
prc->PPictureMAD[0] = prc->CurrentFrameMAD;
prc->PictureMAD[0] = prc->PPictureMAD[0];
if(img->BasicUnit == img->FrameSizeInMbs)
prc->ReferenceMAD[0]=prc->PictureMAD[1];
else
{
if(((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace)) &&(generic_RC->FieldControl==1))
prc->ReferenceMAD[0]=prc->FCBUPFMAD[prc->TotalNumberofBasicUnit-1-prc->NumberofBasicUnit];
else
prc->ReferenceMAD[0]=prc->BUPFMAD[prc->TotalNumberofBasicUnit-1-prc->NumberofBasicUnit];
}
prc->MADPictureC1 = prc->PMADPictureC1;
prc->MADPictureC2 = prc->PMADPictureC2;
/*compute the size of window*/
n_windowSize = (prc->CurrentFrameMAD > prc->PreviousFrameMAD)
? (int) ((float)(RC_MODEL_HISTORY-1) * prc->PreviousFrameMAD / prc->CurrentFrameMAD)
: (int) ((float)(RC_MODEL_HISTORY-1) * prc->CurrentFrameMAD / prc->PreviousFrameMAD);
n_windowSize = iClip3(1, (m_Nc-1), n_windowSize);
n_windowSize=imin(n_windowSize, imin(20, prc->MADm_windowSize + 1));
/*update the previous window size*/
prc->MADm_windowSize=n_windowSize;
for (i = 0; i < (RC_MODEL_HISTORY-1); i++)
{
PictureRejected[i] = FALSE;
}
//update the MAD for the previous frame
if( img->type == P_SLICE || (input->RCUpdateMode == RC_MODE_1 && (img->number != 0)) )
prc->PreviousFrameMAD=prc->CurrentFrameMAD;
// initial MAD model estimator
MADModelEstimator (prc, n_windowSize, PictureRejected);
// remove outlier
for (i = 0; i < n_windowSize; i++)
{
error[i] = prc->MADPictureC1 * prc->ReferenceMAD[i] + prc->MADPictureC2 - prc->PictureMAD[i];
std += (error[i] * error[i]);
}
threshold = (n_windowSize == 2) ? 0 : sqrt (std / n_windowSize);
for (i = 0; i < n_windowSize; i++)
{
if (fabs(error[i]) > threshold)
PictureRejected[i] = TRUE;
}
// always include the last data point
PictureRejected[0] = FALSE;
// second MAD model estimator
MADModelEstimator (prc, n_windowSize, PictureRejected);
}
}
/*!
*************************************************************************************
* \brief
* MAD mode estimator
*
*************************************************************************************
*/
void MADModelEstimator (rc_quadratic *prc, int n_windowSize, Boolean *PictureRejected)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -