text: /* The copyright in this software is being made available under the BSD
   * License, included below. This software may be subject to other third party
   * and contributor rights, including patent rights, and no such rights are
   * granted under this license.
   *
   * Copyright (c) 2010-2015, ITU/ISO/IEC
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   *  * Redistributions of source code must retain the above copyright notice,
   *    this list of conditions and the following disclaimer.
   *  * Redistributions in binary form must reproduce the above copyright notice,
   *    this list of conditions and the following disclaimer in the documentation
   *    and/or other materials provided with the distribution.
   *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
   *    be used to endorse or promote products derived from this software without
   *    specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   * THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  /** \file     TEncRateCtrl.cpp
      \brief    Rate control manager class
  */
  #include "TEncRateCtrl.h"
  #include "../TLibCommon/TComPic.h"
  #include "../TLibCommon/TComChromaFormat.h"
  
  #include <cmath>
  
  using namespace std;
  
  //sequence level
  TEncRCSeq::TEncRCSeq()
  {
    m_totalFrames         = 0;
    m_targetRate          = 0;
    m_frameRate           = 0;
    m_targetBits          = 0;
    m_GOPSize             = 0;
    m_picWidth            = 0;
    m_picHeight           = 0;
    m_LCUWidth            = 0;
    m_LCUHeight           = 0;
    m_numberOfLevel       = 0;
    m_numberOfLCU         = 0;
    m_averageBits         = 0;
    m_bitsRatio           = NULL;
    m_GOPID2Level         = NULL;
    m_picPara             = NULL;
    m_LCUPara             = NULL;
    m_numberOfPixel       = 0;
    m_framesLeft          = 0;
    m_bitsLeft            = 0;
    m_useLCUSeparateModel = false;
    m_adaptiveBit         = 0;
    m_lastLambda          = 0.0;
  }
  
  TEncRCSeq::~TEncRCSeq()
  {
    destroy();
  }
  
  Void TEncRCSeq::create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit )
  {
    destroy();
    m_totalFrames         = totalFrames;
    m_targetRate          = targetBitrate;
    m_frameRate           = frameRate;
    m_GOPSize             = GOPSize;
    m_picWidth            = picWidth;
    m_picHeight           = picHeight;
    m_LCUWidth            = LCUWidth;
    m_LCUHeight           = LCUHeight;
    m_numberOfLevel       = numberOfLevel;
    m_useLCUSeparateModel = useLCUSeparateModel;
  
    m_numberOfPixel   = m_picWidth * m_picHeight;
    m_targetBits      = (Int64)m_totalFrames * (Int64)m_targetRate / (Int64)m_frameRate;
    m_seqTargetBpp = (Double)m_targetRate / (Double)m_frameRate / (Double)m_numberOfPixel;
    if ( m_seqTargetBpp < 0.03 )
    {
      m_alphaUpdate = 0.01;
      m_betaUpdate  = 0.005;
    }
    else if ( m_seqTargetBpp < 0.08 )
    {
      m_alphaUpdate = 0.05;
      m_betaUpdate  = 0.025;
    }
    else if ( m_seqTargetBpp < 0.2 )
    {
      m_alphaUpdate = 0.1;
      m_betaUpdate  = 0.05;
    }
    else if ( m_seqTargetBpp < 0.5 )
    {
      m_alphaUpdate = 0.2;
      m_betaUpdate  = 0.1;
    }
    else
    {
      m_alphaUpdate = 0.4;
      m_betaUpdate  = 0.2;
    }
  
    m_averageBits     = (Int)(m_targetBits / totalFrames);
    Int picWidthInBU  = ( m_picWidth  % m_LCUWidth  ) == 0 ? m_picWidth  / m_LCUWidth  : m_picWidth  / m_LCUWidth  + 1;
    Int picHeightInBU = ( m_picHeight % m_LCUHeight ) == 0 ? m_picHeight / m_LCUHeight : m_picHeight / m_LCUHeight + 1;
    m_numberOfLCU     = picWidthInBU * picHeightInBU;
  
    m_bitsRatio   = new Int[m_GOPSize];
    for ( Int i=0; i<m_GOPSize; i++ )
    {
      m_bitsRatio[i] = 1;
    }
  
    m_GOPID2Level = new Int[m_GOPSize];
    for ( Int i=0; i<m_GOPSize; i++ )
    {
      m_GOPID2Level[i] = 1;
    }
  
    m_picPara = new TRCParameter[m_numberOfLevel];
    for ( Int i=0; i<m_numberOfLevel; i++ )
    {
      m_picPara[i].m_alpha = 0.0;
      m_picPara[i].m_beta  = 0.0;
    }
  
    if ( m_useLCUSeparateModel )
    {
      m_LCUPara = new TRCParameter*[m_numberOfLevel];
      for ( Int i=0; i<m_numberOfLevel; i++ )
      {
        m_LCUPara[i] = new TRCParameter[m_numberOfLCU];
        for ( Int j=0; j<m_numberOfLCU; j++)
        {
          m_LCUPara[i][j].m_alpha = 0.0;
          m_LCUPara[i][j].m_beta  = 0.0;
        }
      }
    }
  
    m_framesLeft = m_totalFrames;
    m_bitsLeft   = m_targetBits;
    m_adaptiveBit = adaptiveBit;
    m_lastLambda = 0.0;
  }
  
  Void TEncRCSeq::destroy()
  {
    if (m_bitsRatio != NULL)
    {
      delete[] m_bitsRatio;
      m_bitsRatio = NULL;
    }
  
    if ( m_GOPID2Level != NULL )
    {
      delete[] m_GOPID2Level;
      m_GOPID2Level = NULL;
    }
  
    if ( m_picPara != NULL )
    {
      delete[] m_picPara;
      m_picPara = NULL;
    }
  
    if ( m_LCUPara != NULL )
    {
      for ( Int i=0; i<m_numberOfLevel; i++ )
      {
        delete[] m_LCUPara[i];
      }
      delete[] m_LCUPara;
      m_LCUPara = NULL;
    }
  }
  
  Void TEncRCSeq::initBitsRatio( Int bitsRatio[])
  {
    for (Int i=0; i<m_GOPSize; i++)
    {
      m_bitsRatio[i] = bitsRatio[i];
    }
  }
  
  Void TEncRCSeq::initGOPID2Level( Int GOPID2Level[] )
  {
    for ( Int i=0; i<m_GOPSize; i++ )
    {
      m_GOPID2Level[i] = GOPID2Level[i];
    }
  }
  
  Void TEncRCSeq::initPicPara( TRCParameter* picPara )
  {
    assert( m_picPara != NULL );
  
    if ( picPara == NULL )
    {
      for ( Int i=0; i<m_numberOfLevel; i++ )
      {
        if (i>0)
        {
          m_picPara[i].m_alpha = 3.2003;
          m_picPara[i].m_beta  = -1.367;
        }
        else
        {
          m_picPara[i].m_alpha = ALPHA;
          m_picPara[i].m_beta  = BETA2;
        }
      }
    }
    else
    {
      for ( Int i=0; i<m_numberOfLevel; i++ )
      {
        m_picPara[i] = picPara[i];
      }
    }
  }
  
  Void TEncRCSeq::initLCUPara( TRCParameter** LCUPara )
  {
    if ( m_LCUPara == NULL )
    {
      return;
    }
    if ( LCUPara == NULL )
    {
      for ( Int i=0; i<m_numberOfLevel; i++ )
      {
        for ( Int j=0; j<m_numberOfLCU; j++)
        {
          m_LCUPara[i][j].m_alpha = m_picPara[i].m_alpha;
          m_LCUPara[i][j].m_beta  = m_picPara[i].m_beta;
        }
      }
    }
    else
    {
      for ( Int i=0; i<m_numberOfLevel; i++ )
      {
        for ( Int j=0; j<m_numberOfLCU; j++)
        {
          m_LCUPara[i][j] = LCUPara[i][j];
        }
      }
    }
  }
  
  Void TEncRCSeq::updateAfterPic ( Int bits )
  {
    m_bitsLeft -= bits;
    m_framesLeft--;
  }
  
  Void TEncRCSeq::setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB )
  {
    Int* bitsRatio = new Int[m_GOPSize];
    for ( Int i=0; i<m_GOPSize; i++ )
    {
      bitsRatio[i] = (Int)( equaCoeffA[i] * pow( basicLambda, equaCoeffB[i] ) * m_numberOfPixel );
    }
    initBitsRatio( bitsRatio );
    delete[] bitsRatio;
  }
  
  //GOP level
  TEncRCGOP::TEncRCGOP()
  {
    m_encRCSeq  = NULL;
    m_picTargetBitInGOP = NULL;
    m_numPic     = 0;
    m_targetBits = 0;
    m_picLeft    = 0;
    m_bitsLeft   = 0;
  }
  
  TEncRCGOP::~TEncRCGOP()
  {
    destroy();
  }
  
  Void TEncRCGOP::create( TEncRCSeq* encRCSeq, Int numPic )
  {
    destroy();
    Int targetBits = xEstGOPTargetBits( encRCSeq, numPic );
  
    if ( encRCSeq->getAdaptiveBits() > 0 && encRCSeq->getLastLambda() > 0.1 )
    {
      Double targetBpp = (Double)targetBits / encRCSeq->getNumPixel();
      Double basicLambda = 0.0;
      Double* lambdaRatio = new Double[encRCSeq->getGOPSize()];
      Double* equaCoeffA = new Double[encRCSeq->getGOPSize()];
      Double* equaCoeffB = new Double[encRCSeq->getGOPSize()];
  
      if ( encRCSeq->getAdaptiveBits() == 1 )   // for GOP size =4, low delay case
      {
        if ( encRCSeq->getLastLambda() < 120.0 )
        {
          lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.5793;
          lambdaRatio[0] = 1.3 * lambdaRatio[1];
          lambdaRatio[2] = 1.3 * lambdaRatio[1];
          lambdaRatio[3] = 1.0;
        }
        else
        {
          lambdaRatio[0] = 5.0;
          lambdaRatio[1] = 4.0;
          lambdaRatio[2] = 5.0;
          lambdaRatio[3] = 1.0;
        }
      }
      else if ( encRCSeq->getAdaptiveBits() == 2 )  // for GOP size = 8, random access case
      {
        if ( encRCSeq->getLastLambda() < 90.0 )
        {
          lambdaRatio[0] = 1.0;
          lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.7963;
          lambdaRatio[2] = 1.3 * lambdaRatio[1];
          lambdaRatio[3] = 3.25 * lambdaRatio[1];
          lambdaRatio[4] = 3.25 * lambdaRatio[1];
          lambdaRatio[5] = 1.3  * lambdaRatio[1];
          lambdaRatio[6] = 3.25 * lambdaRatio[1];
          lambdaRatio[7] = 3.25 * lambdaRatio[1];
        }
        else
        {
          lambdaRatio[0] = 1.0;
          lambdaRatio[1] = 4.0;
          lambdaRatio[2] = 5.0;
          lambdaRatio[3] = 12.3;
          lambdaRatio[4] = 12.3;
          lambdaRatio[5] = 5.0;
          lambdaRatio[6] = 12.3;
          lambdaRatio[7] = 12.3;
        }
      }
  
      xCalEquaCoeff( encRCSeq, lambdaRatio, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() );
      basicLambda = xSolveEqua( targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() );
      encRCSeq->setAllBitRatio( basicLambda, equaCoeffA, equaCoeffB );
  
      delete []lambdaRatio;
      delete []equaCoeffA;
      delete []equaCoeffB;
    }
  
    m_picTargetBitInGOP = new Int[numPic];
    Int i;
    Int totalPicRatio = 0;
    Int currPicRatio = 0;
    for ( i=0; i<numPic; i++ )
    {
      totalPicRatio += encRCSeq->getBitRatio( i );
    }
    for ( i=0; i<numPic; i++ )
    {
      currPicRatio = encRCSeq->getBitRatio( i );
      m_picTargetBitInGOP[i] = (Int)( ((Double)targetBits) * currPicRatio / totalPicRatio );
    }
  
    m_encRCSeq    = encRCSeq;
    m_numPic       = numPic;
    m_targetBits   = targetBits;
    m_picLeft      = m_numPic;
    m_bitsLeft     = m_targetBits;
  }
  
  Void TEncRCGOP::xCalEquaCoeff( TEncRCSeq* encRCSeq, Double* lambdaRatio, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize )
  {
    for ( Int i=0; i<GOPSize; i++ )
    {
      Int frameLevel = encRCSeq->getGOPID2Level(i);
      Double alpha   = encRCSeq->getPicPara(frameLevel).m_alpha;
      Double beta    = encRCSeq->getPicPara(frameLevel).m_beta;
      equaCoeffA[i] = pow( 1.0/alpha, 1.0/beta ) * pow( lambdaRatio[i], 1.0/beta );
      equaCoeffB[i] = 1.0/beta;
    }
  }
  
  Double TEncRCGOP::xSolveEqua( Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize )
  {
    Double solution = 100.0;
    Double minNumber = 0.1;
    Double maxNumber = 10000.0;
    for ( Int i=0; i<g_RCIterationNum; i++ )
    {
      Double fx = 0.0;
      for ( Int j=0; j<GOPSize; j++ )
      {
        fx += equaCoeffA[j] * pow( solution, equaCoeffB[j] );
      }
  
      if ( fabs( fx - targetBpp ) < 0.000001 )
      {
        break;
      }
  
      if ( fx > targetBpp )
      {
        minNumber = solution;
        solution = ( solution + maxNumber ) / 2.0;
      }
      else
      {
        maxNumber = solution;
        solution = ( solution + minNumber ) / 2.0;
      }
    }
  
    solution = Clip3( 0.1, 10000.0, solution );
    return solution;
  }
  
  Void TEncRCGOP::destroy()
  {
    m_encRCSeq = NULL;
    if ( m_picTargetBitInGOP != NULL )
    {
      delete[] m_picTargetBitInGOP;
      m_picTargetBitInGOP = NULL;
    }
  }
  
  Void TEncRCGOP::updateAfterPicture( Int bitsCost )
  {
    m_bitsLeft -= bitsCost;
    m_picLeft--;
  }
  
  Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize )
  {
    Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() );
    Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() );
    Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture );
    Int targetBits = currentTargetBitsPerPic * GOPSize;
  
    if ( targetBits < 200 )
    {
      targetBits = 200;   // at least allocate 200 bits for one GOP
    }
  
    return targetBits;
  }
  
  //picture level
  TEncRCPic::TEncRCPic()
  {
    m_encRCSeq = NULL;
    m_encRCGOP = NULL;
  
    m_frameLevel    = 0;
    m_numberOfPixel = 0;
    m_numberOfLCU   = 0;
    m_targetBits    = 0;
    m_estHeaderBits = 0;
    m_estPicQP      = 0;
    m_estPicLambda  = 0.0;
  
    m_LCULeft       = 0;
    m_bitsLeft      = 0;
    m_pixelsLeft    = 0;
  
    m_LCUs         = NULL;
    m_picActualHeaderBits = 0;
    m_picActualBits       = 0;
    m_picQP               = 0;
    m_picLambda           = 0.0;
  }
  
  TEncRCPic::~TEncRCPic()
  {
    destroy();
  }
  
  Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )
  {
    Int targetBits        = 0;
    Int GOPbitsLeft       = encRCGOP->getBitsLeft();
  
    Int i;
    Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();
    Int currPicRatio    = encRCSeq->getBitRatio( currPicPosition );
    Int totalPicRatio   = 0;
    for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )
    {
      totalPicRatio += encRCSeq->getBitRatio( i );
    }
  
    targetBits  = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );
  
    if ( targetBits < 100 )
    {
      targetBits = 100;   // at least allocate 100 bits for one picture
    }
  
    if ( m_encRCSeq->getFramesLeft() > 16 )
    {
      targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );
    }
  
    return targetBits;
  }
  
  Int TEncRCPic::xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel )
  {
    Int numPreviousPics   = 0;
    Int totalPreviousBits = 0;
  
    list<TEncRCPic*>::iterator it;
    for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )
    {
      if ( (*it)->getFrameLevel() == frameLevel )
      {
        totalPreviousBits += (*it)->getPicActualHeaderBits();
        numPreviousPics++;
      }
    }
  
    Int estHeaderBits = 0;
    if ( numPreviousPics > 0 )
    {
      estHeaderBits = totalPreviousBits / numPreviousPics;
    }
  
    return estHeaderBits;
  }
  
  Void TEncRCPic::addToPictureLsit( list<TEncRCPic*>& listPreviousPictures )
  {
    if ( listPreviousPictures.size() > g_RCMaxPicListSize )
    {
      TEncRCPic* p = listPreviousPictures.front();
      listPreviousPictures.pop_front();
      p->destroy();
      delete p;
    }
  
    listPreviousPictures.push_back( this );
  }
  
  Void TEncRCPic::create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures )
  {
    destroy();
    m_encRCSeq = encRCSeq;
    m_encRCGOP = encRCGOP;
  
    Int targetBits    = xEstPicTargetBits( encRCSeq, encRCGOP );
    Int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel );
  
    if ( targetBits < estHeaderBits + 100 )
    {
      targetBits = estHeaderBits + 100;   // at least allocate 100 bits for picture data
    }
  
    m_frameLevel       = frameLevel;
    m_numberOfPixel    = encRCSeq->getNumPixel();
    m_numberOfLCU      = encRCSeq->getNumberOfLCU();
    m_estPicLambda     = 100.0;
    m_targetBits       = targetBits;
    m_estHeaderBits    = estHeaderBits;
    m_bitsLeft         = m_targetBits;
    Int picWidth       = encRCSeq->getPicWidth();
    Int picHeight      = encRCSeq->getPicHeight();
    Int LCUWidth       = encRCSeq->getLCUWidth();
    Int LCUHeight      = encRCSeq->getLCUHeight();
    Int picWidthInLCU  = ( picWidth  % LCUWidth  ) == 0 ? picWidth  / LCUWidth  : picWidth  / LCUWidth  + 1;
    Int picHeightInLCU = ( picHeight % LCUHeight ) == 0 ? picHeight / LCUHeight : picHeight / LCUHeight + 1;
  
    m_LCULeft         = m_numberOfLCU;
    m_bitsLeft       -= m_estHeaderBits;
    m_pixelsLeft      = m_numberOfPixel;
  
    m_LCUs           = new TRCLCU[m_numberOfLCU];
    Int i, j;
    Int LCUIdx;
    for ( i=0; i<picWidthInLCU; i++ )
    {
      for ( j=0; j<picHeightInLCU; j++ )
      {
        LCUIdx = j*picWidthInLCU + i;
        m_LCUs[LCUIdx].m_actualBits = 0;
        m_LCUs[LCUIdx].m_QP         = 0;
        m_LCUs[LCUIdx].m_lambda     = 0.0;
        m_LCUs[LCUIdx].m_targetBits = 0;
        m_LCUs[LCUIdx].m_bitWeight  = 1.0;
        Int currWidth  = ( (i == picWidthInLCU -1) ? picWidth  - LCUWidth *(picWidthInLCU -1) : LCUWidth  );
        Int currHeight = ( (j == picHeightInLCU-1) ? picHeight - LCUHeight*(picHeightInLCU-1) : LCUHeight );
        m_LCUs[LCUIdx].m_numberOfPixel = currWidth * currHeight;
      }
    }
    m_picActualHeaderBits = 0;
    m_picActualBits       = 0;
    m_picQP               = 0;
    m_picLambda           = 0.0;
  }
  
  Void TEncRCPic::destroy()
  {
    if( m_LCUs != NULL )
    {
      delete[] m_LCUs;
      m_LCUs = NULL;
    }
    m_encRCSeq = NULL;
    m_encRCGOP = NULL;
  }
  
  
  Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType)
  {
    Double alpha         = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
    Double beta          = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
    Double bpp       = (Double)m_targetBits/(Double)m_numberOfPixel;
    Double estLambda;
    if (eSliceType == I_SLICE)
    {
      estLambda = calculateLambdaIntra(alpha, beta, pow(m_totalCostIntra/(Double)m_numberOfPixel, BETA1), bpp);
    }
    else
    {
      estLambda = alpha * pow( bpp, beta );
    }
  
    Double lastLevelLambda = -1.0;
    Double lastPicLambda   = -1.0;
    Double lastValidLambda = -1.0;
    list<TEncRCPic*>::iterator it;
    for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )
    {
      if ( (*it)->getFrameLevel() == m_frameLevel )
      {
        lastLevelLambda = (*it)->getPicActualLambda();
      }
      lastPicLambda     = (*it)->getPicActualLambda();
  
      if ( lastPicLambda > 0.0 )
      {
        lastValidLambda = lastPicLambda;
      }
    }
  
    if ( lastLevelLambda > 0.0 )
    {
      lastLevelLambda = Clip3( 0.1, 10000.0, lastLevelLambda );
      estLambda = Clip3( lastLevelLambda * pow( 2.0, -3.0/3.0 ), lastLevelLambda * pow( 2.0, 3.0/3.0 ), estLambda );
    }
  
    if ( lastPicLambda > 0.0 )
    {
      lastPicLambda = Clip3( 0.1, 2000.0, lastPicLambda );
      estLambda = Clip3( lastPicLambda * pow( 2.0, -10.0/3.0 ), lastPicLambda * pow( 2.0, 10.0/3.0 ), estLambda );
    }
    else if ( lastValidLambda > 0.0 )
    {
      lastValidLambda = Clip3( 0.1, 2000.0, lastValidLambda );
      estLambda = Clip3( lastValidLambda * pow(2.0, -10.0/3.0), lastValidLambda * pow(2.0, 10.0/3.0), estLambda );
    }
    else
    {
      estLambda = Clip3( 0.1, 10000.0, estLambda );
    }
  
    if ( estLambda < 0.1 )
    {
      estLambda = 0.1;
    }
  
    m_estPicLambda = estLambda;
  
    Double totalWeight = 0.0;
    // initial BU bit allocation weight
    for ( Int i=0; i<m_numberOfLCU; i++ )
    {
      Double alphaLCU, betaLCU;
      if ( m_encRCSeq->getUseLCUSeparateModel() )
      {
        alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;
        betaLCU  = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;
      }
      else
      {
        alphaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
        betaLCU  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
      }
  
      m_LCUs[i].m_bitWeight =  m_LCUs[i].m_numberOfPixel * pow( estLambda/alphaLCU, 1.0/betaLCU );
  
      if ( m_LCUs[i].m_bitWeight < 0.01 )
      {
        m_LCUs[i].m_bitWeight = 0.01;
      }
      totalWeight += m_LCUs[i].m_bitWeight;
    }
    for ( Int i=0; i<m_numberOfLCU; i++ )
    {
      Double BUTargetBits = m_targetBits * m_LCUs[i].m_bitWeight / totalWeight;
      m_LCUs[i].m_bitWeight = BUTargetBits;
    }
  
    return estLambda;
  }
  
  Int TEncRCPic::estimatePicQP( Double lambda, list<TEncRCPic*>& listPreviousPictures )
  {
    Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 );
  
    Int lastLevelQP = g_RCInvalidQPValue;
    Int lastPicQP   = g_RCInvalidQPValue;
    Int lastValidQP = g_RCInvalidQPValue;
    list<TEncRCPic*>::iterator it;
    for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )
    {
      if ( (*it)->getFrameLevel() == m_frameLevel )
      {
        lastLevelQP = (*it)->getPicActualQP();
      }
      lastPicQP = (*it)->getPicActualQP();
      if ( lastPicQP > g_RCInvalidQPValue )
      {
        lastValidQP = lastPicQP;
      }
    }
  
    if ( lastLevelQP > g_RCInvalidQPValue )
    {
      QP = Clip3( lastLevelQP - 3, lastLevelQP + 3, QP );
    }
  
    if( lastPicQP > g_RCInvalidQPValue )
    {
      QP = Clip3( lastPicQP - 10, lastPicQP + 10, QP );
    }
    else if( lastValidQP > g_RCInvalidQPValue )
    {
      QP = Clip3( lastValidQP - 10, lastValidQP + 10, QP );
    }
  
    return QP;
  }
  
  Double TEncRCPic::getLCUTargetBpp(SliceType eSliceType)
  {
    Int   LCUIdx    = getLCUCoded();
    Double bpp      = -1.0;
    Int avgBits     = 0;
  
    if (eSliceType == I_SLICE)
    {
      Int noOfLCUsLeft = m_numberOfLCU - LCUIdx + 1;
      Int bitrateWindow = min(4,noOfLCUsLeft);
      Double MAD      = getLCU(LCUIdx).m_costIntra;
  
      if (m_remainingCostIntra > 0.1 )
      {
        Double weightedBitsLeft = (m_bitsLeft*bitrateWindow+(m_bitsLeft-getLCU(LCUIdx).m_targetBitsLeft)*noOfLCUsLeft)/(Double)bitrateWindow;
        avgBits = Int( MAD*weightedBitsLeft/m_remainingCostIntra );
      }
      else
      {
        avgBits = Int( m_bitsLeft / m_LCULeft );
      }
      m_remainingCostIntra -= MAD;
    }
    else
    {
      Double totalWeight = 0;
      for ( Int i=LCUIdx; i<m_numberOfLCU; i++ )
      {
        totalWeight += m_LCUs[i].m_bitWeight;
      }
      Int realInfluenceLCU = min( g_RCLCUSmoothWindowSize, getLCULeft() );
      avgBits = (Int)( m_LCUs[LCUIdx].m_bitWeight - ( totalWeight - m_bitsLeft ) / realInfluenceLCU + 0.5 );
    }
  
    if ( avgBits < 1 )
    {
      avgBits = 1;
    }
  
    bpp = ( Double )avgBits/( Double )m_LCUs[ LCUIdx ].m_numberOfPixel;
    m_LCUs[ LCUIdx ].m_targetBits = avgBits;
  
    return bpp;
  }
  
  Double TEncRCPic::getLCUEstLambda( Double bpp )
  {
    Int   LCUIdx = getLCUCoded();
    Double alpha;
    Double beta;
    if ( m_encRCSeq->getUseLCUSeparateModel() )
    {
      alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha;
      beta  = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta;
    }
    else
    {
      alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
      beta  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
    }
  
    Double estLambda = alpha * pow( bpp, beta );
    //for Lambda clip, picture level clip
    Double clipPicLambda = m_estPicLambda;
  
    //for Lambda clip, LCU level clip
    Double clipNeighbourLambda = -1.0;
    for ( Int i=LCUIdx - 1; i>=0; i-- )
    {
      if ( m_LCUs[i].m_lambda > 0 )
      {
        clipNeighbourLambda = m_LCUs[i].m_lambda;
        break;
      }
    }
  
    if ( clipNeighbourLambda > 0.0 )
    {
      estLambda = Clip3( clipNeighbourLambda * pow( 2.0, -1.0/3.0 ), clipNeighbourLambda * pow( 2.0, 1.0/3.0 ), estLambda );
    }
  
    if ( clipPicLambda > 0.0 )
    {
      estLambda = Clip3( clipPicLambda * pow( 2.0, -2.0/3.0 ), clipPicLambda * pow( 2.0, 2.0/3.0 ), estLambda );
    }
    else
    {
      estLambda = Clip3( 10.0, 1000.0, estLambda );
    }
  
    if ( estLambda < 0.1 )
    {
      estLambda = 0.1;
    }
  
    return estLambda;
  }
  
  Int TEncRCPic::getLCUEstQP( Double lambda, Int clipPicQP )
  {
    Int LCUIdx = getLCUCoded();
    Int estQP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 );
  
    //for Lambda clip, LCU level clip
    Int clipNeighbourQP = g_RCInvalidQPValue;
    for ( Int i=LCUIdx - 1; i>=0; i-- )
    {
      if ( (getLCU(i)).m_QP > g_RCInvalidQPValue )
      {
        clipNeighbourQP = getLCU(i).m_QP;
        break;
      }
    }
  
    if ( clipNeighbourQP > g_RCInvalidQPValue )
    {
      estQP = Clip3( clipNeighbourQP - 1, clipNeighbourQP + 1, estQP );
    }
  
    estQP = Clip3( clipPicQP - 2, clipPicQP + 2, estQP );
  
    return estQP;
  }
  
  Void TEncRCPic::updateAfterCTU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter )
  {
    m_LCUs[LCUIdx].m_actualBits = bits;
    m_LCUs[LCUIdx].m_QP         = QP;
    m_LCUs[LCUIdx].m_lambda     = lambda;
  
    m_LCULeft--;
    m_bitsLeft   -= bits;
    m_pixelsLeft -= m_LCUs[LCUIdx].m_numberOfPixel;
  
    if ( !updateLCUParameter )
    {
      return;
    }
  
    if ( !m_encRCSeq->getUseLCUSeparateModel() )
    {
      return;
    }
  
    Double alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha;
    Double beta  = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta;
  
    Int LCUActualBits   = m_LCUs[LCUIdx].m_actualBits;
    Int LCUTotalPixels  = m_LCUs[LCUIdx].m_numberOfPixel;
    Double bpp         = ( Double )LCUActualBits/( Double )LCUTotalPixels;
    Double calLambda   = alpha * pow( bpp, beta );
    Double inputLambda = m_LCUs[LCUIdx].m_lambda;
  
    if( inputLambda < 0.01 || calLambda < 0.01 || bpp < 0.0001 )
    {
      alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );
      beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );
  
      alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
      beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );
  
      TRCParameter rcPara;
      rcPara.m_alpha = alpha;
      rcPara.m_beta  = beta;
      m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara );
  
      return;
    }
  
    calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );
    alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
    Double lnbpp = log( bpp );
    lnbpp = Clip3( -5.0, -0.1, lnbpp );
    beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;
  
    alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
    beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );
  
    TRCParameter rcPara;
    rcPara.m_alpha = alpha;
    rcPara.m_beta  = beta;
    m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara );
  
  }
  
  Double TEncRCPic::calAverageQP()
  {
    Int totalQPs = 0;
    Int numTotalLCUs = 0;
  
    Int i;
    for ( i=0; i<m_numberOfLCU; i++ )
    {
      if ( m_LCUs[i].m_QP > 0 )
      {
        totalQPs += m_LCUs[i].m_QP;
        numTotalLCUs++;
      }
    }
  
    Double avgQP = 0.0;
    if ( numTotalLCUs == 0 )
    {
      avgQP = g_RCInvalidQPValue;
    }
    else
    {
      avgQP = ((Double)totalQPs) / ((Double)numTotalLCUs);
    }
    return avgQP;
  }
  
  Double TEncRCPic::calAverageLambda()
  {
    Double totalLambdas = 0.0;
    Int numTotalLCUs = 0;
  
    Int i;
    for ( i=0; i<m_numberOfLCU; i++ )
    {
      if ( m_LCUs[i].m_lambda > 0.01 )
      {
        totalLambdas += log( m_LCUs[i].m_lambda );
        numTotalLCUs++;
      }
    }
  
    Double avgLambda;
    if( numTotalLCUs == 0 )
    {
      avgLambda = -1.0;
    }
    else
    {
      avgLambda = pow( 2.7183, totalLambdas / numTotalLCUs );
    }
    return avgLambda;
  }
  
  
  Void TEncRCPic::updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, SliceType eSliceType)
  {
    m_picActualHeaderBits = actualHeaderBits;
    m_picActualBits       = actualTotalBits;
    if ( averageQP > 0.0 )
    {
      m_picQP             = Int( averageQP + 0.5 );
    }
    else
    {
      m_picQP             = g_RCInvalidQPValue;
    }
    m_picLambda           = averageLambda;
  
    Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
    Double beta  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
  
    if (eSliceType == I_SLICE)
    {
      updateAlphaBetaIntra(&alpha, &beta);
    }
    else
    {
      // update parameters
      Double picActualBits = ( Double )m_picActualBits;
      Double picActualBpp  = picActualBits/(Double)m_numberOfPixel;
      Double calLambda     = alpha * pow( picActualBpp, beta );
      Double inputLambda   = m_picLambda;
  
      if ( inputLambda < 0.01 || calLambda < 0.01 || picActualBpp < 0.0001 )
      {
        alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );
        beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );
  
        alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
        beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );
  
        TRCParameter rcPara;
        rcPara.m_alpha = alpha;
        rcPara.m_beta  = beta;
        m_encRCSeq->setPicPara( m_frameLevel, rcPara );
  
        return;
      }
  
      calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );
      alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
      Double lnbpp = log( picActualBpp );
      lnbpp = Clip3( -5.0, -0.1, lnbpp );
  
      beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;
  
      alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
      beta  = Clip3( g_RCBetaMinValue,  g_RCBetaMaxValue,  beta  );
    }
  
    TRCParameter rcPara;
    rcPara.m_alpha = alpha;
    rcPara.m_beta  = beta;
  
    m_encRCSeq->setPicPara( m_frameLevel, rcPara );
  
    if ( m_frameLevel == 1 )
    {
      Double currLambda = Clip3( 0.1, 10000.0, m_picLambda );
      Double updateLastLambda = g_RCWeightHistoryLambda * m_encRCSeq->getLastLambda() + g_RCWeightCurrentLambda * currLambda;
      m_encRCSeq->setLastLambda( updateLastLambda );
    }
  }
  
  Int TEncRCPic::getRefineBitsForIntra( Int orgBits )
  {
    Double alpha=0.25, beta=0.5582;
    Int iIntraBits;
  
    if (orgBits*40 < m_numberOfPixel)
    {
      alpha=0.25;
    }
    else
    {
      alpha=0.30;
    }
  
    iIntraBits = (Int)(alpha* pow(m_totalCostIntra*4.0/(Double)orgBits, beta)*(Double)orgBits+0.5);
  
    return iIntraBits;
  }
  
  Double TEncRCPic::calculateLambdaIntra(Double alpha, Double beta, Double MADPerPixel, Double bitsPerPixel)
  {
    return ( (alpha/256.0) * pow( MADPerPixel/bitsPerPixel, beta ) );
  }
  
  Void TEncRCPic::updateAlphaBetaIntra(Double *alpha, Double *beta)
  {
    Double lnbpp = log(pow(m_totalCostIntra / (Double)m_numberOfPixel, BETA1));
    Double diffLambda = (*beta)*(log((Double)m_picActualBits)-log((Double)m_targetBits));
  
    diffLambda = Clip3(-0.125, 0.125, 0.25*diffLambda);
    *alpha    =  (*alpha) * exp(diffLambda);
    *beta     =  (*beta) + diffLambda / lnbpp;
  }
  
  
  Void TEncRCPic::getLCUInitTargetBits()
  {
    Int iAvgBits     = 0;
  
    m_remainingCostIntra = m_totalCostIntra;
    for (Int i=m_numberOfLCU-1; i>=0; i--)
    {
      iAvgBits += Int(m_targetBits * getLCU(i).m_costIntra/m_totalCostIntra);
      getLCU(i).m_targetBitsLeft = iAvgBits;
    }
  }
  
  
  Double TEncRCPic::getLCUEstLambdaAndQP(Double bpp, Int clipPicQP, Int *estQP)
  {
    Int   LCUIdx = getLCUCoded();
  
    Double   alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
    Double   beta  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
  
    Double costPerPixel = getLCU(LCUIdx).m_costIntra/(Double)getLCU(LCUIdx).m_numberOfPixel;
    costPerPixel = pow(costPerPixel, BETA1);
    Double estLambda = calculateLambdaIntra(alpha, beta, costPerPixel, bpp);
  
    Int clipNeighbourQP = g_RCInvalidQPValue;
    for (Int i=LCUIdx-1; i>=0; i--)
    {
      if ((getLCU(i)).m_QP > g_RCInvalidQPValue)
      {
        clipNeighbourQP = getLCU(i).m_QP;
        break;
      }
    }
  
    Int minQP = clipPicQP - 2;
    Int maxQP = clipPicQP + 2;
  
    if ( clipNeighbourQP > g_RCInvalidQPValue )
    {
      maxQP = min(clipNeighbourQP + 1, maxQP);
      minQP = max(clipNeighbourQP - 1, minQP);
    }
  
    Double maxLambda=exp(((Double)(maxQP+0.49)-13.7122)/4.2005);
    Double minLambda=exp(((Double)(minQP-0.49)-13.7122)/4.2005);
  
    estLambda = Clip3(minLambda, maxLambda, estLambda);
  
    *estQP = Int( 4.2005 * log(estLambda) + 13.7122 + 0.5 );
    *estQP = Clip3(minQP, maxQP, *estQP);
  
    return estLambda;
  }
  
  TEncRateCtrl::TEncRateCtrl()
  {
    m_encRCSeq = NULL;
    m_encRCGOP = NULL;
    m_encRCPic = NULL;
  }
  
  TEncRateCtrl::~TEncRateCtrl()
  {
    destroy();
  }
  
  Void TEncRateCtrl::destroy()
  {
    if ( m_encRCSeq != NULL )
    {
      delete m_encRCSeq;
      m_encRCSeq = NULL;
    }
    if ( m_encRCGOP != NULL )
    {
      delete m_encRCGOP;
      m_encRCGOP = NULL;
    }
    while ( m_listRCPictures.size() > 0 )
    {
      TEncRCPic* p = m_listRCPictures.front();
      m_listRCPictures.pop_front();
      delete p;
    }
  }
  
  Void TEncRateCtrl::init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry  GOPList[MAX_GOP] )
  {
    destroy();
  
    Bool isLowdelay = true;
    for ( Int i=0; i<GOPSize-1; i++ )
    {
      if ( GOPList[i].m_POC > GOPList[i+1].m_POC )
      {
        isLowdelay = false;
        break;
      }
    }
  
    Int numberOfLevel = 1;
    Int adaptiveBit = 0;
    if ( keepHierBits > 0 )
    {
      numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1;
    }
    if ( !isLowdelay && GOPSize == 8 )
    {
      numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1;
    }
    numberOfLevel++;    // intra picture
    numberOfLevel++;    // non-reference picture
  
  
    Int* bitsRatio;
    bitsRatio = new Int[ GOPSize ];
    for ( Int i=0; i<GOPSize; i++ )
    {
      bitsRatio[i] = 10;
      if ( !GOPList[i].m_refPic )
      {
        bitsRatio[i] = 2;
      }
    }
  
    if ( keepHierBits > 0 )
    {
      Double bpp = (Double)( targetBitrate / (Double)( frameRate*picWidth*picHeight ) );
      if ( GOPSize == 4 && isLowdelay )
      {
        if ( bpp > 0.2 )
        {
          bitsRatio[0] = 2;
          bitsRatio[1] = 3;
          bitsRatio[2] = 2;
          bitsRatio[3] = 6;
        }
        else if( bpp > 0.1 )
        {
          bitsRatio[0] = 2;
          bitsRatio[1] = 3;
          bitsRatio[2] = 2;
          bitsRatio[3] = 10;
        }
        else if ( bpp > 0.05 )
        {
          bitsRatio[0] = 2;
          bitsRatio[1] = 3;
          bitsRatio[2] = 2;
          bitsRatio[3] = 12;
        }
        else
        {
          bitsRatio[0] = 2;
          bitsRatio[1] = 3;
          bitsRatio[2] = 2;
          bitsRatio[3] = 14;
        }
  
        if ( keepHierBits == 2 )
        {
          adaptiveBit = 1;
        }
      }
      else if ( GOPSize == 8 && !isLowdelay )
      {
        if ( bpp > 0.2 )
        {
          bitsRatio[0] = 15;
          bitsRatio[1] = 5;
          bitsRatio[2] = 4;
          bitsRatio[3] = 1;
          bitsRatio[4] = 1;
          bitsRatio[5] = 4;
          bitsRatio[6] = 1;
          bitsRatio[7] = 1;
        }
        else if ( bpp > 0.1 )
        {
          bitsRatio[0] = 20;
          bitsRatio[1] = 6;
          bitsRatio[2] = 4;
          bitsRatio[3] = 1;
          bitsRatio[4] = 1;
          bitsRatio[5] = 4;
          bitsRatio[6] = 1;
          bitsRatio[7] = 1;
        }
        else if ( bpp > 0.05 )
        {
          bitsRatio[0] = 25;
          bitsRatio[1] = 7;
          bitsRatio[2] = 4;
          bitsRatio[3] = 1;
          bitsRatio[4] = 1;
          bitsRatio[5] = 4;
          bitsRatio[6] = 1;
          bitsRatio[7] = 1;
        }
        else
        {
          bitsRatio[0] = 30;
          bitsRatio[1] = 8;
          bitsRatio[2] = 4;
          bitsRatio[3] = 1;
          bitsRatio[4] = 1;
          bitsRatio[5] = 4;
          bitsRatio[6] = 1;
          bitsRatio[7] = 1;
        }
  
        if ( keepHierBits == 2 )
        {
          adaptiveBit = 2;
        }
      }
      else
      {
        printf( "\n hierarchical bit allocation is not support for the specified coding structure currently.\n" );
      }
    }
  
    Int* GOPID2Level = new Int[ GOPSize ];
    for ( Int i=0; i<GOPSize; i++ )
    {
      GOPID2Level[i] = 1;
      if ( !GOPList[i].m_refPic )
      {
        GOPID2Level[i] = 2;
      }
    }
  
    if ( keepHierBits > 0 )
    {
      if ( GOPSize == 4 && isLowdelay )
      {
        GOPID2Level[0] = 3;
        GOPID2Level[1] = 2;
        GOPID2Level[2] = 3;
        GOPID2Level[3] = 1;
      }
      else if ( GOPSize == 8 && !isLowdelay )
      {
        GOPID2Level[0] = 1;
        GOPID2Level[1] = 2;
        GOPID2Level[2] = 3;
        GOPID2Level[3] = 4;
        GOPID2Level[4] = 4;
        GOPID2Level[5] = 3;
        GOPID2Level[6] = 4;
        GOPID2Level[7] = 4;
      }
    }
  
    if ( !isLowdelay && GOPSize == 8 )
    {
      GOPID2Level[0] = 1;
      GOPID2Level[1] = 2;
      GOPID2Level[2] = 3;
      GOPID2Level[3] = 4;
      GOPID2Level[4] = 4;
      GOPID2Level[5] = 3;
      GOPID2Level[6] = 4;
      GOPID2Level[7] = 4;
    }
  
    m_encRCSeq = new TEncRCSeq;
    m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit );
    m_encRCSeq->initBitsRatio( bitsRatio );
    m_encRCSeq->initGOPID2Level( GOPID2Level );
    m_encRCSeq->initPicPara();
    if ( useLCUSeparateModel )
    {
      m_encRCSeq->initLCUPara();
    }
  #if U0132_TARGET_BITS_SATURATION
    m_CpbSaturationEnabled = false;
    m_cpbSize              = targetBitrate;
    m_cpbState             = (UInt)(m_cpbSize*0.5f);
    m_bufferingRate        = (Int)(targetBitrate / frameRate);
  #endif
  
    delete[] bitsRatio;
    delete[] GOPID2Level;
  }
  
  Void TEncRateCtrl::initRCPic( Int frameLevel )
  {
    m_encRCPic = new TEncRCPic;
    m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );
  }
  
  Void TEncRateCtrl::initRCGOP( Int numberOfPictures )
  {
    m_encRCGOP = new TEncRCGOP;
    m_encRCGOP->create( m_encRCSeq, numberOfPictures );
  }
  
  #if U0132_TARGET_BITS_SATURATION
  Int  TEncRateCtrl::updateCpbState(Int actualBits)
  {
    Int cpbState = 1;
  
    m_cpbState -= actualBits;
    if (m_cpbState < 0)
    {
      cpbState = -1;
    }
  
    m_cpbState += m_bufferingRate;
    if (m_cpbState > m_cpbSize)
    {
      cpbState = 0;
    }
  
    return cpbState;
  }
  
  Void TEncRateCtrl::initHrdParam(const TComHRD* pcHrd, Int iFrameRate, Double fInitialCpbFullness)
  {
    m_CpbSaturationEnabled = true;
    m_cpbSize = (pcHrd->getCpbSizeValueMinus1(0, 0, 0) + 1) << (4 + pcHrd->getCpbSizeScale());
    m_cpbState = (UInt)(m_cpbSize*fInitialCpbFullness);
    m_bufferingRate = (UInt)(((pcHrd->getBitRateValueMinus1(0, 0, 0) + 1) << (6 + pcHrd->getBitRateScale())) / iFrameRate);
    printf("\nHRD - [Initial CPB state %6d] [CPB Size %6d] [Buffering Rate %6d]\n", m_cpbState, m_cpbSize, m_bufferingRate);
  }
  #endif
  
  Void TEncRateCtrl::destroyRCGOP()
  {
    delete m_encRCGOP;
    m_encRCGOP = NULL;
  }
  