blob: 59f54082d8d2f5f8e7bcf1b177209528d8a1cba3 [file] [log] [blame]
/*!
***************************************************************************
* \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>
* - 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->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 = 51;
lprc->RC_MIN_QUANT = -img->bitdepth_luma_qp_scale;//clipping
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;
/*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;
generic_RC->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->PDuantQp=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;
/*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 (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(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;
denom += (float)input->RCISliceBitRatio - 1.0F;
}
// set bit targets for each type of frame
generic_RC->RCPSliceBits = (int) floor( numer / denom + 0.5F );
generic_RC->RCISliceBits = (input->intra_period) ? (int)(input->RCISliceBitRatio * generic_RC->RCPSliceBits + 0.5) : 0;
for ( level = 0; level < levels; level++ )
{
generic_RC->RCBSliceBits[level] = (int)floor(input->RCBSliceBitRatio[level] * generic_RC->RCPSliceBits + 0.5);
}
generic_RC->NIslice = (input->intra_period) ? ((input->no_frames - 1) / input->intra_period) : 0;
generic_RC->NPslice = input->no_frames - 1 - generic_RC->NIslice;
}
break;
default:
break;
}
/* 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(generic_RC->RemainingBits<0)
Overum=TRUE;
OverBits=-generic_RC->RemainingBits;
/*initialize the lower bound and the upper bound for the target bits of each frame, HRD consideration*/
prc->LowerBound = (int)(generic_RC->RemainingBits + prc->bit_rate / prc->frame_rate);
prc->UpperBound1 = (int)(generic_RC->RemainingBits + (prc->bit_rate * 2.048));
/*compute the total number of bits for the current GOP*/
AllocatedBits = (int) floor((1 + np + nb) * prc->bit_rate / prc->frame_rate + 0.5);
generic_RC->RemainingBits += AllocatedBits;
prc->Np = np;
prc->Nb = nb;
OverDuantQp=(int)(8 * OverBits/AllocatedBits+0.5);
prc->GOPOverdue=FALSE;
/*field coding*/
//generic_RC->NoGranularFieldRC = ( input->PicInterlace || !input->MbInterlace || input->basicunit != img->FrameSizeInMbs );
if ( !input->PicInterlace && input->MbInterlace && input->basicunit == img->FrameSizeInMbs )
generic_RC->NoGranularFieldRC = 0;
else
generic_RC->NoGranularFieldRC = 1;
/*Compute InitialQp for each GOP*/
prc->TotalPFrame=np;
generic_RC->NumberofGOP++;
if(generic_RC->NumberofGOP==1)
{
prc->MyInitialQp = input->SeinitialQP;
prc->CurrLastQP = prc->MyInitialQp - 1; //recent change -0;
prc->QPLastGOP = prc->MyInitialQp;
prc->PAveFrameQP = prc->MyInitialQp;
prc->m_Qc = prc->PAveFrameQP;
prc->FieldQPBuffer = prc->PAveFrameQP;
prc->FrameQPBuffer = prc->PAveFrameQP;
prc->PAverageQp = prc->PAveFrameQP;
}
else
{
/*adaptive field/frame coding*/
if( input->PicInterlace == ADAPTIVE_CODING || input->MbInterlace )
{
if (generic_RC->FieldFrame == 1)
{
generic_RC->TotalQpforPPicture += prc->FrameQPBuffer;
prc->QPLastPFrame = prc->FrameQPBuffer;
}
else
{
generic_RC->TotalQpforPPicture += prc->FieldQPBuffer;
prc->QPLastPFrame = prc->FieldQPBuffer;
}
}
/*compute the average QP of P frames in the previous GOP*/
prc->PAverageQp=(int)(1.0 * generic_RC->TotalQpforPPicture / generic_RC->NumberofPPicture+0.5);
GOPDquant=(int)((1.0*(np+nb+1)/15.0) + 0.5);
if(GOPDquant>2)
GOPDquant=2;
prc->PAverageQp -= GOPDquant;
if (prc->PAverageQp > (prc->QPLastPFrame - 2))
prc->PAverageQp--;
// QP is constrained by QP of previous QP
prc->PAverageQp = iClip3(prc->QPLastGOP - 2, prc->QPLastGOP + 2, prc->PAverageQp);
// Also clipped within range.
prc->PAverageQp = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->PAverageQp);
prc->MyInitialQp = prc->PAverageQp;
prc->Pm_Qp = prc->PAverageQp;
prc->PAveFrameQP = prc->PAverageQp;
prc->QPLastGOP = prc->MyInitialQp;
prc->PrevLastQP = prc->CurrLastQP;
prc->CurrLastQP = prc->MyInitialQp - 1;
}
generic_RC->TotalQpforPPicture=0;
generic_RC->NumberofPPicture=0;
prc->NumberofBFrames=0;
}
/*!
*************************************************************************************
* \brief
* Initialize one picture
*
*************************************************************************************
*/
void rc_init_pict(rc_quadratic *prc, int fieldpic,int topfield,int targetcomputation, float mult)
{
int tmp_T;
/* compute the total number of basic units in a frame */
if(input->MbInterlace)
prc->TotalNumberofBasicUnit = img->FrameSizeInMbs / 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(generic_RC->NumberofCodedPFrame==58)
prc->bit_rate *= 1.5;
else if(generic_RC->NumberofCodedPFrame==59)
prc->PrevBitRate = prc->bit_rate;
}
/* predefine a target buffer level for each frame */
if((fieldpic||topfield) && targetcomputation)
{
if ( (img->type == P_SLICE || input->RCUpdateMode == RC_MODE_1) && (IMG_NUMBER) )
{
/* Since the available bandwidth may vary at any time, the total number of
bits is updated picture by picture*/
if(prc->PrevBitRate!=prc->bit_rate)
generic_RC->RemainingBits +=(int) floor((prc->bit_rate-prc->PrevBitRate)*(prc->Np + prc->Nb)/prc->frame_rate+0.5);
/* predefine the target buffer level for each picture.
frame layer rate control */
if(img->BasicUnit==img->FrameSizeInMbs)
{
if(generic_RC->NumberofPPicture==1)
{
prc->TargetBufferLevel = (double) generic_RC->CurrentBufferFullness;
prc->DeltaP = (generic_RC->CurrentBufferFullness - prc->GOPTargetBufferLevel) / (prc->TotalPFrame-1);
prc->TargetBufferLevel -= prc->DeltaP;
}
else if(generic_RC->NumberofPPicture>1)
prc->TargetBufferLevel -= prc->DeltaP;
}
/* basic unit layer rate control */
else
{
if(generic_RC->NumberofCodedPFrame>0)
{
/* adaptive frame/field coding */
if(((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))&&(generic_RC->FieldControl==1))
memcpy((void *)prc->FCBUPFMAD,(void *)prc->FCBUCFMAD, prc->TotalNumberofBasicUnit * sizeof(double));
else
memcpy((void *)prc->BUPFMAD,(void *)prc->BUCFMAD, prc->TotalNumberofBasicUnit * sizeof(double));
}
if(generic_RC->NumberofGOP==1)
{
if(generic_RC->NumberofPPicture==1)
{
prc->TargetBufferLevel = (double) generic_RC->CurrentBufferFullness;
prc->DeltaP = (generic_RC->CurrentBufferFullness - prc->GOPTargetBufferLevel)/(prc->TotalPFrame - 1);
prc->TargetBufferLevel -= prc->DeltaP;
}
else if(generic_RC->NumberofPPicture>1)
prc->TargetBufferLevel -= prc->DeltaP;
}
else if(generic_RC->NumberofGOP>1)
{
if(generic_RC->NumberofPPicture==0)
{
prc->TargetBufferLevel = (double) generic_RC->CurrentBufferFullness;
prc->DeltaP = (generic_RC->CurrentBufferFullness - prc->GOPTargetBufferLevel) / prc->TotalPFrame;
prc->TargetBufferLevel -= prc->DeltaP;
}
else if(generic_RC->NumberofPPicture>0)
prc->TargetBufferLevel -= prc->DeltaP;
}
}
if(generic_RC->NumberofCodedPFrame==1)
prc->AveWp = prc->Wp;
if((generic_RC->NumberofCodedPFrame<8)&&(generic_RC->NumberofCodedPFrame>1))
prc->AveWp = (prc->AveWp + prc->Wp * (generic_RC->NumberofCodedPFrame-1))/generic_RC->NumberofCodedPFrame;
else if(generic_RC->NumberofCodedPFrame>1)
prc->AveWp = (prc->Wp + 7 * prc->AveWp) / 8;
// compute the average complexity of B frames
if(input->successive_Bframe>0)
{
// compute the target buffer level
prc->TargetBufferLevel += (prc->AveWp * (input->successive_Bframe + 1)*prc->bit_rate\
/(prc->frame_rate*(prc->AveWp+prc->AveWb*input->successive_Bframe))-prc->bit_rate/prc->frame_rate);
}
}
else if ( img->type == B_SLICE )
{
/* update the total number of bits if the bandwidth is changed*/
if(prc->PrevBitRate != prc->bit_rate)
generic_RC->RemainingBits +=(int) floor((prc->bit_rate-prc->PrevBitRate) * (prc->Np + prc->Nb) / prc->frame_rate+0.5);
if((generic_RC->NumberofCodedPFrame==1)&&(generic_RC->NumberofCodedBFrame==1))
{
prc->AveWp = prc->Wp;
prc->AveWb = prc->Wb;
}
else if(generic_RC->NumberofCodedBFrame > 1)
{
//compute the average weight
if(generic_RC->NumberofCodedBFrame<8)
prc->AveWb = (prc->AveWb + prc->Wb*(generic_RC->NumberofCodedBFrame-1)) / generic_RC->NumberofCodedBFrame;
else
prc->AveWb = (prc->Wb + 7 * prc->AveWb) / 8;
}
}
/* Compute the target bit for each frame */
if( (img->type==P_SLICE || input->RCUpdateMode == RC_MODE_1 || input->RCUpdateMode == RC_MODE_3 ) && (IMG_NUMBER) )
{
/* frame layer rate control */
if(img->BasicUnit==img->FrameSizeInMbs || (input->RCUpdateMode == RC_MODE_3) )
{
if(generic_RC->NumberofCodedPFrame>0)
{
if (input->RCUpdateMode == RC_MODE_3)
{
int level_idx = (img->type == B_SLICE && input->HierarchicalCoding) ? (generic_RC->temporal_levels - 1 - gop_structure[img->b_frame_to_code-1].hierarchy_layer) : 0;
int bitrate = (img->type == B_SLICE) ? generic_RC->RCBSliceBits[ level_idx ]
: ( img->type == P_SLICE ? generic_RC->RCPSliceBits : generic_RC->RCISliceBits );
int level, denom = generic_RC->NIslice * generic_RC->RCISliceBits + generic_RC->NPslice * generic_RC->RCPSliceBits;
if ( input->HierarchicalCoding )
{
for ( level = 0; level < generic_RC->temporal_levels; level++ )
denom += generic_RC->hierNb[ level ] * generic_RC->RCBSliceBits[ level ];
}
else
{
denom += generic_RC->hierNb[0] * generic_RC->RCBSliceBits[0];
}
// target due to remaining bits
prc->Target = (int) floor( (float)(1.0 * bitrate * generic_RC->RemainingBits) / (float)denom + 0.5F );
// target given original taget rate and buffer considerations
tmp_T = imax(0, (int) floor( (double)bitrate - prc->GAMMAP * (generic_RC->CurrentBufferFullness-prc->TargetBufferLevel) + 0.5) );
// translate Target rate from B or I "domain" to P domain since the P RC model is going to be used to select the QP
// for hierarchical coding adjust the target QP to account for different temporal levels
switch( img->type )
{
case B_SLICE:
prc->Target = (int) floor( (float)prc->Target / input->RCBoverPRatio + 0.5F);
break;
case I_SLICE:
prc->Target = (int) floor( (float)prc->Target / (input->RCIoverPRatio * 4.0) + 0.5F); // 4x accounts for the fact that header bits reduce the percentage of texture
break;
case P_SLICE:
default:
break;
}
}
else
{
prc->Target = (int) floor( prc->Wp * generic_RC->RemainingBits / (prc->Np * prc->Wp + prc->Nb * prc->Wb) + 0.5);
tmp_T = imax(0, (int) floor(prc->bit_rate / prc->frame_rate - prc->GAMMAP * (generic_RC->CurrentBufferFullness-prc->TargetBufferLevel) + 0.5));
prc->Target = (int) floor(prc->BETAP * (prc->Target - tmp_T) + tmp_T + 0.5);
}
}
}
/* basic unit layer rate control */
else
{
if(((generic_RC->NumberofGOP == 1)&&(generic_RC->NumberofCodedPFrame>0))
|| (generic_RC->NumberofGOP > 1))
{
prc->Target = (int) (floor( prc->Wp * generic_RC->RemainingBits / (prc->Np * prc->Wp + prc->Nb * prc->Wb) + 0.5));
tmp_T = imax(0, (int) (floor(prc->bit_rate / prc->frame_rate - prc->GAMMAP * (generic_RC->CurrentBufferFullness-prc->TargetBufferLevel) + 0.5)));
prc->Target = (int) (floor(prc->BETAP * (prc->Target - tmp_T) + tmp_T + 0.5));
}
}
prc->Target = (int)(mult * prc->Target);
/* reserve some bits for smoothing */
prc->Target = (int)((1.0 - 0.0 * input->successive_Bframe) * prc->Target);
/* HRD consideration */
if ( input->RCUpdateMode != RC_MODE_3 || img->type == P_SLICE )
prc->Target = iClip3(prc->LowerBound,prc->UpperBound2, prc->Target);
if((topfield) || (fieldpic && ((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))))
prc->TargetField=prc->Target;
}
}
if(fieldpic || topfield)
{
/* frame layer rate control */
generic_RC->NumberofHeaderBits = 0;
generic_RC->NumberofTextureBits = 0;
/* basic unit layer rate control */
if(img->BasicUnit<img->FrameSizeInMbs)
{
prc->TotalFrameQP = 0;
generic_RC->NumberofBasicUnitHeaderBits = 0;
generic_RC->NumberofBasicUnitTextureBits = 0;
generic_RC->TotalMADBasicUnit = 0;
if(generic_RC->FieldControl==0)
prc->NumberofBasicUnit = prc->TotalNumberofBasicUnit;
else
prc->NumberofBasicUnit = prc->TotalNumberofBasicUnit >> 1;
}
}
if( ( img->type==P_SLICE || input->RCUpdateMode == RC_MODE_1 ) && img->BasicUnit < img->FrameSizeInMbs && generic_RC->FieldControl == 1 && (IMG_NUMBER) )
{
/* top field at basic unit layer rate control */
if(topfield)
{
prc->bits_topfield=0;
prc->Target=(int)(prc->TargetField*0.6);
}
/* bottom field at basic unit layer rate control */
else
{
prc->Target=prc->TargetField-prc->bits_topfield;
generic_RC->NumberofBasicUnitHeaderBits=0;
generic_RC->NumberofBasicUnitTextureBits=0;
generic_RC->TotalMADBasicUnit=0;
prc->NumberofBasicUnit=prc->TotalNumberofBasicUnit >> 1;
}
}
}
/*!
*************************************************************************************
* \brief
* update one picture after frame/field encoding
*
* \param nbits
* number of bits used for picture
*
*************************************************************************************
*/
void rc_update_pict(rc_quadratic *prc, int nbits)
{
int delta_bits = (nbits - (int)floor(prc->bit_rate / prc->frame_rate + 0.5F) );
generic_RC->RemainingBits -= nbits; /* remaining # of bits in GOP */
generic_RC->CurrentBufferFullness += delta_bits;
/*update the lower bound and the upper bound for the target bits of each frame, HRD consideration*/
prc->LowerBound -= (int) delta_bits;
prc->UpperBound1 -= (int) delta_bits;
prc->UpperBound2 = (int)(OMEGA * prc->UpperBound1);
return;
}
int updateComplexity( rc_quadratic *prc, Boolean is_updated, int nbits )
{
double Avem_Qc;
/* frame layer rate control */
if(img->BasicUnit == img->FrameSizeInMbs)
return ((int) floor(nbits * prc->m_Qc + 0.5));
/* basic unit layer rate control */
else
{
if( is_updated )
{
if( (generic_RC->NoGranularFieldRC == 0 && generic_RC->FieldControl == 1) || generic_RC->FieldControl == 0 )
{
Avem_Qc = (double)prc->TotalFrameQP / (double)prc->TotalNumberofBasicUnit;
return ((int)floor(nbits * Avem_Qc + 0.5));
}
}
else if( img->type == B_SLICE )
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;
generic_RC->NumberofCodedPFrame++;
generic_RC->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 && (IMG_NUMBER)), nbits );
if ( img->type == P_SLICE && (IMG_NUMBER) )
{
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), nbits );
if ( (IMG_NUMBER) )
{
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 && (IMG_NUMBER)), nbits );
if (img->type == I_SLICE && IMG_NUMBER)
generic_RC->NIslice--;
if ( (img->type == P_SLICE) && (IMG_NUMBER) )
{
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 = generic_RC->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) )
{
/*frame layer rate control*/
if(img->BasicUnit == img->FrameSizeInMbs)
{
prc->CurrentFrameMAD = ComputeFrameMAD();
m_Nc=generic_RC->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 = generic_RC->NumberofCodedPFrame * prc->TotalNumberofBasicUnit + prc->CodedBasicUnit;
else
m_Nc = (generic_RC->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) )
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) )
{
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 = generic_RC->NumberofCodedPFrame;
static Boolean PictureRejected[RC_MODEL_HISTORY];
static double error [RC_MODEL_HISTORY];
if(generic_RC->NumberofCodedPFrame>0)
{
//assert (img->type!=P_SLICE);
/*frame layer rate control*/
if(img->BasicUnit == img->FrameSizeInMbs)
m_Nc=generic_RC->NumberofCodedPFrame;
/*basic unit layer rate control*/
else
m_Nc=generic_RC->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) )
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)
{
int n_realSize = n_windowSize;
int i;
double oneSampleQ = 0.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 (PictureRejected[i])
n_realSize--;
}
// default MAD model estimation results
prc->MADPictureC1 = prc->MADPictureC2 = 0.0;
for (i = 0; i < n_windowSize; i++)
{
if (!PictureRejected[i])
oneSampleQ = prc->PictureMAD[i];
}
for (i = 0; i < n_windowSize; i++)
{// if all non-rejected MAD are the same, take 1st order model
if ((prc->PictureMAD[i] != oneSampleQ) && !PictureRejected[i])
estimateX2 = TRUE;
if (!PictureRejected[i])
prc->MADPictureC1 += prc->PictureMAD[i] / (prc->ReferenceMAD[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 (!PictureRejected[i])
{
a00 = a00 + 1.0;
a01 += prc->ReferenceMAD[i];
a10 = a01;
a11 += prc->ReferenceMAD[i] * prc->ReferenceMAD[i];
b0 += prc->PictureMAD[i];
b1 += prc->PictureMAD[i] * prc->ReferenceMAD[i];
}
}
// solve the equation of AX = B
MatrixValue = a00 * a11 - a01 * a10;
if(fabs(MatrixValue) > 0.000001)
{
prc->MADPictureC2 = (b0 * a11 - b1 * a01) / MatrixValue;
prc->MADPictureC1 = (b1 * a00 - b0 * a10) / MatrixValue;
}
else
{
prc->MADPictureC1 = b0/a01;
prc->MADPictureC2 = 0.0;
}
}
if( (img->type == P_SLICE || input->RCUpdateMode == RC_MODE_1) && (IMG_NUMBER) )
{
prc->PMADPictureC1 = prc->MADPictureC1;
prc->PMADPictureC2 = prc->MADPictureC2;
}
}
/*!
*************************************************************************************
* \brief
* compute a quantization parameter for each frame (RC_MODE_0)
*
*************************************************************************************
*/
int updateQPRC0(rc_quadratic *prc, int topfield)
{
int m_Bits;
int BFrameNumber;
int StepSize;
int SumofBasicUnit;
int DuantQp, m_Qp, m_Hp;
/* frame layer rate control */
if(img->BasicUnit==img->FrameSizeInMbs )
{
/* fixed quantization parameter is used to coded I frame, the first P frame and the first B frame
the quantization parameter is adjusted according the available channel bandwidth and
the type of video */
/*top field*/
if((topfield) || (generic_RC->FieldControl==0))
{
if (img->type==I_SLICE)
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else if(img->type == B_SLICE)
{
if(input->successive_Bframe==1)
{
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
prc->m_Qc = imin(prc->PrevLastQP, prc->CurrLastQP) + 2;
prc->m_Qc = imax(prc->m_Qc, imax(prc->PrevLastQP, prc->CurrLastQP));
prc->m_Qc = imax(prc->m_Qc, prc->CurrLastQP + 1);
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
else
{
BFrameNumber = (prc->NumberofBFrames + 1) % input->successive_Bframe;
if(BFrameNumber==0)
BFrameNumber = input->successive_Bframe;
/*adaptive field/frame coding*/
if(BFrameNumber==1)
{
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
}
if((prc->CurrLastQP-prc->PrevLastQP)<=(-2*input->successive_Bframe-3))
StepSize=-3;
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe-2))
StepSize=-2;
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe-1))
StepSize=-1;
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe))
StepSize=0;
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe+1))
StepSize=1;
else
StepSize=2;
prc->m_Qc = prc->PrevLastQP + StepSize;
prc->m_Qc += iClip3( -2 * (BFrameNumber - 1), 2*(BFrameNumber-1),
(BFrameNumber-1)*(prc->CurrLastQP-prc->PrevLastQP)/(input->successive_Bframe-1));
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
return prc->m_Qc;
}
else if( img->type == P_SLICE && generic_RC->NumberofPPicture == 0 && (IMG_NUMBER) )
{
prc->m_Qc=prc->MyInitialQp;
if(generic_RC->FieldControl==0)
updateQPNonPicAFF( prc );
return prc->m_Qc;
}
else
{
/*adaptive field/frame coding*/
if( ( input->PicInterlace == ADAPTIVE_CODING || input->MbInterlace ) && generic_RC->FieldControl == 0 )
updateQPInterlaceBU( prc );
prc->m_X1 = prc->Pm_X1;
prc->m_X2 = prc->Pm_X2;
prc->MADPictureC1 = prc->PMADPictureC1;
prc->MADPictureC2 = prc->PMADPictureC2;
prc->PreviousPictureMAD = prc->PPictureMAD[0];
DuantQp = prc->PDuantQp;
m_Qp = prc->Pm_Qp;
m_Hp = prc->PPreHeader;
/* predict the MAD of current picture*/
prc->CurrentFrameMAD=prc->MADPictureC1*prc->PreviousPictureMAD + prc->MADPictureC2;
/*compute the number of bits for the texture*/
if(prc->Target < 0)
{
prc->m_Qc=m_Qp+DuantQp;
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
else
{
m_Bits = prc->Target-m_Hp;
m_Bits = imax(m_Bits, (int)(prc->bit_rate/(MINVALUE*prc->frame_rate)));
updateModelQPFrame( prc, m_Bits );
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // clipping
prc->m_Qc = iClip3(m_Qp-DuantQp, m_Qp+DuantQp, prc->m_Qc); // control variation
}
if( generic_RC->FieldControl == 0 )
updateQPNonPicAFF( prc );
return prc->m_Qc;
}
}
/*bottom field*/
else
{
if( img->type==P_SLICE && generic_RC->NoGranularFieldRC == 0 && (IMG_NUMBER) )
updateBottomField( prc );
return prc->m_Qc;
}
}
/*basic unit layer rate control*/
else
{
/*top field of I frame*/
if (img->type==I_SLICE || (!IMG_NUMBER))
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else if( img->type == B_SLICE )
{
/*top field of B frame*/
if((topfield)||(generic_RC->FieldControl==0))
{
if(input->successive_Bframe==1)
{
/*adaptive field/frame coding*/
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
if(prc->PrevLastQP==prc->CurrLastQP)
prc->m_Qc=prc->PrevLastQP+2;
else
prc->m_Qc=(prc->PrevLastQP+prc->CurrLastQP)/2+1;
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
else
{
BFrameNumber=(prc->NumberofBFrames+1)%input->successive_Bframe;
if(BFrameNumber==0)
BFrameNumber=input->successive_Bframe;
/*adaptive field/frame coding*/
if(BFrameNumber==1)
{
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
}
if((prc->CurrLastQP-prc->PrevLastQP)<=(-2*input->successive_Bframe-3))
StepSize=-3;
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe-2))
StepSize=-2;
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe-1))
StepSize=-1;
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe))
StepSize=0;//0
else if((prc->CurrLastQP-prc->PrevLastQP)==(-2*input->successive_Bframe+1))
StepSize=1;//1
else
StepSize=2;//2
prc->m_Qc=prc->PrevLastQP+StepSize;
prc->m_Qc +=
iClip3( -2*(BFrameNumber-1), 2*(BFrameNumber-1), (BFrameNumber-1)*(prc->CurrLastQP-prc->PrevLastQP)/(input->successive_Bframe-1) );
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
return prc->m_Qc;
}
/*bottom field of B frame*/
else
{
return prc->m_Qc;
}
}
else if( img->type == P_SLICE )
{
if( generic_RC->NumberofGOP == 1 && generic_RC->NumberofPPicture == 0 )
{
if((generic_RC->FieldControl==0)||((generic_RC->FieldControl==1) && (generic_RC->NoGranularFieldRC==0)))
return updateFirstP( prc, topfield );
}
else
{
prc->m_X1=prc->Pm_X1;
prc->m_X2=prc->Pm_X2;
prc->MADPictureC1=prc->PMADPictureC1;
prc->MADPictureC2=prc->PMADPictureC2;
m_Qp=prc->Pm_Qp;
if(generic_RC->FieldControl==0)
SumofBasicUnit=prc->TotalNumberofBasicUnit;
else
SumofBasicUnit=prc->TotalNumberofBasicUnit>>1;
/*the average QP of the previous frame is used to coded the first basic unit of the current frame or field*/
if(prc->NumberofBasicUnit==SumofBasicUnit)
return updateFirstBU( prc, topfield );
else
{
/*compute the number of remaining bits*/
prc->Target -= (generic_RC->NumberofBasicUnitHeaderBits + generic_RC->NumberofBasicUnitTextureBits);
generic_RC->NumberofBasicUnitHeaderBits = 0;
generic_RC->NumberofBasicUnitTextureBits = 0;
if(prc->Target<0)
return updateNegativeTarget( prc, topfield, m_Qp );
else
{
/*predict the MAD of current picture*/
predictCurrPicMAD( prc );
/*compute the total number of bits for the current basic unit*/
updateModelQPBU( prc, topfield, m_Qp );
prc->TotalFrameQP +=prc->m_Qc;
prc->Pm_Qp=prc->m_Qc;
prc->NumberofBasicUnit--;
if( prc->NumberofBasicUnit == 0 && img->type == P_SLICE && (IMG_NUMBER) )
updateLastBU( prc, topfield );
return prc->m_Qc;
}
}
}
}
}
return prc->m_Qc;
}
/*!
*************************************************************************************
* \brief
* compute a quantization parameter for each frame
*
*************************************************************************************
*/
int updateQPRC1(rc_quadratic *prc, int topfield)
{
int m_Bits;
int SumofBasicUnit;
int DuantQp, m_Qp, m_Hp;
/* frame layer rate control */
if(img->BasicUnit == img->FrameSizeInMbs)
{
/* fixed quantization parameter is used to coded I frame, the first P frame and the first B frame
the quantization parameter is adjusted according the available channel bandwidth and
the type of vide */
/*top field*/
if((topfield) || (generic_RC->FieldControl==0))
{
if ((!IMG_NUMBER))
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else if( generic_RC->NumberofPPicture == 0 && (IMG_NUMBER) )
{
prc->m_Qc=prc->MyInitialQp;
if(generic_RC->FieldControl==0)
updateQPNonPicAFF( prc );
return prc->m_Qc;
}
else
{
/*adaptive field/frame coding*/
if( ( input->PicInterlace == ADAPTIVE_CODING || input->MbInterlace ) && generic_RC->FieldControl == 0 )
updateQPInterlaceBU( prc );
prc->m_X1 = prc->Pm_X1;
prc->m_X2 = prc->Pm_X2;
prc->MADPictureC1 = prc->PMADPictureC1;
prc->MADPictureC2 = prc->PMADPictureC2;
prc->PreviousPictureMAD = prc->PPictureMAD[0];
DuantQp = prc->PDuantQp;
m_Qp = prc->Pm_Qp;
m_Hp = prc->PPreHeader;
/* predict the MAD of current picture*/
prc->CurrentFrameMAD=prc->MADPictureC1*prc->PreviousPictureMAD + prc->MADPictureC2;
/*compute the number of bits for the texture*/
if(prc->Target < 0)
{
prc->m_Qc=m_Qp+DuantQp;
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
else
{
m_Bits = prc->Target-m_Hp;
m_Bits = imax(m_Bits, (int)(prc->bit_rate/(MINVALUE*prc->frame_rate)));
updateModelQPFrame( prc, m_Bits );
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // clipping
prc->m_Qc = iClip3(m_Qp-DuantQp, m_Qp+DuantQp, prc->m_Qc); // control variation
}
if( generic_RC->FieldControl == 0 )
updateQPNonPicAFF( prc );
return prc->m_Qc;
}
}
/*bottom field*/
else
{
if( generic_RC->NoGranularFieldRC == 0 && (IMG_NUMBER) )
updateBottomField( prc );
return prc->m_Qc;
}
}
/*basic unit layer rate control*/
else
{
/*top field of I frame*/
if ((!IMG_NUMBER))
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else
{
if((generic_RC->NumberofGOP==1)&&(generic_RC->NumberofPPicture==0))
{
if((generic_RC->FieldControl==0)||((generic_RC->FieldControl==1) && (generic_RC->NoGranularFieldRC==0)))
return updateFirstP( prc, topfield );
}
else
{
prc->m_X1=prc->Pm_X1;
prc->m_X2=prc->Pm_X2;
prc->MADPictureC1=prc->PMADPictureC1;
prc->MADPictureC2=prc->PMADPictureC2;
m_Qp=prc->Pm_Qp;
if(generic_RC->FieldControl==0)
SumofBasicUnit=prc->TotalNumberofBasicUnit;
else
SumofBasicUnit=prc->TotalNumberofBasicUnit>>1;
/*the average QP of the previous frame is used to coded the first basic unit of the current frame or field*/
if(prc->NumberofBasicUnit==SumofBasicUnit)
return updateFirstBU( prc, topfield );
else
{
/*compute the number of remaining bits*/
prc->Target -= (generic_RC->NumberofBasicUnitHeaderBits + generic_RC->NumberofBasicUnitTextureBits);
generic_RC->NumberofBasicUnitHeaderBits = 0;
generic_RC->NumberofBasicUnitTextureBits = 0;
if(prc->Target<0)
return updateNegativeTarget( prc, topfield, m_Qp );
else
{
/*predict the MAD of current picture*/
predictCurrPicMAD( prc );
/*compute the total number of bits for the current basic unit*/
updateModelQPBU( prc, topfield, m_Qp );
prc->TotalFrameQP +=prc->m_Qc;
prc->Pm_Qp=prc->m_Qc;
prc->NumberofBasicUnit--;
if((prc->NumberofBasicUnit==0) && (IMG_NUMBER) )
updateLastBU( prc, topfield );
return prc->m_Qc;
}
}
}
}
}
return prc->m_Qc;
}
/*!
*************************************************************************************
* \brief
* compute a quantization parameter for each frame
*
*************************************************************************************
*/
int updateQPRC2(rc_quadratic *prc, int topfield)
{
int m_Bits;
int SumofBasicUnit;
int DuantQp, m_Qp, m_Hp;
/* frame layer rate control */
if(img->BasicUnit==img->FrameSizeInMbs )
{
/* fixed quantization parameter is used to coded I frame, the first P frame and the first B frame
the quantization parameter is adjusted according the available channel bandwidth and
the type of vide */
/*top field*/
if((topfield) || (generic_RC->FieldControl==0))
{
if ((!IMG_NUMBER))
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else if (img->type==I_SLICE)
{
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
prc->m_Qc = prc->CurrLastQP; // Set QP to average qp of last P frame
return prc->m_Qc;
}
else if(img->type == B_SLICE)
{
int prevQP = imax(prc->PrevLastQP, prc->CurrLastQP);
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
if (input->HierarchicalCoding)
{
if (img->b_frame_to_code == 0)
prc->m_Qc = prevQP;
else
prc->m_Qc = prevQP + img->GopLevels - gop_structure[img->b_frame_to_code-1].hierarchy_layer;
}
else
prc->m_Qc = prevQP + 2 - img->nal_reference_idc;
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
return prc->m_Qc;
}
else if( img->type == P_SLICE && generic_RC->NumberofPPicture == 0 && (IMG_NUMBER) )
{
prc->m_Qc=prc->MyInitialQp;
if(generic_RC->FieldControl==0)
updateQPNonPicAFF( prc );
return prc->m_Qc;
}
else
{
/*adaptive field/frame coding*/
if( ( input->PicInterlace == ADAPTIVE_CODING || input->MbInterlace ) && generic_RC->FieldControl == 0 )
updateQPInterlaceBU( prc );
prc->m_X1 = prc->Pm_X1;
prc->m_X2 = prc->Pm_X2;
prc->MADPictureC1 = prc->PMADPictureC1;
prc->MADPictureC2 = prc->PMADPictureC2;
prc->PreviousPictureMAD = prc->PPictureMAD[0];
DuantQp = prc->PDuantQp;
m_Qp = prc->Pm_Qp;
m_Hp = prc->PPreHeader;
/* predict the MAD of current picture*/
prc->CurrentFrameMAD=prc->MADPictureC1*prc->PreviousPictureMAD + prc->MADPictureC2;
/*compute the number of bits for the texture*/
if(prc->Target < 0)
{
prc->m_Qc=m_Qp+DuantQp;
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
else
{
m_Bits = prc->Target-m_Hp;
m_Bits = imax(m_Bits, (int)(prc->bit_rate/(MINVALUE*prc->frame_rate)));
updateModelQPFrame( prc, m_Bits );
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // clipping
prc->m_Qc = iClip3(m_Qp-DuantQp, m_Qp+DuantQp, prc->m_Qc); // control variation
}
if( generic_RC->FieldControl == 0 )
updateQPNonPicAFF( prc );
return prc->m_Qc;
}
}
/*bottom field*/
else
{
if( img->type==P_SLICE && generic_RC->NoGranularFieldRC == 0 && (IMG_NUMBER) )
updateBottomField( prc );
return prc->m_Qc;
}
}
/*basic unit layer rate control*/
else
{
/*top field of I frame*/
if ((!IMG_NUMBER))
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else if (img->type==I_SLICE)
{
/*adaptive field/frame coding*/
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
prc->m_Qc = prc->PrevLastQP; // Set QP to average qp of last P frame
prc->PrevLastQP = prc->CurrLastQP;
prc->CurrLastQP = prc->PrevLastQP;
prc->PAveFrameQP = prc->CurrLastQP;
return prc->m_Qc;
}
else if(img->type == B_SLICE)
{
int prevQP = imax(prc->PrevLastQP, prc->CurrLastQP);
if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
updateQPInterlace( prc );
if (input->HierarchicalCoding)
{
if (img->b_frame_to_code == 0)
prc->m_Qc = prevQP;
else
prc->m_Qc = prevQP + img->GopLevels - gop_structure[img->b_frame_to_code-1].hierarchy_layer;
}
else
prc->m_Qc = prevQP + 2 - img->nal_reference_idc;
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
return prc->m_Qc;
}
else if( img->type == P_SLICE )
{
if((generic_RC->NumberofGOP==1)&&(generic_RC->NumberofPPicture==0))
{
if((generic_RC->FieldControl==0)||((generic_RC->FieldControl==1) && (generic_RC->NoGranularFieldRC==0)))
return updateFirstP( prc, topfield );
}
else
{
prc->m_X1=prc->Pm_X1;
prc->m_X2=prc->Pm_X2;
prc->MADPictureC1=prc->PMADPictureC1;
prc->MADPictureC2=prc->PMADPictureC2;
m_Qp=prc->Pm_Qp;
if(generic_RC->FieldControl==0)
SumofBasicUnit=prc->TotalNumberofBasicUnit;
else
SumofBasicUnit=prc->TotalNumberofBasicUnit>>1;
/*the average QP of the previous frame is used to coded the first basic unit of the current frame or field*/
if(prc->NumberofBasicUnit==SumofBasicUnit)
return updateFirstBU( prc, topfield );
else
{
/*compute the number of remaining bits*/
prc->Target -= (generic_RC->NumberofBasicUnitHeaderBits + generic_RC->NumberofBasicUnitTextureBits);
generic_RC->NumberofBasicUnitHeaderBits = 0;
generic_RC->NumberofBasicUnitTextureBits = 0;
if(prc->Target<0)
return updateNegativeTarget( prc, topfield, m_Qp );
else
{
/*predict the MAD of current picture*/
predictCurrPicMAD( prc );
/*compute the total number of bits for the current basic unit*/
updateModelQPBU( prc, topfield, m_Qp );
prc->TotalFrameQP +=prc->m_Qc;
prc->Pm_Qp=prc->m_Qc;
prc->NumberofBasicUnit--;
if((prc->NumberofBasicUnit==0) && img->type == P_SLICE && (IMG_NUMBER) )
updateLastBU( prc, topfield );
return prc->m_Qc;
}
}
}
}
}
return prc->m_Qc;
}
/*!
*************************************************************************************
* \brief
* compute a quantization parameter for each frame
*
*************************************************************************************
*/
int updateQPRC3(rc_quadratic *prc, int topfield)
{
int m_Bits;
int SumofBasicUnit;
int DuantQp, m_Qp, m_Hp;
/* frame layer rate control */
if(img->BasicUnit==img->FrameSizeInMbs || img->type != P_SLICE )
{
/* fixed quantization parameter is used to coded I frame, the first P frame and the first B frame
the quantization parameter is adjusted according the available channel bandwidth and
the type of video */
/*top field*/
if((topfield) || (generic_RC->FieldControl==0))
{
if ((!IMG_NUMBER))
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else if( img->type == P_SLICE && generic_RC->NumberofPPicture == 0 && (IMG_NUMBER) )
{
prc->m_Qc=prc->MyInitialQp;
if(generic_RC->FieldControl==0)
updateQPNonPicAFF( prc );
return prc->m_Qc;
}
else
{
/*adaptive field/frame coding*/
if( img->type == P_SLICE && ( input->PicInterlace == ADAPTIVE_CODING || input->MbInterlace ) && generic_RC->FieldControl == 0 )
updateQPInterlaceBU( prc );
prc->m_X1 = prc->Pm_X1;
prc->m_X2 = prc->Pm_X2;
prc->MADPictureC1 = prc->PMADPictureC1;
prc->MADPictureC2 = prc->PMADPictureC2;
prc->PreviousPictureMAD = prc->PPictureMAD[0];
DuantQp = prc->PDuantQp;
m_Qp = prc->Pm_Qp;
m_Hp = prc->PPreHeader;
if ( img->BasicUnit < img->FrameSizeInMbs && img->type != P_SLICE )
{
// when RC_MODE_3 is set and basic unit is smaller than a frame, note that:
// the linear MAD model and the quadratic QP model operate on small units and not on a whole frame;
// we therefore have to account for this
prc->PreviousPictureMAD = prc->PreviousWholeFrameMAD;
}
if ( img->type == I_SLICE )
m_Hp = 0; // it is usually a very small portion of the total I_SLICE bit budget
/* predict the MAD of current picture*/
prc->CurrentFrameMAD=prc->MADPictureC1*prc->PreviousPictureMAD + prc->MADPictureC2;
/*compute the number of bits for the texture*/
if(prc->Target < 0)
{
prc->m_Qc=m_Qp+DuantQp;
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // Clipping
}
else
{
if ( img->type != P_SLICE )
{
if ( img->BasicUnit < img->FrameSizeInMbs )
m_Bits =(prc->Target-m_Hp)/prc->TotalNumberofBasicUnit;
else
m_Bits =prc->Target-m_Hp;
}
else {
m_Bits = prc->Target-m_Hp;
m_Bits = imax(m_Bits, (int)(prc->bit_rate/(MINVALUE*prc->frame_rate)));
}
updateModelQPFrame( prc, m_Bits );
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // clipping
if ( img->type == P_SLICE )
prc->m_Qc = iClip3(m_Qp-DuantQp, m_Qp+DuantQp, prc->m_Qc); // control variation
}
if( img->type == P_SLICE && generic_RC->FieldControl == 0 )
updateQPNonPicAFF( prc );
if ( img->type == B_SLICE )
{
// hierarchical adjustment
int prevqp = ((prc->PrevLastQP+prc->CurrLastQP) >> 1) + 1;
if ( input->HierarchicalCoding && img->b_frame_to_code)
prc->m_Qc -= gop_structure[img->b_frame_to_code-1].hierarchy_layer;
// check bounds
prc->m_Qc = iClip3(prevqp - (input->HierarchicalCoding ? 0 : 5), prevqp + 5, prc->m_Qc); // control variation
prc->m_Qc = iClip3(prc->RC_MIN_QUANT, prc->RC_MAX_QUANT, prc->m_Qc); // clipping
}
return prc->m_Qc;
}
}
/*bottom field*/
else
{
if( img->type==P_SLICE && generic_RC->NoGranularFieldRC == 0 && (IMG_NUMBER) )
updateBottomField( prc );
return prc->m_Qc;
}
}
/*basic unit layer rate control*/
else
{
/*top field of I frame*/
if ((!IMG_NUMBER))
{
prc->m_Qc = prc->MyInitialQp;
return prc->m_Qc;
}
else if( img->type == P_SLICE )
{
if((generic_RC->NumberofGOP==1)&&(generic_RC->NumberofPPicture==0))
{
if((generic_RC->FieldControl==0)||((generic_RC->FieldControl==1) && (generic_RC->NoGranularFieldRC==0)))
return updateFirstP( prc, topfield );
}
else
{
prc->m_X1=prc->Pm_X1;
prc->m_X2=prc->Pm_X2;
prc->MADPictureC1=prc->PMADPictureC1;
prc->MADPictureC2=prc->PMADPictureC2;
m_Qp=prc->Pm_Qp;
if(generic_RC->FieldControl==0)
SumofBasicUnit=prc->TotalNumberofBasicUnit;
else
SumofBasicUnit=prc->TotalNumberofBasicUnit>>1;
/*the average QP of the previous frame is used to coded the first basic unit of the current frame or field*/
if(prc->NumberofBasicUnit==SumofBasicUnit)
return updateFirstBU( prc, topfield );
else
{
/*compute the number of remaining bits*/
prc->Target -= (generic_RC->NumberofBasicUnitHeaderBits + generic_RC->NumberofBasicUnitTextureBits);
generic_RC->NumberofBasicUnitHeaderBits = 0;
generic_RC->NumberofBasicUnitTextureBits = 0;
if(prc->Target<0)
return updateNegativeTarget( prc, topfield, m_Qp );
else
{
/*predict the MAD of current picture*/
predictCurrPicMAD( prc );
/*compute the total number of bits for the current basic unit*/
updateModelQPBU( prc, topfield, m_Qp );
prc->TotalFrameQP +=prc->m_Qc;
prc->Pm_Qp=prc->m_Qc;
prc->NumberofBasicUnit--;
if((prc->NumberofBasicUnit==0) && img->type == P_SLICE && (IMG_NUMBER) )
updateLastBU( prc, topfield );
return prc->m_Qc;
}
}
}
}
}
return prc->m_Qc;
}
void updateQPInterlace( rc_quadratic *prc )
{
if(generic_RC->FieldControl==0)
{
/*previous choice is frame coding*/
if(generic_RC->FieldFrame==1)
{
prc->PrevLastQP=prc->CurrLastQP;
prc->CurrLastQP=prc->FrameQPBuffer;
}
/*previous choice is field coding*/
else
{
prc->PrevLastQP=prc->CurrLastQP;
prc->CurrLastQP=prc->FieldQPBuffer;
}
}
}
void updateQPNonPicAFF( rc_quadratic *prc )
{
if(active_sps->frame_mbs_only_flag)
{
generic_RC->TotalQpforPPicture +=prc->m_Qc;
prc->PrevLastQP=prc->CurrLastQP;
prc->CurrLastQP=prc->m_Qc;
prc->Pm_Qp=prc->m_Qc;
}
/*adaptive field/frame coding*/
else
prc->FrameQPBuffer=prc->m_Qc;
}
void updateBottomField( rc_quadratic *prc )
{
/*field coding*/
if(input->PicInterlace==FIELD_CODING)
{
generic_RC->TotalQpforPPicture +=prc->m_Qc;
prc->PrevLastQP=prc->CurrLastQP+1;
prc->CurrLastQP=prc->m_Qc;//+0 Recent change 13/1/2003
prc->Pm_Qp=prc->m_Qc;
}
/*adaptive field/frame coding*/
else
prc->FieldQPBuffer=prc->m_Qc;
}
int updateFirstP( rc_quadratic *prc, int topfield )
{
/*top field of the first P frame*/
prc->m_Qc=prc->MyInitialQp;
generic_RC->NumberofBasicUnitHeaderBits=0;
generic_RC->NumberofBasicUnitTextureBits=0;
prc->NumberofBasicUnit--;
/*bottom field of the first P frame*/
if((!topfield)&&(prc->NumberofBasicUnit==0))
{
/*frame coding or field coding*/
if((active_sps->frame_mbs_only_flag)||(input->PicInterlace==FIELD_CODING))
{
generic_RC->TotalQpforPPicture +=prc->m_Qc;
prc->PrevLastQP=prc->CurrLastQP;
prc->CurrLastQP=prc->m_Qc;
prc->PAveFrameQP=prc->m_Qc;
prc->PAveHeaderBits3=prc->PAveHeaderBits2;
}
/*adaptive frame/field coding*/
else if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
{
if(generic_RC->FieldControl==0)
{
prc->FrameQPBuffer=prc->m_Qc;
prc->FrameAveHeaderBits=prc->PAveHeaderBits2;
}
else
{
prc->FieldQPBuffer=prc->m_Qc;
prc->FieldAveHeaderBits=prc->PAveHeaderBits2;
}
}
}
prc->Pm_Qp=prc->m_Qc;
prc->TotalFrameQP +=prc->m_Qc;
return prc->m_Qc;
}
int updateNegativeTarget( rc_quadratic *prc, int topfield, int m_Qp )
{
int PAverageQP;
if(prc->GOPOverdue==TRUE)
prc->m_Qc=m_Qp+2;
else
prc->m_Qc=m_Qp+prc->DDquant;//2
prc->m_Qc = imin(prc->m_Qc, prc->RC_MAX_QUANT); // clipping
if(input->basicunit>=prc->MBPerRow)
prc->m_Qc = imin(prc->m_Qc, prc->PAveFrameQP + 6);
else
prc->m_Qc = imin(prc->m_Qc, prc->PAveFrameQP + 3);
prc->TotalFrameQP +=prc->m_Qc;
prc->NumberofBasicUnit--;
if(prc->NumberofBasicUnit==0)
{
if((!topfield)||(generic_RC->FieldControl==0))
{
/*frame coding or field coding*/
if((active_sps->frame_mbs_only_flag)||(input->PicInterlace==FIELD_CODING))
{
PAverageQP=(int)((double)prc->TotalFrameQP/(double)prc->TotalNumberofBasicUnit+0.5);
if (generic_RC->NumberofPPicture == (input->intra_period - 2))
prc->QPLastPFrame = PAverageQP;
generic_RC->TotalQpforPPicture +=PAverageQP;
if(prc->GOPOverdue==TRUE)
{
prc->PrevLastQP=prc->CurrLastQP+1;
prc->CurrLastQP=PAverageQP;
}
else
{
if((generic_RC->NumberofPPicture==0)&&(generic_RC->NumberofGOP>1))
{
prc->PrevLastQP=prc->CurrLastQP;
prc->CurrLastQP=PAverageQP;
}
else if(generic_RC->NumberofPPicture>0)
{
prc->PrevLastQP=prc->CurrLastQP+1;
prc->CurrLastQP=PAverageQP;
}
}
prc->PAveFrameQP=PAverageQP;
prc->PAveHeaderBits3=prc->PAveHeaderBits2;
}
/*adaptive field/frame coding*/
else if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
{
if(generic_RC->FieldControl==0)
{
PAverageQP=(int)((double)prc->TotalFrameQP/(double)prc->TotalNumberofBasicUnit+0.5);
prc->FrameQPBuffer=PAverageQP;
prc->FrameAveHeaderBits=prc->PAveHeaderBits2;
}
else
{
PAverageQP=(int)((double)prc->TotalFrameQP/(double)prc->TotalNumberofBasicUnit+0.5);
prc->FieldQPBuffer=PAverageQP;
prc->FieldAveHeaderBits=prc->PAveHeaderBits2;
}
}
}
}
if(prc->GOPOverdue==TRUE)
prc->Pm_Qp=prc->PAveFrameQP;
else
prc->Pm_Qp=prc->m_Qc;
return prc->m_Qc;
}
int updateFirstBU( rc_quadratic *prc, int topfield )
{
/*adaptive field/frame coding*/
if(((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))&&(generic_RC->FieldControl==0))
{
/*previous choice is frame coding*/
if(generic_RC->FieldFrame==1)
{
if(generic_RC->NumberofPPicture>0)
generic_RC->TotalQpforPPicture +=prc->FrameQPBuffer;
prc->PAveFrameQP=prc->FrameQPBuffer;
prc->PAveHeaderBits3=prc->FrameAveHeaderBits;
}
/*previous choice is field coding*/
else
{
if(generic_RC->NumberofPPicture>0)
generic_RC->TotalQpforPPicture +=prc->FieldQPBuffer;
prc->PAveFrameQP=prc->FieldQPBuffer;
prc->PAveHeaderBits3=prc->FieldAveHeaderBits;
}
}
if(prc->Target<=0)
{
prc->m_Qc = prc->PAveFrameQP + 2;
if(prc->m_Qc > prc->RC_MAX_QUANT)
prc->m_Qc = prc->RC_MAX_QUANT;
if(topfield||(generic_RC->FieldControl==0))
prc->GOPOverdue=TRUE;
}
else
{
prc->m_Qc=prc->PAveFrameQP;
}
prc->TotalFrameQP +=prc->m_Qc;
prc->NumberofBasicUnit--;
prc->Pm_Qp = prc->PAveFrameQP;
return prc->m_Qc;
}
void updateLastBU( rc_quadratic *prc, int topfield )
{
int PAverageQP;
if((!topfield)||(generic_RC->FieldControl==0))
{
/*frame coding or field coding*/
if((active_sps->frame_mbs_only_flag)||(input->PicInterlace==FIELD_CODING))
{
PAverageQP=(int)((double)prc->TotalFrameQP/(double) prc->TotalNumberofBasicUnit+0.5);
if (generic_RC->NumberofPPicture == (input->intra_period - 2))
prc->QPLastPFrame = PAverageQP;
generic_RC->TotalQpforPPicture +=PAverageQP;
prc->PrevLastQP=prc->CurrLastQP;
prc->CurrLastQP=PAverageQP;
prc->PAveFrameQP=PAverageQP;
prc->PAveHeaderBits3=prc->PAveHeaderBits2;
}
else if((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))
{
if(generic_RC->FieldControl==0)
{
PAverageQP=(int)((double) prc->TotalFrameQP/(double)prc->TotalNumberofBasicUnit+0.5);
prc->FrameQPBuffer=PAverageQP;
prc->FrameAveHeaderBits=prc->PAveHeaderBits2;
}
else
{
PAverageQP=(int)((double) prc->TotalFrameQP/(double) prc->TotalNumberofBasicUnit+0.5);
prc->FieldQPBuffer=PAverageQP;
prc->FieldAveHeaderBits=prc->PAveHeaderBits2;
}
}
}
}
void predictCurrPicMAD( rc_quadratic *prc )
{
int i;
if(((input->PicInterlace==ADAPTIVE_CODING)||(input->MbInterlace))&&(generic_RC->FieldControl==1))
{
prc->CurrentFrameMAD=prc->MADPictureC1*prc->FCBUPFMAD[prc->TotalNumberofBasicUnit-prc->NumberofBasicUnit]+prc->MADPictureC2;
prc->TotalBUMAD=0;
for(i=prc->TotalNumberofBasicUnit-1; i>=(prc->TotalNumberofBasicUnit-prc->NumberofBasicUnit);i--)
{
prc->CurrentBUMAD=prc->MADPictureC1*prc->FCBUPFMAD[i]+prc->MADPictureC2;
prc->TotalBUMAD +=prc->CurrentBUMAD*prc->CurrentBUMAD;
}
}
else
{
prc->CurrentFrameMAD=prc->MADPictureC1*prc->BUPFMAD[prc->TotalNumberofBasicUnit-prc->NumberofBasicUnit]+prc->MADPictureC2;
prc->TotalBUMAD=0;
for(i=prc->TotalNumberofBasicUnit-1; i>=(prc->TotalNumberofBasicUnit-prc->NumberofBasicUnit);i--)
{
prc->CurrentBUMAD=prc->MADPictureC1*prc->BUPFMAD[i]+prc->MADPictureC2;
prc->TotalBUMAD +=prc->CurrentBUMAD*prc->CurrentBUMAD;
}
}
}
void updateModelQPBU( rc_quadratic *prc, int topfield, int m_Qp )
{
double dtmp, m_Qstep;
int m_Bits;
/*compute the total number of bits for the current basic unit*/
m_Bits =(int)(prc->Target * prc->CurrentFrameMAD * prc->CurrentFrameMAD / prc->TotalBUMAD);
/*compute the number of texture bits*/
m_Bits -=prc->PAveHeaderBits2;
m_Bits=imax(m_Bits,(int)(prc->bit_rate/(MINVALUE*prc->frame_rate*prc->TotalNumberofBasicUnit)));
dtmp = prc->CurrentFrameMAD * prc->CurrentFrameMAD * prc->m_X1 * prc->m_X1 \
+ 4 * prc->m_X2 * prc->CurrentFrameMAD * m_Bits;
if ((prc->m_X2 == 0.0) || (dtmp < 0) || ((sqrt (dtmp) - prc->m_X1 * prc->CurrentFrameMAD) <= 0.0)) // fall back 1st order mode
m_Qstep = (float)(prc->m_X1 * prc->CurrentFrameMAD / (double) m_Bits);
else // 2nd order mode
m_Qstep = (float) ((2 * prc->m_X2 * prc->CurrentFrameMAD) / (sqrt (dtmp) - prc->m_X1 * prc->CurrentFrameMAD));
prc->m_Qc = Qstep2QP(m_Qstep);
prc->m_Qc = imin(m_Qp+prc->DDquant, prc->m_Qc); // control variation
if(input->basicunit>=prc->MBPerRow)
prc->m_Qc = imin(prc->PAveFrameQP+6, prc->m_Qc);
else
prc->m_Qc = imin(prc->PAveFrameQP+3, prc->m_Qc);
prc->m_Qc = iClip3(m_Qp-prc->DDquant, prc->RC_MAX_QUANT, prc->m_Qc); // clipping
if(input->basicunit>=prc->MBPerRow)
prc->m_Qc = imax(prc->PAveFrameQP-6, prc->m_Qc);
else
prc->m_Qc = imax(prc->PAveFrameQP-3, prc->m_Qc);
prc->m_Qc = imax(prc->RC_MIN_QUANT, prc->m_Qc);
}
void updateQPInterlaceBU( rc_quadratic *prc )
{
/*previous choice is frame coding*/
if(generic_RC->FieldFrame==1)
{
generic_RC->TotalQpforPPicture +=prc->FrameQPBuffer;
prc->Pm_Qp=prc->FrameQPBuffer;
}
/*previous choice is field coding*/
else
{
generic_RC->TotalQpforPPicture +=prc->FieldQPBuffer;
prc->Pm_Qp=prc->FieldQPBuffer;
}
}
void updateModelQPFrame( rc_quadratic *prc, int m_Bits )
{
double dtmp, m_Qstep;
dtmp = prc->CurrentFrameMAD * prc->m_X1 * prc->CurrentFrameMAD * prc->m_X1
+ 4 * prc->m_X2 * prc->CurrentFrameMAD * m_Bits;
if ((prc->m_X2 == 0.0) || (dtmp < 0) || ((sqrt (dtmp) - prc->m_X1 * prc->CurrentFrameMAD) <= 0.0)) // fall back 1st order mode
m_Qstep = (float) (prc->m_X1 * prc->CurrentFrameMAD / (double) m_Bits);
else // 2nd order mode
m_Qstep = (float) ((2 * prc->m_X2 * prc->CurrentFrameMAD) / (sqrt (dtmp) - prc->m_X1 * prc->CurrentFrameMAD));
prc->m_Qc = Qstep2QP(m_Qstep);
}