📄 rc_quadratic.c
字号:
/*!
***************************************************************************
* \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
**************************************************************************
*/
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <memory.h>
#include <limits.h>
#include "global.h"
#include "ratectl.h"
#include "rc_quadratic.h"
static const float THETA = 1.3636F;
static const float OMEGA = 0.9F;
static const float MINVALUE = 4.0F;
/*!
*************************************************************************************
* \brief
* Dynamically allocate memory needed for rate control
*
*************************************************************************************
*/
void rc_alloc( rc_quadratic **prc )
{
int rcBufSize = img->FrameSizeInMbs / input->basicunit;
rc_quadratic *lprc;
(*prc) = (rc_quadratic *) malloc ( sizeof( rc_quadratic ) );
if (NULL==(*prc))
{
no_mem_exit("init_global_buffers: (*prc)");
}
lprc = *prc;
lprc->PreviousFrameMAD = 1.0;
lprc->CurrentFrameMAD = 1.0;
lprc->Pprev_bits = 0;
lprc->Iprev_bits = 0;
lprc->Target = 0;
lprc->TargetField = 0;
lprc->LowerBound = 0;
lprc->UpperBound1 = INT_MAX;
lprc->UpperBound2 = INT_MAX;
lprc->Wp = 0.0;
lprc->Wb = 0.0;
lprc->AveWb = 0.0;
lprc->PAveFrameQP = input->qp0;
lprc->m_Qc = lprc->PAveFrameQP;
lprc->FieldQPBuffer = lprc->PAveFrameQP;
lprc->FrameQPBuffer = lprc->PAveFrameQP;
lprc->PAverageQp = lprc->PAveFrameQP;
lprc->MyInitialQp = lprc->PAveFrameQP;
lprc->RC_MAX_QUANT = input->RCMaxQP;
lprc->RC_MIN_QUANT = input->RCMinQP; //-img->bitdepth_luma_qp_scale;//clipping
lprc->AveWb = 0.0;
lprc->BUPFMAD = (double*) calloc ((rcBufSize), sizeof (double));
if (NULL==lprc->BUPFMAD)
{
no_mem_exit("rc_alloc: lprc->BUPFMAD");
}
lprc->BUCFMAD = (double*) calloc ((rcBufSize), sizeof (double));
if (NULL==lprc->BUCFMAD)
{
no_mem_exit("rc_alloc: lprc->BUCFMAD");
}
lprc->FCBUCFMAD = (double*) calloc ((rcBufSize), sizeof (double));
if (NULL==lprc->FCBUCFMAD)
{
no_mem_exit("rc_alloc: lprc->FCBUCFMAD");
}
lprc->FCBUPFMAD = (double*) calloc ((rcBufSize), sizeof (double));
if (NULL==lprc->FCBUPFMAD)
{
no_mem_exit("rc_alloc: lprc->FCBUPFMAD");
}
}
/*!
*************************************************************************************
* \brief
* Copy JVT rate control objects
*
*************************************************************************************
*/
void copy_rc_jvt( rc_quadratic *dst, rc_quadratic *src )
{
int rcBufSize = img->FrameSizeInMbs / input->basicunit;
/* buffer original addresses for which memory has been allocated */
double *tmpBUPFMAD = dst->BUPFMAD;
double *tmpBUCFMAD = dst->BUCFMAD;
double *tmpFCBUPFMAD = dst->FCBUPFMAD;
double *tmpFCBUCFMAD = dst->FCBUCFMAD;
/* copy object */
memcpy( (void *)dst, (void *)src, sizeof(rc_quadratic) );
/* restore original addresses */
dst->BUPFMAD = tmpBUPFMAD;
dst->BUCFMAD = tmpBUCFMAD;
dst->FCBUPFMAD = tmpFCBUPFMAD;
dst->FCBUCFMAD = tmpFCBUCFMAD;
/* copy MADs */
memcpy( (void *)dst->BUPFMAD, (void *)src->BUPFMAD, (rcBufSize) * sizeof (double) );
memcpy( (void *)dst->BUCFMAD, (void *)src->BUCFMAD, (rcBufSize) * sizeof (double) );
memcpy( (void *)dst->FCBUPFMAD, (void *)src->FCBUPFMAD, (rcBufSize) * sizeof (double) );
memcpy( (void *)dst->FCBUCFMAD, (void *)src->FCBUCFMAD, (rcBufSize) * sizeof (double) );
}
/*!
*************************************************************************************
* \brief
* Free memory needed for rate control
*
*************************************************************************************
*/
void rc_free(rc_quadratic **prc)
{
if (NULL!=(*prc)->BUPFMAD)
{
free ((*prc)->BUPFMAD);
(*prc)->BUPFMAD = NULL;
}
if (NULL!=(*prc)->BUCFMAD)
{
free ((*prc)->BUCFMAD);
(*prc)->BUCFMAD = NULL;
}
if (NULL!=(*prc)->FCBUCFMAD)
{
free ((*prc)->FCBUCFMAD);
(*prc)->FCBUCFMAD = NULL;
}
if (NULL!=(*prc)->FCBUPFMAD)
{
free ((*prc)->FCBUPFMAD);
(*prc)->FCBUPFMAD = NULL;
}
if (NULL!=(*prc))
{
free ((*prc));
(*prc) = NULL;
}
}
/*!
*************************************************************************************
* \brief
* Initialize rate control parameters
*
*************************************************************************************
*/
void rc_init_seq(rc_quadratic *prc)
{
double L1,L2,L3,bpp;
int qp, i;
switch ( input->RCUpdateMode )
{
case RC_MODE_0:
updateQP = updateQPRC0;
break;
case RC_MODE_1:
updateQP = updateQPRC1;
break;
case RC_MODE_2:
updateQP = updateQPRC2;
break;
case RC_MODE_3:
updateQP = updateQPRC3;
break;
default:
updateQP = updateQPRC0;
break;
}
prc->Xp=0;
prc->Xb=0;
prc->bit_rate = (float) input->bit_rate;
prc->frame_rate = (img->framerate *(float)(input->successive_Bframe + 1)) / (float) (input->jumpd + 1);
prc->PrevBitRate = prc->bit_rate;
/*compute the total number of MBs in a frame*/
if(input->basicunit > img->FrameSizeInMbs)
input->basicunit = img->FrameSizeInMbs;
if(input->basicunit < img->FrameSizeInMbs)
prc->TotalNumberofBasicUnit = img->FrameSizeInMbs/input->basicunit;
else
prc->TotalNumberofBasicUnit = 1;
/*initialize the parameters of fluid flow traffic model*/
generic_RC->CurrentBufferFullness = 0;
prc->GOPTargetBufferLevel = (double) generic_RC->CurrentBufferFullness;
/*initialize the previous window size*/
prc->m_windowSize = 0;
prc->MADm_windowSize = 0;
generic_RC->NumberofCodedBFrame = 0;
prc->NumberofCodedPFrame = 0;
generic_RC->NumberofGOP = 0;
/*remaining # of bits in GOP */
generic_RC->RemainingBits = 0;
/*control parameter */
if(input->successive_Bframe>0)
{
prc->GAMMAP=0.25;
prc->BETAP=0.9;
}
else
{
prc->GAMMAP=0.5;
prc->BETAP=0.5;
}
/*quadratic rate-distortion model*/
prc->PPreHeader=0;
prc->Pm_X1 = prc->bit_rate * 1.0;
prc->Pm_X2 = 0.0;
/* linear prediction model for P picture*/
prc->PMADPictureC1 = 1.0;
prc->PMADPictureC2 = 0.0;
// Initialize values
for(i=0;i<21;i++)
{
prc->Pm_rgQp[i] = 0;
prc->Pm_rgRp[i] = 0.0;
prc->PPictureMAD[i] = 0.0;
}
//Define the largest variation of quantization parameters
prc->PMaxQpChange=2;
/*basic unit layer rate control*/
prc->PAveHeaderBits1 = 0;
prc->PAveHeaderBits3 = 0;
prc->DDquant = (prc->TotalNumberofBasicUnit>=9 ? 1 : 2);
prc->MBPerRow = img->PicWidthInMbs;
/*adaptive field/frame coding*/
generic_RC->FieldControl=0;
if (input->SeinitialQP==0)
{
/*compute the initial QP*/
bpp = 1.0*prc->bit_rate /(prc->frame_rate*img->size);
if (img->width == 176)
{
L1 = 0.1;
L2 = 0.3;
L3 = 0.6;
}
else if (img->width == 352)
{
L1 = 0.2;
L2 = 0.6;
L3 = 1.2;
}
else
{
L1 = 0.6;
L2 = 1.4;
L3 = 2.4;
}
if (bpp<= L1)
qp = 35;
else if(bpp<=L2)
qp = 25;
else if(bpp<=L3)
qp = 20;
else
qp = 10;
input->SeinitialQP = qp;
}
}
/*!
*************************************************************************************
* \brief
* Initialize one GOP
*
*************************************************************************************
*/
void rc_init_GOP(rc_quadratic *prc, int np, int nb)
{
Boolean Overum=FALSE;
int OverBits, OverDuantQp;
int AllocatedBits, GOPDquant;
// bit allocation for RC_MODE_3
switch( input->RCUpdateMode )
{
case RC_MODE_3:
{
int sum = 0, tmp, level, levels = 0, num_frames[RC_MAX_TEMPORAL_LEVELS];
float numer, denom;
int gop = input->successive_Bframe + 1;
memset( num_frames, 0, RC_MAX_TEMPORAL_LEVELS * sizeof(int) );
// are there any B frames?
if ( input->successive_Bframe )
{
if ( input->HierarchicalCoding == 1 ) // two layers: even/odd
{
levels = 2;
num_frames[0] = input->successive_Bframe >> 1;
num_frames[1] = (input->successive_Bframe - num_frames[0]) >= 0 ? (input->successive_Bframe - num_frames[0]) : 0;
}
else if ( input->HierarchicalCoding == 2 ) // binary hierarchical structure
{
// check if gop is power of two
tmp = gop;
while ( tmp )
{
sum += tmp & 1;
tmp >>= 1;
}
assert( sum == 1 );
// determine number of levels
levels = 0;
tmp = gop;
while ( tmp > 1 )
{
tmp >>= 1; // divide by 2
num_frames[levels] = 1 << levels;
levels++;
}
assert( levels >= 1 && levels <= RC_MAX_TEMPORAL_LEVELS );
}
else if ( input->HierarchicalCoding == 3 )
{
fprintf(stderr, "\n RCUpdateMode=3 and HierarchicalCoding == 3 are currently not supported"); // This error message should be moved elsewhere and have proper memory deallocation
exit(1);
}
else // all frames of the same priority - level
{
levels = 1;
num_frames[0] = input->successive_Bframe;
}
generic_RC->temporal_levels = levels;
}
else
{
for ( level = 0; level < RC_MAX_TEMPORAL_LEVELS; level++ )
{
input->RCBSliceBitRatio[level] = 0.0F;
}
generic_RC->temporal_levels = 0;
}
// calculate allocated bits for each type of frame
numer = (float)(( (!input->intra_period ? 1 : input->intra_period) * gop) * ((double)input->bit_rate / input->FrameRate));
denom = 0.0F;
for ( level = 0; level < levels; level++ )
{
denom += (float)(num_frames[level] * input->RCBSliceBitRatio[level]);
generic_RC->hierNb[level] = num_frames[level] * np;
}
denom += 1.0F;
if ( input->intra_period >= 1 )
{
denom *= (float)input->intra_period;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -