zoukankan      html  css  js  c++  java
  • HEVC码率控制浅析——HM代码阅读之二

    上一篇文章主要讨论了RC的总体框架,本文开始分析具体的代码实现细节。分析的顺序按照总体框架来,即初始化-->更新。

    (1)m_cRateCtrl.init()

    #if M0036_RC_IMPROVEMENT
    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] )
    #else
    Void TEncRateCtrl::init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Bool keepHierBits, Bool useLCUSeparateModel, GOPEntry  GOPList[MAX_GOP] )
    #endif
    {
      destroy();
    
      Bool isLowdelay = true;
      for ( Int i=0; i<GOPSize-1; i++ )
      {
        if ( GOPList[i].m_POC > GOPList[i+1].m_POC ) //!< 判断是否为lowdelay配置
        {
          isLowdelay = false;
          break;
        }
      }
    
      Int numberOfLevel = 1;
    #if M0036_RC_IMPROVEMENT
      Int adaptiveBit = 0;
      if ( keepHierBits > 0 )
    #else
      if ( keepHierBits )	//!< hierarchical structure
    #endif
      {
        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;	//!< 每一幅picture的权值
      bitsRatio = new Int[ GOPSize ];
      for ( Int i=0; i<GOPSize; i++ )
      {
        bitsRatio[i] = 10;
        if ( !GOPList[i].m_refPic )
        {
          bitsRatio[i] = 2;
        }
      }
    
    #if M0036_RC_IMPROVEMENT
      if ( keepHierBits > 0 )
    #else
      if ( keepHierBits )
    #endif
      {
        Double bpp = (Double)( targetBitrate / (Double)( frameRate*picWidth*picHeight ) ); //!< K0103 式子(3)
        if ( GOPSize == 4 && isLowdelay ) //!< K0103 Table 1
        {
          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 M0036_RC_IMPROVEMENT
          if ( keepHierBits == 2 )
          {
            adaptiveBit = 1;
          }
    #endif
        }
        else if ( GOPSize == 8 && !isLowdelay ) //!< K0103 Table 2
        {
          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 M0036_RC_IMPROVEMENT
          if ( keepHierBits == 2 )
          {
            adaptiveBit = 2;
          }
    #endif
        }
        else
        {
    #if M0036_RC_IMPROVEMENT
          printf( "
     hierarchical bit allocation is not support for the specified coding structure currently.
    " );
    #else
          printf( "
     hierarchical bit allocation is not support for the specified coding structure currently." );
    #endif
        }
      }
    
      Int* GOPID2Level = new int[ GOPSize ]; //!< 根据在GOP中的id确定所属的分层
      for ( int i=0; i<GOPSize; i++ )
      {
        GOPID2Level[i] = 1;
        if ( !GOPList[i].m_refPic )
        {
          GOPID2Level[i] = 2;
        }
      }
    #if M0036_RC_IMPROVEMENT
      if ( keepHierBits > 0 )
    #else
      if ( keepHierBits )
    #endif
      {
        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;
    #if M0036_RC_IMPROVEMENT
      m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit );
    #else //!< 序列级RC参数的初始化
      m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel );
    #endif
      m_encRCSeq->initBitsRatio( bitsRatio ); //!< 每幅picture的权值
      m_encRCSeq->initGOPID2Level( GOPID2Level ); 
      m_encRCSeq->initPicPara(/*TRCParameter* picPara  = NULL*/); //!< alpha, beta
      if ( useLCUSeparateModel )
      {
        m_encRCSeq->initLCUPara(); //!< alpha,beta初始化
      }
    
      delete[] bitsRatio;
      delete[] GOPID2Level;
    }


    分析该函数中调用的比较重要的若干个子函数:

    m_encRCSeq->create()

    #if M0036_RC_IMPROVEMENT
    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 )
    #else
    Void TEncRCSeq::create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel )
    #endif
    {
      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; //!< m_targetRate--bps
      
      //!< m_alphaUpdata和m_betaUpdate这两个变量用于在接下来更新lamda的参数值
      if ( m_seqTargetBpp < 0.03 )	//!< (..., 0.03)
      {
        m_alphaUpdate = 0.01;
        m_betaUpdate  = 0.005;
      }
      else if ( m_seqTargetBpp < 0.08 ) //!< [0.03, 0.08)
      {
        m_alphaUpdate = 0.05;
        m_betaUpdate  = 0.025;
      }
    #if M0036_RC_IMPROVEMENT
      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;
      }
    #else
      else //!< [0.08, ...]
      {
        m_alphaUpdate = 0.1;
        m_betaUpdate  = 0.05;
      }
    #endif
      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; //!< 一帧picture中包含的LCU数目
    
      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 ) //!< 每个LCU的alpha和beta都有各自的值
      {
        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;	//!< 剩余可用的比特数
    #if M0036_RC_IMPROVEMENT
      m_adaptiveBit = adaptiveBit;
      m_lastLambda = 0.0;
    #endif
    }


    m_encRCSeq->initPicPara()

    Void TEncRCSeq::initPicPara( TRCParameter* picPara )
    {
      assert( m_picPara != NULL );
    
      if ( picPara == NULL ) //!< K0103 式子(10)
      {
        for ( Int i=0; i<m_numberOfLevel; i++ )
        {
    #if RATE_CONTROL_INTRA
          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	//!< 第一帧图像的参数初始化
          m_picPara[i].m_alpha = 3.2003;
          m_picPara[i].m_beta  = -1.367;
    #endif
        }
      }
      else
      {
        for ( Int i=0; i<m_numberOfLevel; i++ )
        {
          m_picPara[i] = picPara[i];
        }
      }
    }


    (2)m_cRateCtrl.initRCGOP()

    Void TEncRateCtrl::initRCGOP( Int numberOfPictures )
    {
      m_encRCGOP = new TEncRCGOP;
      m_encRCGOP->create( m_encRCSeq, numberOfPictures );
    }
    Void TEncRCGOP::create( TEncRCSeq* encRCSeq, Int numPic )
    {
      destroy();
      Int targetBits = xEstGOPTargetBits( encRCSeq, numPic ); //!< GOP level bit allocation
    
    #if M0036_RC_IMPROVEMENT
      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;
      }
    #endif
    
      m_picTargetBitInGOP = new Int[numPic]; //!< 用于保存当前GOP中每幅picture对应的目标码率
      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 ); //!< 当前picture的权值
    #if M0036_RC_IMPROVEMENT
        m_picTargetBitInGOP[i] = (Int)( ((Double)targetBits) * currPicRatio / totalPicRatio );
    #else
        m_picTargetBitInGOP[i] = targetBits * currPicRatio / totalPicRatio; //!< K0103 式子(9),注意:由于是初始化,式子中的CodedGOP等于0
    #endif
      }
    
      m_encRCSeq    = encRCSeq;
      m_numPic       = numPic;
      m_targetBits   = targetBits;
      m_picLeft      = m_numPic;
      m_bitsLeft     = m_targetBits;
    }
    Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize )
    {
      Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() ); //!< 获得实际的平滑窗口大小
      Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() ); //!< RPicArg
      Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture ); //!< TAvgPic,计算方法跟K0103不同,这里利用left的思路计算,而K0103利用coded的思路计算,但结果是一样的
      Int targetBits = currentTargetBitsPerPic * GOPSize; //!< TGOP
    
      if ( targetBits < 200 )
      {
        targetBits = 200;   // at least allocate 200 bits for one GOP
      }
    
      return targetBits;
    }


    (未完待续...)

  • 相关阅读:
    经典测试工程师面试题(一)
    python面试题2
    python面试题1
    软件测试面试题2
    软件测试面试题1
    python读写csv文件
    死亡还是合并?和李开复聊聊走投无路创业公司(转)
    项目如何开始:怎样和客户谈需求(转)
    [转载]给IT人员支招:如何跟业务部门谈需求分析?
    VS2013的一些常用快捷键
  • 原文地址:https://www.cnblogs.com/riskyer/p/3299387.html
Copyright © 2011-2022 走看看