/***************************************************************************** * Copyright (C) 2013-2020 MulticoreWare, Inc * * Authors: Sumalatha Polureddy * Aarthi Priya Thirumalai * Xun Xu, PPLive Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. * * This program is also available under a commercial proprietary license. * For more information, contact us at license @ x265.com. *****************************************************************************/ #ifndef X265_RATECONTROL_H #define X265_RATECONTROL_H #include "common.h" #include "sei.h" #include "ringmem.h" namespace X265_NS { // encoder namespace class Encoder; class Frame; class SEIBufferingPeriod; struct SPS; #define BASE_FRAME_DURATION 0.04 /* Arbitrary limitations as a sanity check. */ #define MAX_FRAME_DURATION 1.00 #define MIN_FRAME_DURATION 0.01 #define MIN_AMORTIZE_FRAME 10 #define MIN_AMORTIZE_FRACTION 0.2 #define CLIP_DURATION(f) x265_clip3(MIN_FRAME_DURATION, MAX_FRAME_DURATION, f) struct Predictor { double coeffMin; double coeff; double count; double decay; double offset; }; struct HRDTiming { double cpbInitialAT; double cpbFinalAT; double dpbOutputTime; double cpbRemovalTime; }; struct RateControlEntry { Predictor rowPreds[3][2]; Predictor* rowPred[2]; int64_t currentSatd; int64_t lastSatd; /* Contains the picture cost of the previous frame, required for resetAbr and VBV */ int64_t leadingNoBSatd; int64_t rowTotalBits; /* update cplxrsum and totalbits at the end of 2 rows */ double blurredComplexity; double qpaRc; double qpAq; double qRceq; double qpPrev; double frameSizePlanned; /* frame Size decided by RateCotrol before encoding the frame */ double bufferRate; double movingAvgSum; double rowCplxrSum; double qpNoVbv; double bufferFill; double bufferFillFinal; double bufferFillActual; double targetFill; bool vbvEndAdj; double frameDuration; double clippedDuration; double frameSizeEstimated; /* hold frameSize, updated from cu level vbv rc */ double frameSizeMaximum; /* max frame Size according to minCR restrictions and level of the video */ int sliceType; int bframes; int poc; int encodeOrder; bool bLastMiniGopBFrame; bool isActive; double amortizeFrames; double amortizeFraction; /* Required in 2-pass rate control */ uint64_t expectedBits; /* total expected bits up to the current frame (current one excluded) */ double iCuCount; double pCuCount; double skipCuCount; double expectedVbv; double qScale; double newQScale; double newQp; int mvBits; int miscBits; int coeffBits; bool keptAsRef; bool scenecut; bool isIdr; SEIPictureTiming *picTimingSEI; HRDTiming *hrdTiming; int rpsIdx; RPS rpsData; bool isFadeEnd; }; class RateControl { public: x265_param* m_param; Slice* m_curSlice; /* all info about the current frame */ SliceType m_sliceType; /* Current frame type */ int m_ncu; /* number of CUs in a frame */ int m_qp; /* updated qp for current frame */ /*Zone reconfiguration*/ double* m_relativeComplexity; int m_zoneBufferIdx; bool m_isAbr; bool m_isVbv; bool m_isCbr; bool m_singleFrameVbv; bool m_isGrainEnabled; bool m_isAbrReset; bool m_isNextGop; bool m_initVbv; int m_lastAbrResetPoc; int m_lastScenecut; int m_lastScenecutAwareIFrame; double m_rateTolerance; double m_frameDuration; /* current frame duration in seconds */ double m_bitrate; double m_rateFactorConstant; double m_bufferSize; double m_bufferFillFinal; /* real buffer as of the last finished frame */ double m_unclippedBufferFillFinal; /* real unclipped buffer as of the last finished frame used to log in CSV*/ double m_bufferFill; /* planned buffer, if all in-progress frames hit their bit budget */ double m_bufferRate; /* # of bits added to buffer_fill after each frame */ double m_vbvMaxRate; /* in kbps */ double m_rateFactorMaxIncrement; /* Don't allow RF above (CRF + this value). */ double m_rateFactorMaxDecrement; /* don't allow RF below (this value). */ double m_avgPFrameQp; double m_bufferFillActual; double m_bufferExcess; double m_minBufferFill; double m_maxBufferFill; bool m_isFirstMiniGop; Predictor m_pred[4]; /* Slice predictors to preidct bits for each Slice type - I,P,Bref and B */ int64_t m_leadingNoBSatd; int m_predType; /* Type of slice predictors to be used - depends on the slice type */ double m_ipOffset; double m_pbOffset; int64_t m_bframeBits; int64_t m_currentSatd; int m_qpConstant[3]; int m_lastNonBPictType; int m_framesDone; /* # of frames passed through RateCotrol already */ double m_cplxrSum; /* sum of bits*qscale/rceq */ double m_wantedBitsWindow; /* target bitrate * window */ double m_accumPQp; /* for determining I-frame quant */ double m_accumPNorm; double m_lastQScaleFor[3]; /* last qscale for a specific pict type, used for max_diff & ipb factor stuff */ double m_lstep; double m_lmin[3]; double m_lmax[3]; double m_shortTermCplxSum; double m_shortTermCplxCount; double m_lastRceq; double m_qCompress; int64_t m_totalBits; /* total bits used for already encoded frames (after ammortization) */ int64_t m_encodedBits; /* bits used for encoded frames (without ammortization) */ int64_t m_encodedSegmentBits; /* bits used for encoded frames in a segment*/ double m_segDur; double m_fps; int64_t m_satdCostWindow[50]; int64_t m_encodedBitsWindow[50]; int m_sliderPos; int64_t m_lastRemovedSatdCost; double m_movingAvgSum; /* To detect a pattern of low detailed static frames in single pass ABR using satdcosts */ int64_t m_lastBsliceSatdCost; int m_numBframesInPattern; bool m_isPatternPresent; bool m_isSceneTransition; int m_lastPredictorReset; double m_qpToEncodedBits[QP_MAX_MAX + 1]; /* a common variable on which rateControlStart, rateControlEnd and rateControUpdateStats waits to * sync the calls to these functions. For example * -F2: * rceStart 10 * rceUpdate 10 * rceEnd 9 * rceStart 11 * rceUpdate 11 * rceEnd 10 * rceStart 12 * rceUpdate 12 * rceEnd 11 */ ThreadSafeInteger m_startEndOrder; int m_finalFrameCount; /* set when encoder begins flushing */ bool m_bTerminated; /* set true when encoder is closing */ /* hrd stuff */ SEIBufferingPeriod m_bufPeriodSEI; double m_nominalRemovalTime; double m_prevCpbFinalAT; /* 2 pass */ bool m_2pass; bool m_isGopReEncoded; bool m_isQpModified; int m_numEntries; int m_start; int m_reencode; FILE* m_statFileOut; FILE* m_cutreeStatFileOut; FILE* m_cutreeStatFileIn; ///< store the cutree data in memory instead of file RingMem *m_cutreeShrMem; double m_lastAccumPNorm; double m_expectedBitsSum; /* sum of qscale2bits after rceq, ratefactor, and overflow, only includes finished frames */ int64_t m_predictedBits; int *m_encOrder; RateControlEntry* m_rce2Pass; Encoder* m_top; struct { uint16_t *qpBuffer[2]; /* Global buffers for converting MB-tree quantizer data. */ int qpBufPos; /* In order to handle pyramid reordering, QP buffer acts as a stack. * This value is the current position (0 or 1). */ } m_cuTreeStats; RateControl(x265_param& p, Encoder *enc); bool init(const SPS& sps); void initHRD(SPS& sps); void initVBV(const SPS& sps); void reconfigureRC(); void setFinalFrameCount(int count); void terminate(); /* un-block all waiting functions so encoder may close */ void destroy(); // to be called for each curFrame to process RateControl and set QP int rateControlStart(Frame* curFrame, RateControlEntry* rce, Encoder* enc); void rateControlUpdateStats(RateControlEntry* rce); int rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* rce, int *filler); int rowVbvRateControl(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv, uint32_t* m_sliceBaseRow, uint32_t sliceId); int rateControlSliceType(int frameNum); bool cuTreeReadFor2Pass(Frame* curFrame); void hrdFullness(SEIBufferingPeriod* sei); int writeRateControlFrameStats(Frame* curFrame, RateControlEntry* rce); bool initPass2(); bool initCUTreeSharedMem(); void skipCUTreeSharedMemRead(int32_t cnt); double forwardMasking(Frame* curFrame, double q); double backwardMasking(Frame* curFrame, double q); protected: static const int s_slidingWindowFrames; static const char* s_defaultStatFileName; double m_amortizeFraction; int m_amortizeFrames; int m_residualFrames; int m_partialResidualFrames; int m_residualCost; int m_partialResidualCost; x265_zone* getZone(); double getQScale(RateControlEntry *rce, double rateFactor); double rateEstimateQscale(Frame* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR double tuneAbrQScaleFromFeedback(double qScale); double tuneQScaleForZone(RateControlEntry *rce, double qScale); // Tune qScale to adhere to zone budget double tuneQscaleForSBRC(Frame* curFrame, double q); // Tune qScale to adhere to segment budget void accumPQpUpdate(); int getPredictorType(int lowresSliceType, int sliceType); int updateVbv(int64_t bits, RateControlEntry* rce); void updatePredictor(Predictor *p, double q, double var, double bits); double clipQscale(Frame* pic, RateControlEntry* rce, double q); void updateVbvPlan(Encoder* enc); double predictSize(Predictor *p, double q, double var); void checkAndResetABR(RateControlEntry* rce, bool isFrameDone); double predictRowsSizeSum(Frame* pic, RateControlEntry* rce, double qpm, int32_t& encodedBits); bool analyseABR2Pass(uint64_t allAvailableBits); void initFramePredictors(); double getDiffLimitedQScale(RateControlEntry *rce, double q); double countExpectedBits(int startPos, int framesCount); bool vbv2Pass(uint64_t allAvailableBits, int frameCount, int startPos); bool findUnderflow(double *fills, int *t0, int *t1, int over, int framesCount); bool fixUnderflow(int t0, int t1, double adjustment, double qscaleMin, double qscaleMax); double tuneQScaleForGrain(double rcOverflow); void splitdeltaPOC(char deltapoc[], RateControlEntry *rce); void splitbUsed(char deltapoc[], RateControlEntry *rce); void checkAndResetCRF(RateControlEntry* rce); }; } #endif // ifndef X265_RATECONTROL_H