#ifndef X265_RATECONTROL_H
#define X265_RATECONTROL_H
#include "common.h"
#include "sei.h"
namespace X265_NS {
class Encoder;
class Frame;
class SEIBufferingPeriod;
struct SPS;
#define BASE_FRAME_DURATION 0.04
#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 lastSatd;
int64_t leadingNoBSatd;
int64_t rowTotalBits;
double blurredComplexity;
double qpaRc;
double qpAq;
double qRceq;
double qpPrev;
double frameSizePlanned;
double bufferRate;
double movingAvgSum;
double rowCplxrSum;
double qpNoVbv;
double bufferFill;
double frameDuration;
double clippedDuration;
double frameSizeEstimated;
double frameSizeMaximum;
int sliceType;
int bframes;
int poc;
int encodeOrder;
bool bLastMiniGopBFrame;
bool isActive;
double amortizeFrames;
double amortizeFraction;
uint64_t expectedBits;
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;
};
class RateControl
{
public:
x265_param* m_param;
Slice* m_curSlice;
SliceType m_sliceType;
int m_ncu;
int m_qp;
bool m_isAbr;
bool m_isVbv;
bool m_isCbr;
bool m_singleFrameVbv;
bool m_isGrainEnabled;
bool m_isAbrReset;
bool m_isNextGop;
int m_lastAbrResetPoc;
double m_rateTolerance;
double m_frameDuration;
double m_bitrate;
double m_rateFactorConstant;
double m_bufferSize;
double m_bufferFillFinal;
double m_bufferFill;
double m_bufferRate;
double m_vbvMaxRate;
double m_rateFactorMaxIncrement;
double m_rateFactorMaxDecrement;
double m_avgPFrameQp;
double m_bufferFillActual;
double m_bufferExcess;
bool m_isFirstMiniGop;
Predictor m_pred[4];
int64_t m_leadingNoBSatd;
int m_predType;
double m_ipOffset;
double m_pbOffset;
int64_t m_bframeBits;
int64_t m_currentSatd;
int m_qpConstant[3];
int m_lastNonBPictType;
int m_framesDone;
double m_cplxrSum;
double m_wantedBitsWindow;
double m_accumPQp;
double m_accumPNorm;
double m_lastQScaleFor[3];
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;
int64_t m_encodedBits;
double m_fps;
int64_t m_satdCostWindow[50];
int64_t m_encodedBitsWindow[50];
int m_sliderPos;
int64_t m_lastRemovedSatdCost;
double m_movingAvgSum;
int64_t m_lastBsliceSatdCost;
int m_numBframesInPattern;
bool m_isPatternPresent;
bool m_isSceneTransition;
int m_lastPredictorReset;
double m_qpToEncodedBits[QP_MAX_MAX + 1];
ThreadSafeInteger m_startEndOrder;
int m_finalFrameCount;
bool m_bTerminated;
SEIBufferingPeriod m_bufPeriodSEI;
double m_nominalRemovalTime;
double m_prevCpbFinalAT;
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;
double m_lastAccumPNorm;
double m_expectedBitsSum;
int64_t m_predictedBits;
int *m_encOrder;
RateControlEntry* m_rce2Pass;
struct
{
uint16_t *qpBuffer[2];
int qpBufPos;
} m_cuTreeStats;
RateControl(x265_param& p);
bool init(const SPS& sps);
void initHRD(SPS& sps);
void reconfigureRC();
void setFinalFrameCount(int count);
void terminate();
void destroy();
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);
int rateControlSliceType(int frameNum);
bool cuTreeReadFor2Pass(Frame* curFrame);
void hrdFullness(SEIBufferingPeriod* sei);
int writeRateControlFrameStats(Frame* curFrame, RateControlEntry* rce);
bool initPass2();
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);
double tuneAbrQScaleFromFeedback(double qScale);
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);
};
}
#endif