📄 ratectl.c
字号:
/*!
***************************************************************************
* \file ratectl.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>
*
* \date
* 16 Jan. 2003
**************************************************************************
*/
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "global.h"
#include "ratectl.h"
const double THETA=1.3636;
const int Switch=0;
int Iprev_bits=0;
int Pprev_bits=0;
/* rate control variables */
int Xp, Xb;
static int R,T_field;
static int Np, Nb, bits_topfield;
long T,T1;
//HRD consideration
long UpperBound1, UpperBound2, LowerBound;
double InitialDelayOffset;
const double OMEGA=0.9;
double Wp,Wb;
int TotalPFrame;
int DuantQp;
int PDuantQp;
FILE *BitRate;
double DeltaP;
/*!
*************************************************************************************
* \brief
* Dynamically allocate memory needed for rate control
*
*************************************************************************************
*/
void rc_alloc()
{
img->MADofMB = (double*) calloc (img->FrameSizeInMbs, sizeof (double));
if (NULL==img->MADofMB)
{
no_mem_exit("rc_alloc: img->MADofMB");
}
BUPFMAD = (double*) calloc ((img->FrameSizeInMbs/input->basicunit), sizeof (double));
if (NULL==BUPFMAD)
{
no_mem_exit("rc_alloc: img->BUPFMAD");
}
BUCFMAD = (double*) calloc ((img->FrameSizeInMbs/input->basicunit), sizeof (double));
if (NULL==BUCFMAD)
{
no_mem_exit("rc_alloc: img->BUCFMAD");
}
FCBUCFMAD = (double*) calloc ((img->FrameSizeInMbs/input->basicunit), sizeof (double));
if (NULL==FCBUCFMAD)
{
no_mem_exit("rc_alloc: img->FCBUCFMAD");
}
FCBUPFMAD = (double*) calloc ((img->FrameSizeInMbs/input->basicunit), sizeof (double));
if (NULL==FCBUPFMAD)
{
no_mem_exit("rc_alloc: img->FCBUPFMAD");
}
}
/*!
*************************************************************************************
* \brief
* Free memory needed for rate control
*
*************************************************************************************
*/
void rc_free()
{
if (NULL!=img->MADofMB)
{
free (img->MADofMB);
img->MADofMB = NULL;
}
if (NULL!=BUPFMAD)
{
free (BUPFMAD);
BUPFMAD = NULL;
}
if (NULL!=BUCFMAD)
{
free (BUCFMAD);
BUCFMAD = NULL;
}
if (NULL!=FCBUCFMAD)
{
free (FCBUCFMAD);
FCBUCFMAD = NULL;
}
if (NULL!=FCBUPFMAD)
{
free (FCBUPFMAD);
FCBUPFMAD = NULL;
}
}
/*!
*************************************************************************************
* \brief
* Initialize rate control parameters
*
*************************************************************************************
*/
void rc_init_seq()
{
double L1,L2,L3,bpp;
int qp;
int i;
Xp=0;
Xb=0;
bit_rate=input->bit_rate;
frame_rate = (img->framerate *(float)(input->successive_Bframe + 1)) / (float) (input->jumpd + 1);
PreviousBit_Rate=bit_rate;
/*compute the total number of MBs in a frame*/
img->Frame_Total_Number_MB=img->height*img->width/256;
if(input->basicunit>img->Frame_Total_Number_MB)
input->basicunit=img->Frame_Total_Number_MB;
if(input->basicunit<img->Frame_Total_Number_MB)
TotalNumberofBasicUnit=img->Frame_Total_Number_MB/input->basicunit;
MINVALUE=4.0;
/*initialize the parameters of fluid flow traffic model*/
BufferSize=bit_rate*2.56;
CurrentBufferFullness=0;
GOPTargetBufferLevel=CurrentBufferFullness;
/*HRD consideration*/
InitialDelayOffset=BufferSize*0.8;
/*initialize the previous window size*/
m_windowSize=0;
MADm_windowSize=0;
img->NumberofCodedBFrame=0;
img->NumberofCodedPFrame=0;
img->NumberofGOP=0;
/*remaining # of bits in GOP */
R = 0;
/*control parameter */
if(input->successive_Bframe>0)
{
GAMMAP=0.25;
BETAP=0.9;
}
else
{
GAMMAP=0.5;
BETAP=0.5;
}
/*quadratic rate-distortion model*/
PPreHeader=0;
Pm_X1=bit_rate*1.0;
Pm_X2=0.0;
/* linear prediction model for P picture*/
PMADPictureC1=1.0;
PMADPictureC2=0.0;
for(i=0;i<20;i++)
{
Pm_rgQp[i]=0;
Pm_rgRp[i]=0.0;
PPictureMAD[i]=0.0;
}
PPictureMAD[20]=0.0;
//Define the largest variation of quantization parameters
PDuantQp=2;
/*basic unit layer rate control*/
PAveHeaderBits1=0;
PAveHeaderBits3=0;
if(TotalNumberofBasicUnit>=9)
DDquant=1;
else
DDquant=2;
MBPerRow=img->width/16;
/*adaptive field/frame coding*/
img->FieldControl=0;
RC_MAX_QUANT = 51; // clipping
RC_MIN_QUANT = 0;//clipping
/*compute the initial QP*/
bpp = 1.0*bit_rate /(frame_rate*img->width*img->height);
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 (input->SeinitialQP==0)
{
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(int np, int nb)
{
Boolean Overum=FALSE;
int OverBits;
int OverDuantQp;
int AllocatedBits;
int GOPDquant;
/* 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.*/
if(R<0)
Overum=TRUE;
OverBits=-R;
/*initialize the lower bound and the upper bound for the target bits of each frame, HRD consideration*/
LowerBound=(long)(R+bit_rate/frame_rate);
UpperBound1=(long)(R+InitialDelayOffset);
/*compute the total number of bits for the current GOP*/
AllocatedBits = (int) floor((1 + np + nb) * bit_rate / frame_rate + 0.5);
R +=AllocatedBits;
Np = np;
Nb = nb;
OverDuantQp=(int)(8*OverBits/AllocatedBits+0.5);
GOPOverdue=FALSE;
/*field coding*/
img->IFLAG=1;
/*Compute InitialQp for each GOP*/
TotalPFrame=np;
img->NumberofGOP++;
if(img->NumberofGOP==1)
{
MyInitialQp=input->SeinitialQP;
PreviousQp2=MyInitialQp-1; //recent change -0;
QPLastGOP=MyInitialQp;
}
else
{
/*adaptive field/frame coding*/
if((input->PicInterlace==ADAPTIVE_CODING)\
||(input->MbInterlace))
{
if (img->FieldFrame == 1)
{
img->TotalQpforPPicture += FrameQPBuffer;
QPLastPFrame = FrameQPBuffer;
}
else
{
img->TotalQpforPPicture += FieldQPBuffer;
QPLastPFrame = FieldQPBuffer;
}
}
/*compute the average QP of P frames in the previous GOP*/
PAverageQp=(int)(1.0*img->TotalQpforPPicture/img->NumberofPPicture+0.5);
GOPDquant=(int)(0.5+1.0*(np+nb+1)/15);
if(GOPDquant>2)
GOPDquant=2;
PAverageQp-=GOPDquant;
if (PAverageQp > (QPLastPFrame - 2))
PAverageQp--;
PAverageQp = MAX(QPLastGOP-2, PAverageQp);
PAverageQp = MIN(QPLastGOP+2, PAverageQp);
PAverageQp = MIN(RC_MAX_QUANT, PAverageQp);
PAverageQp = MAX(RC_MIN_QUANT, PAverageQp);
MyInitialQp=PAverageQp;
QPLastGOP = MyInitialQp;
Pm_Qp=PAverageQp;
PAveFrameQP=PAverageQp;
PreviousQp1=PreviousQp2;
PreviousQp2=MyInitialQp-1;
}
img->TotalQpforPPicture=0;
img->NumberofPPicture=0;
NumberofBFrames=0;
}
/*!
*************************************************************************************
* \brief
* Initialize one picture
*
*************************************************************************************
*/
void rc_init_pict(int fieldpic,int topfield,int targetcomputation)
{
int i;
/* compute the total number of basic units in a frame */
if(input->MbInterlace)
TotalNumberofBasicUnit=img->Frame_Total_Number_MB/img->BasicUnit;
img->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(input->channel_type==1)
{
if(img->NumberofCodedPFrame==58)
bit_rate *=1.5;
else if(img->NumberofCodedPFrame==59)
PreviousBit_Rate=bit_rate;
}
/* predefine a target buffer level for each frame */
if((fieldpic||topfield)&&targetcomputation)
{
switch (img->type)
{
case P_SLICE:
/* Since the available bandwidth may vary at any time, the total number of
bits is updated picture by picture*/
if(PreviousBit_Rate!=bit_rate)
R +=(int) floor((bit_rate-PreviousBit_Rate)*(Np+Nb)/frame_rate+0.5);
/* predefine the target buffer level for each picture.
frame layer rate control */
if(img->BasicUnit==img->Frame_Total_Number_MB)
{
if(img->NumberofPPicture==1)
{
TargetBufferLevel=CurrentBufferFullness;
DeltaP=(CurrentBufferFullness-GOPTargetBufferLevel)/(TotalPFrame-1);
TargetBufferLevel -=DeltaP;
}
else if(img->NumberofPPicture>1)
TargetBufferLevel -=DeltaP;
}
/* basic unit layer rate control */
else
{
if(img->NumberofCodedPFrame>0)
{
/* adaptive frame/filed coding */
if(((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))\
&&(img->FieldControl==1))
{
for(i=0;i<TotalNumberofBasicUnit;i++)
FCBUPFMAD[i]=FCBUCFMAD[i];
}
else
{
for(i=0;i<TotalNumberofBasicUnit;i++)
BUPFMAD[i]=BUCFMAD[i];
}
}
if(img->NumberofGOP==1)
{
if(img->NumberofPPicture==1)
{
TargetBufferLevel=CurrentBufferFullness;
DeltaP=(CurrentBufferFullness-GOPTargetBufferLevel)/(TotalPFrame-1);
TargetBufferLevel -=DeltaP;
}
else if(img->NumberofPPicture>1)
TargetBufferLevel -=DeltaP;
}
else if(img->NumberofGOP>1)
{
if(img->NumberofPPicture==0)
{
TargetBufferLevel=CurrentBufferFullness;
DeltaP=(CurrentBufferFullness-GOPTargetBufferLevel)/TotalPFrame;
TargetBufferLevel -=DeltaP;
}
else if(img->NumberofPPicture>0)
TargetBufferLevel -=DeltaP;
}
}
if(img->NumberofCodedPFrame==1)
AWp=Wp;
if((img->NumberofCodedPFrame<8)&&(img->NumberofCodedPFrame>1))
AWp=Wp*(img->NumberofCodedPFrame-1)/img->NumberofCodedPFrame+\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -