/* 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-2014, 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 _HM_TENCRATECTRL_H_ #define _HM_TENCRATECTRL_H_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "../TLibCommon/CommonDef.h" #include "../TLibCommon/TComDataCU.h" #include #include using namespace std; //! \ingroup TLibEncoder //! \{ #include "../TLibEncoder/TEncCfg.h" #include #include 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; 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; #define ALPHA 6.7542; #define BETA1 1.2517 #define BETA2 1.7860 struct TRCLCU { Int m_actualBits; Int m_QP; // QP of skip mode is set to g_RCInvalidQPValue Int m_targetBits; Double m_lambda; Double m_bitWeight; Int m_numberOfPixel; Double m_costIntra; Int m_targetBitsLeft; #if KWU_RC_MADPRED_E0227 Double m_MAD; Int m_CUWidth; Int m_CUHeight; Double m_IVMAD; #endif }; struct TRCParameter { Double m_alpha; Double m_beta; }; class TEncRCSeq { public: TEncRCSeq(); ~TEncRCSeq(); public: Void create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit ); 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 ); Void setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB ); 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& listPreviousPictures, Int layerID ); #else Void create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list& listPreviousPictures ); #endif Void destroy(); #if KWU_RC_MADPRED_E0227 Double estimatePicLambdaIV( list& listPreviousPictures, Int curPOC ); #endif Int estimatePicQP ( Double lambda, list& listPreviousPictures ); Int getRefineBitsForIntra(Int orgBits); Double calculateLambdaIntra(double alpha, double beta, double MADPerPixel, double bitsPerPixel); Double estimatePicLambda( list& listPreviousPictures, SliceType eSliceType); Void updateAlphaBetaIntra(double *alpha, double *beta); Double getLCUTargetBpp(SliceType eSliceType); Double getLCUEstLambdaAndQP(Double bpp, Int clipPicQP, Int *estQP); #if KWU_RC_MADPRED_E0227 Double getLCUTargetBppforInterView( list& listPreviousPictures, TComDataCU* pcCU, Double basePos, Double curPos, Double focalLen, Double znear, Double zfar, Int direction, Int* disparity ); #endif Double getLCUEstLambda( Double bpp ); Int getLCUEstQP( Double lambda, Int clipPicQP ); Void updateAfterLCU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter = true ); Void updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, SliceType eSliceType); Void addToPictureLsit( list& listPreviousPictures ); #if KWU_RC_MADPRED_E0227 Void addToPictureLsitIV( list& listPreviousPictures ); Void setIVPic( TEncRCPic* baseRCPic ); #endif Double calAverageQP(); Double calAverageLambda(); private: Int xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP ); Int xEstPicHeaderBits( list& 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; } 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; } Void setTargetBits( Int bits ) { m_targetBits = bits; m_bitsLeft = bits;} Void setTotalIntraCost(Double cost) { m_totalCostIntra = cost; } Void getLCUInitTargetBits(); #if KWU_RC_MADPRED_E0227 Double getTotalMAD() { return m_totalMAD; } Void setTotalMAD( Double MAD ) { m_totalMAD = MAD; } Double getIVTotalMAD() { return m_IVtotalMAD; } Void setIVTotalMAD( Double MAD ) { m_IVtotalMAD = MAD; } #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; } #if KWU_RC_MADPRED_E0227 Int getLayerID() { return m_LayerID; } Void setLayerID(Int layerid) { m_LayerID = layerid; } #endif private: TEncRCSeq* m_encRCSeq; TEncRCGOP* m_encRCGOP; Int m_frameLevel; Int m_numberOfPixel; Int m_numberOfLCU; 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 Double m_totalCostIntra; Double m_remainingCostIntra; Int m_picActualBits; // the whole picture, including header Int m_picQP; // in integer form Double m_picLambda; #if KWU_RC_MADPRED_E0227 Double m_totalMAD; TEncRCPic* m_lastPicture; Int m_LayerID; TEncRCPic* m_lastIVPicture; Double m_IVtotalMAD; #endif }; class TEncRateCtrl { public: TEncRateCtrl(); ~TEncRateCtrl(); public: #if KWU_RC_MADPRED_E0227 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], Int layerID ); #else 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] ); #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& getPicList() { return m_listRCPictures; } #if KWU_RC_MADPRED_E0227 Int getLayerID() { return m_LayerID; } Void setLayerID(Int layerid) { m_LayerID = layerid; } #endif private: TEncRCSeq* m_encRCSeq; TEncRCGOP* m_encRCGOP; TEncRCPic* m_encRCPic; list m_listRCPictures; Int m_RCQP; #if KWU_RC_MADPRED_E0227 Int m_LayerID; #endif }; #endif