不多说,直接上代码,主要是参考K0103提案看的。
/* 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-2013, 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.h \brief Rate control manager class */ #ifndef __TENCRATECTRL__ #define __TENCRATECTRL__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "../TLibCommon/CommonDef.h" #include "../TLibCommon/TComDataCU.h" #include <vector> #include <algorithm> using namespace std; //! \ingroup TLibEncoder //! \{ #if RATE_CONTROL_LAMBDA_DOMAIN #include "../TLibEncoder/TEncCfg.h" #include <list> #include <cassert> const Int g_RCInvalidQPValue = -999; const Int g_RCSmoothWindowSize = 40; const Int g_RCMaxPicListSize = 32; const Double g_RCWeightPicTargetBitInGOP = 0.9; const Double g_RCWeightPicRargetBitInBuffer = 1.0 - g_RCWeightPicTargetBitInGOP; #if M0036_RC_IMPROVEMENT const Int g_RCIterationNum = 20; const Double g_RCWeightHistoryLambda = 0.5; const Double g_RCWeightCurrentLambda = 1.0 - g_RCWeightHistoryLambda; const Int g_RCLCUSmoothWindowSize = 4; const Double g_RCAlphaMinValue = 0.05; const Double g_RCAlphaMaxValue = 500.0; const Double g_RCBetaMinValue = -3.0; const Double g_RCBetaMaxValue = -0.1; #endif #if RATE_CONTROL_INTRA #define ALPHA 6.7542; #define BETA1 1.2517 #define BETA2 1.7860 #endif struct TRCLCU { Int m_actualBits; Int m_QP; // QP of skip mode is set to g_RCInvalidQPValue Int m_targetBits; Double m_lambda; #if M0036_RC_IMPROVEMENT Double m_bitWeight; #else Double m_MAD; #endif Int m_numberOfPixel;//指当前LCU的像素数 #if RATE_CONTROL_INTRA Double m_costIntra; Int m_targetBitsLeft; #endif }; struct TRCParameter { Double m_alpha; Double m_beta; }; class TEncRCSeq { public: TEncRCSeq(); ~TEncRCSeq(); public: //主要是初始化EC这个类 #if M0036_RC_IMPROVEMENT Void 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 create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel ); #endif Void destroy(); Void initBitsRatio( Int bitsRatio[] ); Void initGOPID2Level( Int GOPID2Level[] ); Void initPicPara( TRCParameter* picPara = NULL ); // NULL to initial with default value Void initLCUPara( TRCParameter** LCUPara = NULL ); // NULL to initial with default value Void updateAfterPic ( Int bits ); #if !RATE_CONTROL_INTRA Int getRefineBitsForIntra( Int orgBits ); #endif #if M0036_RC_IMPROVEMENT Void setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB ); #endif public: Int getTotalFrames() { return m_totalFrames; } Int getTargetRate() { return m_targetRate; } Int getFrameRate() { return m_frameRate; } Int getGOPSize() { return m_GOPSize; } Int getPicWidth() { return m_picWidth; } Int getPicHeight() { return m_picHeight; } Int getLCUWidth() { return m_LCUWidth; } Int getLCUHeight() { return m_LCUHeight; } Int getNumberOfLevel() { return m_numberOfLevel; } Int getAverageBits() { return m_averageBits; } Int getLeftAverageBits() { assert( m_framesLeft > 0 ); return (Int)(m_bitsLeft / m_framesLeft); } Bool getUseLCUSeparateModel() { return m_useLCUSeparateModel; } Int getNumPixel() { return m_numberOfPixel; } Int64 getTargetBits() { return m_targetBits; } Int getNumberOfLCU() { return m_numberOfLCU; } Int* getBitRatio() { return m_bitsRatio; } Int getBitRatio( Int idx ) { assert( idx<m_GOPSize); return m_bitsRatio[idx]; } Int* getGOPID2Level() { return m_GOPID2Level; } Int getGOPID2Level( Int ID ) { assert( ID < m_GOPSize ); return m_GOPID2Level[ID]; } TRCParameter* getPicPara() { return m_picPara; } TRCParameter getPicPara( Int level ) { assert( level < m_numberOfLevel ); return m_picPara[level]; } Void setPicPara( Int level, TRCParameter para ) { assert( level < m_numberOfLevel ); m_picPara[level] = para; } TRCParameter** getLCUPara() { return m_LCUPara; } TRCParameter* getLCUPara( Int level ) { assert( level < m_numberOfLevel ); return m_LCUPara[level]; } TRCParameter getLCUPara( Int level, Int LCUIdx ) { assert( LCUIdx < m_numberOfLCU ); return getLCUPara(level)[LCUIdx]; } Void setLCUPara( Int level, Int LCUIdx, TRCParameter para ) { assert( level < m_numberOfLevel ); assert( LCUIdx < m_numberOfLCU ); m_LCUPara[level][LCUIdx] = para; } Int getFramesLeft() { return m_framesLeft; } Int64 getBitsLeft() { return m_bitsLeft; } Double getSeqBpp() { return m_seqTargetBpp; } Double getAlphaUpdate() { return m_alphaUpdate; } Double getBetaUpdate() { return m_betaUpdate; } #if M0036_RC_IMPROVEMENT Int getAdaptiveBits() { return m_adaptiveBit; } Double getLastLambda() { return m_lastLambda; } Void setLastLambda( Double lamdba ) { m_lastLambda = lamdba; } #endif private: Int m_totalFrames; Int m_targetRate; Int m_frameRate; Int m_GOPSize; Int m_picWidth; Int m_picHeight; Int m_LCUWidth; Int m_LCUHeight; Int m_numberOfLevel;//控制alpha beta的参数个数 Int m_averageBits;//平均每帧图像的位数(bits) Int m_numberOfPixel;//图片的总像素数 Int64 m_targetBits;////文件编码后总的位数,为文件播放时间乘以码率,即文件的总码率 Int m_numberOfLCU;//表示一幅图片是LCU数量 Int* m_bitsRatio;//一个GOP里每幅图像的权值。 Int* m_GOPID2Level; TRCParameter* m_picPara; TRCParameter** m_LCUPara; Int m_framesLeft; Int64 m_bitsLeft; Double m_seqTargetBpp;//码率/(帧率*m_numberOfPixel) Double m_alphaUpdate; Double m_betaUpdate; Bool m_useLCUSeparateModel; #if M0036_RC_IMPROVEMENT Int m_adaptiveBit; Double m_lastLambda; #endif }; class TEncRCGOP { public: TEncRCGOP(); ~TEncRCGOP(); public: Void create( TEncRCSeq* encRCSeq, Int numPic ); Void destroy(); Void updateAfterPicture( Int bitsCost ); private: Int xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize );//根据残留帧的残留大小估计GOP的目标bit大小,对应的是K0103的(7)(8)公式 #if M0036_RC_IMPROVEMENT Void xCalEquaCoeff( TEncRCSeq* encRCSeq, Double* lambdaRatio, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize ); Double xSolveEqua( Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize ); #endif public: TEncRCSeq* getEncRCSeq() { return m_encRCSeq; } Int getNumPic() { return m_numPic;} Int getTargetBits() { return m_targetBits; } Int getPicLeft() { return m_picLeft; } Int getBitsLeft() { return m_bitsLeft; } Int getTargetBitInGOP( Int i ) { return m_picTargetBitInGOP[i]; } private: TEncRCSeq* m_encRCSeq; Int* m_picTargetBitInGOP;//表示一个GOP里的各个图片帧的所占的比特数 Int m_numPic; Int m_targetBits;//GOP里所有图片帧的总的比特数 Int m_picLeft; Int m_bitsLeft; }; class TEncRCPic { public: TEncRCPic(); ~TEncRCPic(); public: Void create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures ); Void destroy(); #if !RATE_CONTROL_INTRA Double estimatePicLambda( list<TEncRCPic*>& listPreviousPictures ); #endif Int estimatePicQP ( Double lambda, list<TEncRCPic*>& listPreviousPictures );//根据K0103的文档估计图片级的QP。 #if RATE_CONTROL_INTRA Int getRefineBitsForIntra(Int orgBits); Double calculateLambdaIntra(double alpha, double beta, double MADPerPixel, double bitsPerPixel); Double estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType); Void updateAlphaBetaIntra(double *alpha, double *beta); Double getLCUTargetBpp(SliceType eSliceType); Double getLCUEstLambdaAndQP(Double bpp, Int clipPicQP, Int *estQP); #else Double getLCUTargetBpp(); #endif Double getLCUEstLambda( Double bpp );//获得LCU的lambda Int getLCUEstQP( Double lambda, Int clipPicQP );//获得LCU的qp Void updateAfterLCU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter = true );//LCU之后的一些参数更新,例如alpha和beta那些 #if M0036_RC_IMPROVEMENT #if RATE_CONTROL_INTRA Void updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, SliceType eSliceType); #else Void updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda ); #endif #else Void updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, Double effectivePercentage ); #endif Void addToPictureLsit( list<TEncRCPic*>& listPreviousPictures ); #if !M0036_RC_IMPROVEMENT Double getEffectivePercentage(); #endif Double calAverageQP(); Double calAverageLambda(); private: Int xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP );//返回估计的当前视频帧的比特数 Int xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel );//返回估计的视频帧头的比特数 public: TEncRCSeq* getRCSequence() { return m_encRCSeq; } TEncRCGOP* getRCGOP() { return m_encRCGOP; } Int getFrameLevel() { return m_frameLevel; } Int getNumberOfPixel() { return m_numberOfPixel; } Int getNumberOfLCU() { return m_numberOfLCU; } Int getTargetBits() { return m_targetBits; } #if !RATE_CONTROL_INTRA Void setTargetBits( Int bits ) { m_targetBits = bits; } #endif Int getEstHeaderBits() { return m_estHeaderBits; } Int getLCULeft() { return m_LCULeft; } Int getBitsLeft() { return m_bitsLeft; } Int getPixelsLeft() { return m_pixelsLeft; } Int getBitsCoded() { return m_targetBits - m_estHeaderBits - m_bitsLeft; } Int getLCUCoded() { return m_numberOfLCU - m_LCULeft; } TRCLCU* getLCU() { return m_LCUs; } TRCLCU& getLCU( Int LCUIdx ) { return m_LCUs[LCUIdx]; } Int getPicActualHeaderBits() { return m_picActualHeaderBits; } #if !M0036_RC_IMPROVEMENT Double getTotalMAD() { return m_totalMAD; } Void setTotalMAD( Double MAD ) { m_totalMAD = MAD; } #endif #if RATE_CONTROL_INTRA Void setTargetBits( Int bits ) { m_targetBits = bits; m_bitsLeft = bits;} Void setTotalIntraCost(Double cost) { m_totalCostIntra = cost; } Void getLCUInitTargetBits(); #endif Int getPicActualBits() { return m_picActualBits; } Int getPicActualQP() { return m_picQP; } Double getPicActualLambda() { return m_picLambda; } Int getPicEstQP() { return m_estPicQP; } Void setPicEstQP( Int QP ) { m_estPicQP = QP; } Double getPicEstLambda() { return m_estPicLambda; } Void setPicEstLambda( Double lambda ) { m_picLambda = lambda; } private: TEncRCSeq* m_encRCSeq; TEncRCGOP* m_encRCGOP; Int m_frameLevel; Int m_numberOfPixel;//一帧图片的像素数 Int m_numberOfLCU;//一帧图片的LCU数 Int m_targetBits;//当前图片的比特数 Int m_estHeaderBits;//当前图片的帧头的比特数 Int m_estPicQP; Double m_estPicLambda; Int m_LCULeft; Int m_bitsLeft; Int m_pixelsLeft; TRCLCU* m_LCUs; Int m_picActualHeaderBits; // only SH and potential APS #if !M0036_RC_IMPROVEMENT Double m_totalMAD; #endif #if RATE_CONTROL_INTRA Double m_totalCostIntra; Double m_remainingCostIntra; #endif Int m_picActualBits; // the whole picture, including header Int m_picQP; // in integer form Double m_picLambda; #if !M0036_RC_IMPROVEMENT TEncRCPic* m_lastPicture; #endif }; class TEncRateCtrl { public: TEncRateCtrl(); ~TEncRateCtrl(); public: #if M0036_RC_IMPROVEMENT Void 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 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 Void destroy(); Void initRCPic( Int frameLevel ); Void initRCGOP( Int numberOfPictures ); Void destroyRCGOP(); public: Void setRCQP ( Int QP ) { m_RCQP = QP; } Int getRCQP () { return m_RCQP; } TEncRCSeq* getRCSeq() { assert ( m_encRCSeq != NULL ); return m_encRCSeq; } TEncRCGOP* getRCGOP() { assert ( m_encRCGOP != NULL ); return m_encRCGOP; } TEncRCPic* getRCPic() { assert ( m_encRCPic != NULL ); return m_encRCPic; } list<TEncRCPic*>& getPicList() { return m_listRCPictures; } private: TEncRCSeq* m_encRCSeq; TEncRCGOP* m_encRCGOP; TEncRCPic* m_encRCPic; list<TEncRCPic*> m_listRCPictures; Int m_RCQP; }; #else // ==================================================================================================================== // Class definition // ==================================================================================================================== #define MAX_DELTA_QP 2 #define MAX_CUDQP_DEPTH 0 typedef struct FrameData { Bool m_isReferenced; Int m_qp; Int m_bits; Double m_costMAD; }FrameData; typedef struct LCUData { Int m_qp; ///< coded QP Int m_bits; ///< actually generated bits Int m_pixels; ///< number of pixels for a unit Int m_widthInPixel; ///< number of pixels for width Int m_heightInPixel; ///< number of pixels for height Double m_costMAD; ///< texture complexity for a unit }LCUData; enum MAD_HISTORY { MAD_PPPrevious = 0, MAD_PPrevious = 1, MAD_Previous = 2, NUM_MAD_HISTORY= 3 }; class MADLinearModel { private: Bool m_activeOn; Double m_paramY1; Double m_paramY2; Double m_costMADs[NUM_MAD_HISTORY]; public: MADLinearModel () {}; ~MADLinearModel() {}; Void initMADLinearModel (); Double getMAD (); Void updateMADLiearModel (); Void updateMADHistory (Double costMAD); Bool IsUpdateAvailable () { return m_activeOn; } }; class PixelBaseURQQuadraticModel { private: Double m_paramHighX1; Double m_paramHighX2; Double m_paramLowX1; Double m_paramLowX2; public: PixelBaseURQQuadraticModel () {}; ~PixelBaseURQQuadraticModel() {}; Void initPixelBaseQuadraticModel (); Int getQP (Int qp, Int targetBits, Int numberOfPixels, Double costPredMAD); Void updatePixelBasedURQQuadraticModel (Int qp, Int bits, Int numberOfPixels, Double costMAD); Bool checkUpdateAvailable (Int qpReference ); Double xConvertQP2QStep (Int qp ); Int xConvertQStep2QP (Double qStep ); }; class TEncRateCtrl { private: Bool m_isLowdelay; Int m_prevBitrate; Int m_currBitrate; Int m_frameRate; Int m_refFrameNum; Int m_nonRefFrameNum; Int m_numOfPixels; Int m_sourceWidthInLCU; Int m_sourceHeightInLCU; Int m_sizeGOP; Int m_indexGOP; Int m_indexFrame; Int m_indexLCU; Int m_indexUnit; Int m_indexRefFrame; Int m_indexNonRefFrame; Int m_indexPOCInGOP; Int m_indexPrevPOCInGOP; Int m_occupancyVB; Int m_initialOVB; Int m_targetBufLevel; Int m_initialTBL; Int m_remainingBitsInGOP; Int m_remainingBitsInFrame; Int m_occupancyVBInFrame; Int m_targetBits; Int m_numUnitInFrame; Int m_codedPixels; Bool m_activeUnitLevelOn; Double m_costNonRefAvgWeighting; Double m_costRefAvgWeighting; Double m_costAvgbpp; FrameData* m_pcFrameData; LCUData* m_pcLCUData; MADLinearModel m_cMADLinearModel; PixelBaseURQQuadraticModel m_cPixelURQQuadraticModel; public: TEncRateCtrl () {}; virtual ~TEncRateCtrl() {}; Void create (Int sizeIntraPeriod, Int sizeGOP, Int frameRate, Int targetKbps, Int qp, Int numLCUInBasicUnit, Int sourceWidth, Int sourceHeight, Int maxCUWidth, Int maxCUHeight, const ChromaFormat format); Void destroy (); Void initFrameData (Int qp = 0); Void initUnitData (Int qp = 0); Int getFrameQP (Bool isReferenced, Int POC); Bool calculateUnitQP (); Int getUnitQP () { return m_pcLCUData[m_indexLCU].m_qp; } Void updateRCGOPStatus (); Void updataRCFrameStatus (Int frameBits, SliceType eSliceType); Void updataRCUnitStatus (); Void updateLCUData (TComDataCU* pcCU, UInt64 actualLCUBits, Int qp); Void updateFrameData (UInt64 actualFrameBits); Double xAdjustmentBits (Int& reductionBits, Int& compensationBits); Int getGOPId () { return m_indexFrame; } }; #endif #endif