ref: 91cd93e5d0c69fa2f9729c3f042c845e8f44296c
parent: 53f77ee7b5be9ad0a9b3ad1601df626eaeae4c70
parent: f6ce43f83bd8f6f453c6a642acd62aba3f339b37
author: huili2 <[email protected]>
date: Fri Jun 13 06:59:50 EDT 2014
Merge pull request #962 from dongzha/UseIntInRC Use Int instead of Double in Rate Control and Modify anchor SHA1 value
--- a/codec/common/inc/macros.h
+++ b/codec/common/inc/macros.h
@@ -44,6 +44,7 @@
#include <assert.h>
#include "typedefs.h"
+
/*
* ENFORCE_STACK_ALIGN_1D: force 1 dimension local data aligned in stack
* _tp: type
@@ -124,6 +125,14 @@
#ifndef WELS_ROUND
#define WELS_ROUND(x) ((int32_t)(0.5+(x)))
#endif//WELS_ROUND
+
+#ifndef WELS_DIV_ROUND
+#define WELS_DIV_ROUND(x,y) ((int32_t)((y)==0?((x)/((y)+1)):(((y)/2+(x))/(y))))
+#endif//WELS_DIV_ROUND
+
+#ifndef WELS_DIV_ROUND64
+#define WELS_DIV_ROUND64(x,y) ((int64_t)((y)==0?((x)/((y)+1)):(((y)/2+(x))/(y))))
+#endif//WELS_DIV_ROUND64
#define WELS_NON_ZERO_COUNT_AVERAGE(nC,nA,nB) { \
nC = nA + nB + 1; \
--- a/codec/encoder/core/inc/mt_defs.h
+++ b/codec/encoder/core/inc/mt_defs.h
@@ -85,7 +85,7 @@
WELS_MUTEX mutexSliceNumUpdate; // for dynamic slicing mode MT
uint32_t* pSliceConsumeTime[MAX_DEPENDENCY_LAYER]; // consuming time for each slice, [iSpatialIdx][uiSliceIdx]
- float* pSliceComplexRatio[MAX_DEPENDENCY_LAYER];
+ int32_t* pSliceComplexRatio[MAX_DEPENDENCY_LAYER]; // *INT_MULTIPLY
#ifdef MT_DEBUG
FILE* pFSliceDiff; // file handle for debug
--- a/codec/encoder/core/inc/rc.h
+++ b/codec/encoder/core/inc/rc.h
@@ -107,18 +107,21 @@
//bits allocation
#define MAX_BITS_VARY_PERCENTAGE 100 //bits vary range in percentage
+#define INT_MULTIPLY 100 // use to multiply in Double to Int Conversion, should be same as AQ_QSTEP_INT_MULTIPLY in WelsVP
+#define WEIGHT_MULTIPLY 2000
+#define REMAIN_BITS_TH (10) // *INT_MULTIPLY
#define VGOP_BITS_PERCENTAGE_DIFF 5
-#define IDR_BITRATE_RATIO 4.0
-#define FRAME_iTargetBits_VARY_RANGE 0.5
+#define IDR_BITRATE_RATIO 4
+#define FRAME_iTargetBits_VARY_RANGE 50 // *INT_MULTIPLY
//R-Q Model
-#define LINEAR_MODEL_DECAY_FACTOR 0.8
-#define FRAME_CMPLX_RATIO_RANGE 0.1
-#define SMOOTH_FACTOR_MIN_VALUE 0.02
+#define LINEAR_MODEL_DECAY_FACTOR 80 // *INT_MULTIPLY
+#define FRAME_CMPLX_RATIO_RANGE 10 // *INT_MULTIPLY
+#define SMOOTH_FACTOR_MIN_VALUE 2 // *INT_MULTIPLY
//#define VGOP_BITS_MIN_RATIO 0.8
//skip and padding
-#define SKIP_RATIO 0.5
-#define PADDING_BUFFER_RATIO 0.5
-#define PADDING_THRESHOLD 0.05
+#define SKIP_RATIO 50 // *INT_MULTIPLY
+#define PADDING_BUFFER_RATIO 50 // *INT_MULTIPLY
+#define PADDING_THRESHOLD 5 //*INT_MULTIPLY
typedef struct TagRCSlicing {
int32_t iComplexityIndexSlice;
@@ -138,10 +141,10 @@
typedef struct TagRCTemporal {
int32_t iMinBitsTl;
int32_t iMaxBitsTl;
- double dTlayerWeight;
+ int32_t iTlayerWeight;
int32_t iGopBitsDq;
//P frame level R-Q Model
- double dLinearCmplx;
+ int64_t iLinearCmplx; // *INT_MULTIPLY
int32_t iPFrameNum;
int32_t iFrameCmplxMean;
@@ -149,7 +152,7 @@
typedef struct TagWelsRc {
int32_t iRcVaryPercentage;
- double dRcVaryRatio;
+ int32_t iRcVaryRatio;
int32_t iInitialQp; //initial qp
int32_t iBitRate;
@@ -156,7 +159,7 @@
int32_t iPreviousBitrate;
int32_t iPreviousGopSize;
double fFrameRate;
- double dBitsPerFrame;
+ int32_t iBitsPerFrame; // *INT_MULTIPLY
double dPreviousFps;
// bits allocation and status
@@ -169,7 +172,7 @@
int32_t iIntraMbCount;
int8_t iTlOfFrames[VGOP_SIZE];
- double dRemainingWeights;
+ int32_t iRemainingWeights;
int32_t iFrameDqBits;
double* pGomComplexity;
@@ -195,9 +198,9 @@
int32_t iMinQp;
int32_t iMaxQp;
//int32_t delta_adaptive_qp;
- double dSkipBufferRatio;
+ int32_t iSkipBufferRatio;
- double dQStep;
+ int32_t iQStep; // *INT_MULTIPLY
int32_t iFrameDeltaQpUpper;
int32_t iFrameDeltaQpLower;
int32_t iLastCalculatedQScale;
--- a/codec/encoder/core/src/ratectl.cpp
+++ b/codec/encoder/core/src/ratectl.cpp
@@ -56,6 +56,12 @@
FILE* fp_vgop = NULL;
#endif
#define _BITS_RANGE 0
+const int32_t g_kiQpToQstepTable[52] = { 63, 71, 79, 89, 100, 112, 126, 141, 159, 178,
+ 200, 224, 252, 283, 317, 356, 400, 449, 504, 566,
+ 635, 713, 800, 898, 1008, 1131, 1270, 1425, 1600, 1796,
+ 2016, 2263, 2540, 2851, 3200, 3592, 4032, 4525, 5080, 5702,
+ 6400, 7184, 8063, 9051,10159,11404,12800,14368,16127,18102,
+ 20319,22807}; //WELS_ROUND(INT_MULTIPLY*pow (2.0, (iQP - 4.0) / 6.0))
void RcInitLayerMemory (SWelsSvcRc* pWelsSvcRc, CMemoryAlign* pMA, const int32_t kiMaxTl) {
const int32_t kiSliceNum = pWelsSvcRc->iSliceNum;
@@ -96,11 +102,11 @@
}
}
-static inline double RcConvertQp2QStep (double dQP) {
- return pow (2.0, (dQP - 4.0) / 6.0);
+static inline int32_t RcConvertQp2QStep (int32_t iQP) {
+ return g_kiQpToQstepTable[iQP];
}
-static inline double RcConvertQStep2Qp (double dQpStep) {
- return (6 * log (dQpStep) / log (2.0) + 4.0);
+static inline int32_t RcConvertQStep2Qp (int32_t iQpStep) {
+ return WELS_ROUND((6 * log (iQpStep*1.0f/INT_MULTIPLY) / log (2.0) + 4.0));
}
void RcInitSequenceParameter (sWelsEncCtx* pEncCtx) {
@@ -125,14 +131,14 @@
pWelsSvcRc->iSliceNum = pSliceCtx->iSliceNumInFrame;
pWelsSvcRc->iRcVaryPercentage = _BITS_RANGE; // % -- for temp
- pWelsSvcRc->dRcVaryRatio = (double)pWelsSvcRc->iRcVaryPercentage / MAX_BITS_VARY_PERCENTAGE;
+ pWelsSvcRc->iRcVaryRatio = pWelsSvcRc->iRcVaryPercentage;
- pWelsSvcRc->dSkipBufferRatio = SKIP_RATIO;
+ pWelsSvcRc->iSkipBufferRatio = SKIP_RATIO;
- pWelsSvcRc->iQpRangeUpperInFrame = QP_RANGE_UPPER_MODE1 - WELS_ROUND ((QP_RANGE_UPPER_MODE1 - QP_RANGE_MODE0) *
- pWelsSvcRc->dRcVaryRatio);
- pWelsSvcRc->iQpRangeLowerInFrame = QP_RANGE_LOWER_MODE1 - WELS_ROUND ((QP_RANGE_LOWER_MODE1 - QP_RANGE_MODE0) *
- pWelsSvcRc->dRcVaryRatio);
+ pWelsSvcRc->iQpRangeUpperInFrame = (QP_RANGE_UPPER_MODE1 * MAX_BITS_VARY_PERCENTAGE - ((QP_RANGE_UPPER_MODE1 - QP_RANGE_MODE0) *
+ pWelsSvcRc->iRcVaryRatio)) / MAX_BITS_VARY_PERCENTAGE;
+ pWelsSvcRc->iQpRangeLowerInFrame = (QP_RANGE_LOWER_MODE1 * MAX_BITS_VARY_PERCENTAGE - ((QP_RANGE_LOWER_MODE1 - QP_RANGE_MODE0) *
+ pWelsSvcRc->iRcVaryRatio)) / MAX_BITS_VARY_PERCENTAGE;
if (iMbWidth <= MB_WIDTH_THRESHOLD_90P) {
pWelsSvcRc->iSkipQpValue = SKIP_QP_90P;
@@ -151,7 +157,7 @@
iGomRowMode0 = GOM_ROW_MODE0_720P;
iGomRowMode1 = GOM_ROW_MODE1_720P;
}
- iGomRowMode0 = iGomRowMode1 + WELS_ROUND ((iGomRowMode0 - iGomRowMode1) * pWelsSvcRc->dRcVaryRatio);
+ iGomRowMode0 = iGomRowMode1 + ((iGomRowMode0 - iGomRowMode1) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE);
pWelsSvcRc->iNumberMbGom = iMbWidth * iGomRowMode0;
@@ -158,10 +164,10 @@
pWelsSvcRc->iMinQp = GOM_MIN_QP_MODE;
pWelsSvcRc->iMaxQp = GOM_MAX_QP_MODE;
- pWelsSvcRc->iFrameDeltaQpUpper = LAST_FRAME_QP_RANGE_UPPER_MODE1 - WELS_ROUND ((LAST_FRAME_QP_RANGE_UPPER_MODE1 -
- LAST_FRAME_QP_RANGE_UPPER_MODE0) * pWelsSvcRc->dRcVaryRatio);
- pWelsSvcRc->iFrameDeltaQpLower = LAST_FRAME_QP_RANGE_LOWER_MODE1 - WELS_ROUND ((LAST_FRAME_QP_RANGE_LOWER_MODE1 -
- LAST_FRAME_QP_RANGE_LOWER_MODE0) * pWelsSvcRc->dRcVaryRatio);
+ pWelsSvcRc->iFrameDeltaQpUpper = LAST_FRAME_QP_RANGE_UPPER_MODE1 - ((LAST_FRAME_QP_RANGE_UPPER_MODE1 -
+ LAST_FRAME_QP_RANGE_UPPER_MODE0) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE);
+ pWelsSvcRc->iFrameDeltaQpLower = LAST_FRAME_QP_RANGE_LOWER_MODE1 - ((LAST_FRAME_QP_RANGE_LOWER_MODE1 -
+ LAST_FRAME_QP_RANGE_LOWER_MODE0) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE);
pWelsSvcRc->iSkipFrameNum = 0;
pWelsSvcRc->iGomSize = (pWelsSvcRc->iNumberMbFrame + pWelsSvcRc->iNumberMbGom - 1) / pWelsSvcRc->iNumberMbGom;
@@ -186,13 +192,14 @@
const int32_t kiHighestTid = pDLayerParam->iHighestTemporalId;
//Index 0:Virtual GOP size, Index 1:Frame rate
- double WeightArray[4][4] = { {1.0, 0, 0, 0}, {0.6, 0.4, 0, 0}, {0.4, 0.3, 0.15, 0}, {0.25, 0.15, 0.125, 0.0875}};
+ //double WeightArray[4][4] = { {1.0, 0, 0, 0}, {0.6, 0.4, 0, 0}, {0.4, 0.3, 0.15, 0}, {0.25, 0.15, 0.125, 0.0875}};
+ int32_t iWeightArray[4][4] = { {2000, 0, 0, 0}, {1200, 800, 0, 0}, {800, 600, 300, 0}, {500, 300, 250, 175}}; // original*WEIGHT_MULTIPLY
const int32_t kiGopSize = (1 << kiDecompositionStages);
int32_t i, k, n;
n = 0;
while (n <= kiHighestTid) {
- pTOverRc[n].dTlayerWeight = WeightArray[kiDecompositionStages][n];
+ pTOverRc[n].iTlayerWeight = iWeightArray[kiDecompositionStages][n];
++ n;
}
//Calculate the frame index for the current frame and its reference frame
@@ -214,30 +221,30 @@
SDLayerParam* pDLayerParam = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
const int32_t kiGopSize = (1 << pDLayerParam->iDecompositionStages);
const int32_t kiHighestTid = pDLayerParam->iHighestTemporalId;
- double input_dBitsPerFrame = pDLayerParam->iSpatialBitrate / pDLayerParam->fInputFrameRate;
- const int32_t kiGopBits = WELS_ROUND (input_dBitsPerFrame * kiGopSize);
+ int32_t input_iBitsPerFrame = WELS_ROUND(pDLayerParam->iSpatialBitrate * INT_MULTIPLY / pDLayerParam->fInputFrameRate);
+ const int32_t kiGopBits = WELS_DIV_ROUND(input_iBitsPerFrame * kiGopSize, INT_MULTIPLY);
int32_t i;
pWelsSvcRc->iBitRate = pDLayerParam->iSpatialBitrate;
pWelsSvcRc->fFrameRate = pDLayerParam->fInputFrameRate;
- double dTargetVaryRange = FRAME_iTargetBits_VARY_RANGE * (1.0 - pWelsSvcRc->dRcVaryRatio);
- double dMinBitsRatio = 1.0 - dTargetVaryRange;
- double dMaxBitsRatio = 1.0 + FRAME_iTargetBits_VARY_RANGE;//dTargetVaryRange;
+ int32_t iTargetVaryRange = FRAME_iTargetBits_VARY_RANGE * (MAX_BITS_VARY_PERCENTAGE - pWelsSvcRc->iRcVaryRatio);
+ int32_t iMinBitsRatio = (MAX_BITS_VARY_PERCENTAGE) * INT_MULTIPLY - iTargetVaryRange;
+ int32_t iMaxBitsRatio = (MAX_BITS_VARY_PERCENTAGE) * (INT_MULTIPLY + FRAME_iTargetBits_VARY_RANGE);
for (i = 0; i <= kiHighestTid; i++) {
- const double kdConstraitBits = kiGopBits * pTOverRc[i].dTlayerWeight;
- pTOverRc[i].iMinBitsTl = WELS_ROUND (kdConstraitBits * dMinBitsRatio);
- pTOverRc[i].iMaxBitsTl = WELS_ROUND (kdConstraitBits * dMaxBitsRatio);
+ const int64_t kdConstraitBits = kiGopBits * pTOverRc[i].iTlayerWeight;
+ pTOverRc[i].iMinBitsTl = WELS_DIV_ROUND(kdConstraitBits * iMinBitsRatio, INT_MULTIPLY * MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY);
+ pTOverRc[i].iMaxBitsTl = WELS_DIV_ROUND(kdConstraitBits * iMaxBitsRatio, INT_MULTIPLY * MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY);
}
//When bitrate is changed, pBuffer size should be updated
- pWelsSvcRc->iBufferSizeSkip = WELS_ROUND (pWelsSvcRc->iBitRate * pWelsSvcRc->dSkipBufferRatio);
- pWelsSvcRc->iBufferSizePadding = WELS_ROUND (pWelsSvcRc->iBitRate * PADDING_BUFFER_RATIO);
+ pWelsSvcRc->iBufferSizeSkip = WELS_DIV_ROUND(pWelsSvcRc->iBitRate * pWelsSvcRc->iSkipBufferRatio, INT_MULTIPLY);
+ pWelsSvcRc->iBufferSizePadding = WELS_DIV_ROUND(pWelsSvcRc->iBitRate * PADDING_BUFFER_RATIO, INT_MULTIPLY);
//change remaining bits
- if (pWelsSvcRc->dBitsPerFrame > 0.1)
- pWelsSvcRc->iRemainingBits = WELS_ROUND (pWelsSvcRc->iRemainingBits * input_dBitsPerFrame / pWelsSvcRc->dBitsPerFrame);
- pWelsSvcRc->dBitsPerFrame = input_dBitsPerFrame;
+ if (pWelsSvcRc->iBitsPerFrame > REMAIN_BITS_TH)
+ pWelsSvcRc->iRemainingBits = pWelsSvcRc->iRemainingBits * input_iBitsPerFrame / pWelsSvcRc->iBitsPerFrame;
+ pWelsSvcRc->iBitsPerFrame = input_iBitsPerFrame;
}
@@ -247,8 +254,8 @@
SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc;
const int32_t kiHighestTid = pEncCtx->pSvcParam->sDependencyLayers[kiDid].iHighestTemporalId;
- pWelsSvcRc->iRemainingBits = WELS_ROUND (VGOP_SIZE * pWelsSvcRc->dBitsPerFrame);
- pWelsSvcRc->dRemainingWeights = pWelsSvcRc->iGopNumberInVGop;
+ pWelsSvcRc->iRemainingBits = WELS_DIV_ROUND(VGOP_SIZE * pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
+ pWelsSvcRc->iRemainingWeights = pWelsSvcRc->iGopNumberInVGop * WEIGHT_MULTIPLY;
pWelsSvcRc->iFrameCodedInVGop = 0;
pWelsSvcRc->iGopIndexInVGop = 0;
@@ -273,7 +280,7 @@
//P frame R-Q Model
for (i = 0; i <= kiHighestTid; i++) {
pTOverRc[i].iPFrameNum = 0;
- pTOverRc[i].dLinearCmplx = 0.0;
+ pTOverRc[i].iLinearCmplx = 0;
pTOverRc[i].iFrameCmplxMean = 0;
}
@@ -282,7 +289,7 @@
pWelsSvcRc->iGopIndexInVGop = 0;
pWelsSvcRc->iRemainingBits = 0;
- pWelsSvcRc->dBitsPerFrame = 0.0;
+ pWelsSvcRc->iBitsPerFrame = 0;
//Backup the initial bitrate and fps
pWelsSvcRc->iPreviousBitrate = pDLayerParam->iSpatialBitrate;
@@ -404,7 +411,7 @@
pWelsSvcRc->iInitialQp = dInitialQPArray[iBppIndex][i];
pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP);
pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp;
- pWelsSvcRc->dQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);
+ pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);
pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp;
}
@@ -412,14 +419,14 @@
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
//obtain the idr qp using previous idr complexity
if (pWelsSvcRc->iNumberMbFrame != pWelsSvcRc->iIntraMbCount) {
- pWelsSvcRc->iIntraComplexity = WELS_ROUND ((double)pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame /
- pWelsSvcRc->iIntraMbCount);
+ pWelsSvcRc->iIntraComplexity = pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame /
+ pWelsSvcRc->iIntraMbCount;
}
- pWelsSvcRc->iInitialQp = WELS_ROUND (RcConvertQStep2Qp ((double)pWelsSvcRc->iIntraComplexity /
- pWelsSvcRc->iTargetBits));
+ pWelsSvcRc->iInitialQp = RcConvertQStep2Qp (pWelsSvcRc->iIntraComplexity /
+ pWelsSvcRc->iTargetBits);
pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP);
pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp;
- pWelsSvcRc->dQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);
+ pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);
pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp;
}
@@ -450,11 +457,11 @@
pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal);
iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, MAX_LOW_BR_QP);
- pWelsSvcRc->dQStep = RcConvertQp2QStep (iLumaQp);
+ pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp);
pWelsSvcRc->iLastCalculatedQScale = iLumaQp;
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {
- iLumaQp = WELS_ROUND (iLumaQp - pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp);
+ iLumaQp = WELS_CLIP3 ((iLumaQp*INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp)/INT_MULTIPLY, GOM_MIN_QP_MODE, MAX_LOW_BR_QP);
}
pEncCtx->iGlobalQp = iLumaQp;
@@ -461,11 +468,11 @@
return;
} else {
- double dCmplxRatio = (double)pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity / pTOverRc->iFrameCmplxMean;
- dCmplxRatio = WELS_CLIP3 (dCmplxRatio, 1.0 - FRAME_CMPLX_RATIO_RANGE, 1.0 + FRAME_CMPLX_RATIO_RANGE);
+ int64_t iCmplxRatio = WELS_DIV_ROUND64(pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity *INT_MULTIPLY, pTOverRc->iFrameCmplxMean);
+ iCmplxRatio = WELS_CLIP3 (iCmplxRatio, INT_MULTIPLY - FRAME_CMPLX_RATIO_RANGE, INT_MULTIPLY + FRAME_CMPLX_RATIO_RANGE);
- pWelsSvcRc->dQStep = pTOverRc->dLinearCmplx * dCmplxRatio / pWelsSvcRc->iTargetBits;
- iLumaQp = WELS_ROUND (RcConvertQStep2Qp (pWelsSvcRc->dQStep));
+ pWelsSvcRc->iQStep = WELS_DIV_ROUND((pTOverRc->iLinearCmplx * iCmplxRatio), (pWelsSvcRc->iTargetBits * INT_MULTIPLY));
+ iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep);
//limit QP
int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1;
@@ -485,12 +492,12 @@
iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, GOM_MAX_QP_MODE);
- pWelsSvcRc->dQStep = RcConvertQp2QStep (iLumaQp);
+ pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp);
pWelsSvcRc->iLastCalculatedQScale = iLumaQp;
#ifndef _NOT_USE_AQ_FOR_TEST_
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {
- iLumaQp = WELS_ROUND (iLumaQp - pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp);
+ iLumaQp = WELS_DIV_ROUND(iLumaQp*INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp,INT_MULTIPLY);
if (pEncCtx->pSvcParam->iRCMode != RC_LOW_BW_MODE)
iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp);
@@ -505,7 +512,7 @@
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[0];
const int32_t kiSliceNum = pCurSliceCtx->iSliceNumInFrame;
- const double kdBitsPerMb = (double)pWelsSvcRc->iTargetBits / pWelsSvcRc->iNumberMbFrame;
+ const int32_t kdBitsPerMb = WELS_DIV_ROUND(pWelsSvcRc->iTargetBits * INT_MULTIPLY, pWelsSvcRc->iNumberMbFrame);
for (int32_t i = 0; i < kiSliceNum; i++) {
pSOverRc->iStartMbSlice =
@@ -513,7 +520,7 @@
pSOverRc->iEndMbSlice += (pCurSliceCtx->pCountMbNumInSlice[i] - 1);
pSOverRc->iTotalQpSlice = 0;
pSOverRc->iTotalMbSlice = 0;
- pSOverRc->iTargetBitsSlice = WELS_ROUND (kdBitsPerMb * pCurSliceCtx->pCountMbNumInSlice[i]);
+ pSOverRc->iTargetBitsSlice = WELS_DIV_ROUND(kdBitsPerMb * pCurSliceCtx->pCountMbNumInSlice[i], INT_MULTIPLY);
pSOverRc->iFrameBitsSlice = 0;
pSOverRc->iGomBitsSlice = 0;
++ pSOverRc;
@@ -527,10 +534,10 @@
pWelsSvcRc->iCurrentBitsLevel = BITS_NORMAL;
//allocate bits
if (pEncCtx->eSliceType == I_SLICE) {
- pWelsSvcRc->iTargetBits = WELS_ROUND (pWelsSvcRc->dBitsPerFrame * IDR_BITRATE_RATIO);
+ pWelsSvcRc->iTargetBits = WELS_DIV_ROUND(pWelsSvcRc->iBitsPerFrame * IDR_BITRATE_RATIO, INT_MULTIPLY);
} else {
- pWelsSvcRc->iTargetBits = WELS_ROUND (pWelsSvcRc->iRemainingBits * pTOverRc->dTlayerWeight /
- pWelsSvcRc->dRemainingWeights);
+ pWelsSvcRc->iTargetBits = (pWelsSvcRc->iRemainingBits * pTOverRc->iTlayerWeight /
+ pWelsSvcRc->iRemainingWeights);
if ((pWelsSvcRc->iTargetBits <= 0) && (pEncCtx->pSvcParam->iRCMode == RC_LOW_BW_MODE)) {
pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED;
} else if ((pWelsSvcRc->iTargetBits <= pTOverRc->iMinBitsTl) && (pEncCtx->pSvcParam->iRCMode == RC_LOW_BW_MODE)) {
@@ -538,7 +545,7 @@
}
pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl);
}
- pWelsSvcRc->dRemainingWeights -= pTOverRc->dTlayerWeight;
+ pWelsSvcRc->iRemainingWeights -= pTOverRc->iTlayerWeight;
}
@@ -602,7 +609,7 @@
SWelsSvcRc* pWelsSvcRc_Base = NULL;
SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[kiSliceId];
- double dAllocateBits = 0;
+ int32_t iAllocateBits = 0;
int32_t iSumSad = 0;
int32_t iLastGomIndex = 0;
int32_t iLeftBits = 0;
@@ -616,7 +623,7 @@
pSOverRc->iGomTargetBits = 0;
return;
} else if (kiComplexityIndex >= iLastGomIndex) {
- dAllocateBits = iLeftBits;
+ iAllocateBits = iLeftBits;
} else {
pWelsSvcRc_Base = RcJudgeBaseUsability (pEncCtx);
pWelsSvcRc_Base = (pWelsSvcRc_Base) ? pWelsSvcRc_Base : pWelsSvcRc;
@@ -624,12 +631,12 @@
iSumSad += pWelsSvcRc_Base->pCurrentFrameGomSad[i];
}
if (0 == iSumSad)
- dAllocateBits = (double)iLeftBits / (iLastGomIndex - kiComplexityIndex);
+ iAllocateBits = WELS_DIV_ROUND(iLeftBits, (iLastGomIndex - kiComplexityIndex));
else
- dAllocateBits = (double)iLeftBits * pWelsSvcRc_Base->pCurrentFrameGomSad[kiComplexityIndex + 1] / iSumSad;
+ iAllocateBits = WELS_DIV_ROUND(iLeftBits * pWelsSvcRc_Base->pCurrentFrameGomSad[kiComplexityIndex + 1], iSumSad);
}
- pSOverRc->iGomTargetBits = WELS_ROUND (dAllocateBits);
+ pSOverRc->iGomTargetBits = iAllocateBits;
}
@@ -637,7 +644,7 @@
void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) {
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[iSliceId];
- double dBitsRatio = 1.0;
+ int32_t iBitsRatio = 1;
int32_t iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice;
int32_t iTargetLeftBits = iLeftBits + pSOverRc->iGomBitsSlice - pSOverRc->iGomTargetBits;
@@ -646,14 +653,14 @@
pSOverRc->iCalculatedQpSlice += 2;
} else {
//globe decision
- dBitsRatio = iLeftBits / (iTargetLeftBits + 0.1);
- if (dBitsRatio < 0.8409) //2^(-1.5/6)
+ iBitsRatio = 10000 * iLeftBits / (iTargetLeftBits+1);
+ if (iBitsRatio < 8409) //2^(-1.5/6)*10000
pSOverRc->iCalculatedQpSlice += 2;
- else if (dBitsRatio < 0.9439) //2^(-0.5/6)
+ else if (iBitsRatio < 9439) //2^(-0.5/6)*10000
pSOverRc->iCalculatedQpSlice += 1;
- else if (dBitsRatio > 1.06) //2^(0.5/6)
+ else if (iBitsRatio > 10600) //2^(0.5/6)*10000
pSOverRc->iCalculatedQpSlice -= 1;
- else if (dBitsRatio > 1.19) //2^(1.5/6)
+ else if (iBitsRatio > 11900) //2^(1.5/6)*10000
pSOverRc->iCalculatedQpSlice -= 2;
}
@@ -669,11 +676,11 @@
void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) {
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc;
- const int32_t kiOutputBits = WELS_ROUND (pWelsSvcRc->dBitsPerFrame);
+ const int32_t kiOutputBits = WELS_DIV_ROUND(pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
//condition 1: whole pBuffer fullness
pWelsSvcRc->iBufferFullnessSkip += (pWelsSvcRc->iFrameDqBits - kiOutputBits);
//condition 2: VGOP bits constraint
- const int32_t kiVGopBits = WELS_ROUND (pWelsSvcRc->dBitsPerFrame * VGOP_SIZE);
+ const int32_t kiVGopBits = WELS_DIV_ROUND(pWelsSvcRc->iBitsPerFrame * VGOP_SIZE, INT_MULTIPLY);
int32_t iVGopBitsPred = 0;
for (int32_t i = pWelsSvcRc->iFrameCodedInVGop + 1; i < VGOP_SIZE; i++)
iVGopBitsPred += pTOverRc[pWelsSvcRc->iTlOfFrames[i]].iMinBitsTl;
@@ -694,7 +701,7 @@
pWelsSvcRc->iBufferFullnessSkip = 0;
if (pEncCtx->iSkipFrameFlag == 1) {
- pWelsSvcRc->iRemainingBits += WELS_ROUND (pWelsSvcRc->dBitsPerFrame);
+ pWelsSvcRc->iRemainingBits += WELS_DIV_ROUND(pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
pWelsSvcRc->iSkipFrameNum++;
pWelsSvcRc->iSkipFrameInVGop++;
}
@@ -702,8 +709,8 @@
void RcVBufferCalculationPadding (sWelsEncCtx* pEncCtx) {
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
- const int32_t kiOutputBits = WELS_ROUND (pWelsSvcRc->dBitsPerFrame);
- const int32_t kiBufferThreshold = WELS_ROUND (PADDING_THRESHOLD * (-pWelsSvcRc->iBufferSizePadding));
+ const int32_t kiOutputBits = WELS_DIV_ROUND(pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
+ const int32_t kiBufferThreshold = WELS_DIV_ROUND(PADDING_THRESHOLD * (-pWelsSvcRc->iBufferSizePadding), INT_MULTIPLY);
pWelsSvcRc->iBufferFullnessPadding += (pWelsSvcRc->iFrameDqBits - kiOutputBits);
@@ -740,7 +747,7 @@
++ pSOverRc;
}
if (iTotalMb > 0)
- pWelsSvcRc->iAverageFrameQp = WELS_ROUND (1.0 * iTotalQp / iTotalMb);
+ pWelsSvcRc->iAverageFrameQp = WELS_DIV_ROUND(INT_MULTIPLY * iTotalQp, iTotalMb * INT_MULTIPLY);
else
pWelsSvcRc->iAverageFrameQp = pEncCtx->iGlobalQp;
} else {
@@ -752,12 +759,11 @@
void RcUpdateIntraComplexity (sWelsEncCtx* pEncCtx) {
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
- double iAlpha = 1.0 / (1 + pWelsSvcRc->iIdrNum);
- if (iAlpha < 0.25) iAlpha = 0.25;
+ int32_t iAlpha = WELS_DIV_ROUND(INT_MULTIPLY, (1 + pWelsSvcRc->iIdrNum));
+ if (iAlpha < (INT_MULTIPLY/4)) iAlpha = INT_MULTIPLY/4;
- double dIntraCmplx = pWelsSvcRc->dQStep * pWelsSvcRc->iFrameDqBits;
- dIntraCmplx = (1.0 - iAlpha) * pWelsSvcRc->iIntraComplexity + iAlpha * dIntraCmplx;
- pWelsSvcRc->iIntraComplexity = WELS_ROUND (dIntraCmplx);
+ int64_t iIntraCmplx = pWelsSvcRc->iQStep * pWelsSvcRc->iFrameDqBits;
+ pWelsSvcRc->iIntraComplexity = WELS_DIV_ROUND(((INT_MULTIPLY - iAlpha) * pWelsSvcRc->iIntraComplexity + iAlpha * iIntraCmplx), INT_MULTIPLY);
pWelsSvcRc->iIntraMbCount = pWelsSvcRc->iNumberMbFrame;
pWelsSvcRc->iIdrNum++;
@@ -771,16 +777,16 @@
SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[kiTl];
if (0 == pTOverRc->iPFrameNum) {
- pTOverRc->dLinearCmplx = pWelsSvcRc->iFrameDqBits * pWelsSvcRc->dQStep;
+ pTOverRc->iLinearCmplx = ((int64_t)pWelsSvcRc->iFrameDqBits) * pWelsSvcRc->iQStep;
} else {
- pTOverRc->dLinearCmplx = LINEAR_MODEL_DECAY_FACTOR * pTOverRc->dLinearCmplx
- + (1.0 - LINEAR_MODEL_DECAY_FACTOR) * (pWelsSvcRc->iFrameDqBits * pWelsSvcRc->dQStep);
+ pTOverRc->iLinearCmplx = WELS_DIV_ROUND64((LINEAR_MODEL_DECAY_FACTOR * pTOverRc->iLinearCmplx
+ + (INT_MULTIPLY - LINEAR_MODEL_DECAY_FACTOR) * (pWelsSvcRc->iFrameDqBits * pWelsSvcRc->iQStep)), INT_MULTIPLY);
}
- double iAlpha = 1.0 / (1 + pTOverRc->iPFrameNum);
+ int32_t iAlpha = WELS_DIV_ROUND(INT_MULTIPLY, (1 + pTOverRc->iPFrameNum));
if (iAlpha < SMOOTH_FACTOR_MIN_VALUE)
iAlpha = SMOOTH_FACTOR_MIN_VALUE;
- pTOverRc->iFrameCmplxMean = WELS_ROUND ((1.0 - iAlpha) * pTOverRc->iFrameCmplxMean + iAlpha *
- pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity);
+ pTOverRc->iFrameCmplxMean = WELS_DIV_ROUND(((INT_MULTIPLY - iAlpha) * pTOverRc->iFrameCmplxMean + iAlpha *
+ pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity), INT_MULTIPLY);
pTOverRc->iPFrameNum++;
if (pTOverRc->iPFrameNum > 255)
@@ -925,8 +931,8 @@
pEncCtx->iGlobalQp = RcCalculateCascadingQp (pEncCtx, kiQp);
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant && (pEncCtx->eSliceType == P_SLICE)) {
- pEncCtx->iGlobalQp = WELS_CLIP3 (WELS_ROUND (pEncCtx->iGlobalQp -
- pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp), GOM_MIN_QP_MODE, GOM_MAX_QP_MODE);
+ pEncCtx->iGlobalQp = WELS_CLIP3 ( (pEncCtx->iGlobalQp *INT_MULTIPLY -
+ pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp)/INT_MULTIPLY, GOM_MIN_QP_MODE, GOM_MAX_QP_MODE);
} else {
pEncCtx->iGlobalQp = WELS_CLIP3 (pEncCtx->iGlobalQp, 0, 51);
}
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -120,9 +120,9 @@
}
void CalcSliceComplexRatio (void* pRatio, SSliceCtx* pSliceCtx, uint32_t* pSliceConsume) {
- float* pRatioList = (float*)pRatio;
- float fAvI[MAX_SLICES_NUM];
- float fSumAv = .0f;
+ int32_t* pRatioList = (int32_t*)pRatio;
+ int32_t iAvI[MAX_SLICES_NUM];
+ int32_t iSumAv = 0;
uint32_t* pSliceTime = (uint32_t*)pSliceConsume;
int32_t* pCountMbInSlice = (int32_t*)pSliceCtx->pCountMbNumInSlice;
const int32_t kiSliceCount = pSliceCtx->iSliceNumInFrame;
@@ -131,16 +131,16 @@
WelsEmms();
while (iSliceIdx < kiSliceCount) {
- fAvI[iSliceIdx] = 1.0f * pCountMbInSlice[iSliceIdx] / pSliceTime[iSliceIdx];
+ iAvI[iSliceIdx] = WELS_DIV_ROUND(INT_MULTIPLY * pCountMbInSlice[iSliceIdx], pSliceTime[iSliceIdx]);
MT_TRACE_LOG (NULL, WELS_LOG_DEBUG, "[MT] CalcSliceComplexRatio(), pSliceConsumeTime[%d]= %d us, slice_run= %d\n",
iSliceIdx,
pSliceTime[iSliceIdx], pCountMbInSlice[iSliceIdx]);
- fSumAv += fAvI[iSliceIdx];
+ iSumAv += iAvI[iSliceIdx];
++ iSliceIdx;
}
while (-- iSliceIdx >= 0) {
- pRatioList[iSliceIdx] = fAvI[iSliceIdx] / fSumAv;
+ pRatioList[iSliceIdx] = WELS_DIV_ROUND(INT_MULTIPLY * iAvI[iSliceIdx], iSumAv);
}
}
@@ -200,7 +200,7 @@
const int32_t kiCountNumMb = pSliceCtx->iMbNumInFrame;
int32_t iMinimalMbNum = pSliceCtx->iMbWidth; // in theory we need only 1 SMB, here let it as one SMB row required
int32_t iMaximalMbNum = 0; // dynamically assign later
- float* pSliceComplexRatio = (float*)pComplexRatio;
+ int32_t* pSliceComplexRatio = (int32_t*)pComplexRatio;
int32_t iMbNumLeft = kiCountNumMb;
int32_t iRunLen[MAX_THREADS_NUM] = {0};
int32_t iSliceIdx = 0;
@@ -236,11 +236,11 @@
iSliceIdx = 0;
while (iSliceIdx + 1 < kiCountSliceNum) {
- int32_t iNumMbAssigning = WELS_ROUND (kiCountNumMb * pSliceComplexRatio[iSliceIdx]);
+ int32_t iNumMbAssigning = WELS_DIV_ROUND(kiCountNumMb * pSliceComplexRatio[iSliceIdx], INT_MULTIPLY);
// GOM boundary aligned
if (pCtx->pSvcParam->iRCMode != RC_OFF_MODE) {
- iNumMbAssigning = WELS_ROUND (1.0f * iNumMbAssigning / iNumMbInEachGom) * iNumMbInEachGom;
+ iNumMbAssigning = iNumMbAssigning / iNumMbInEachGom * iNumMbInEachGom;
}
// make sure one GOM at least in each pSlice for safe
@@ -259,7 +259,7 @@
iRunLen[iSliceIdx] = iNumMbAssigning;
MT_TRACE_LOG (pCtx, WELS_LOG_DEBUG,
"[MT] DynamicAdjustSlicing(), uiSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n",
- iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iNumMbAssigning);
+ iSliceIdx, pSliceComplexRatio[iSliceIdx]* 1.0f / INT_MULTIPLY, pSliceCtx->pCountMbNumInSlice[iSliceIdx], iNumMbAssigning);
++ iSliceIdx;
iMaximalMbNum = iMbNumLeft - (kiCountSliceNum - iSliceIdx - 1) * iMinimalMbNum; // get maximal num_mb in left parts
}
@@ -266,7 +266,7 @@
iRunLen[iSliceIdx] = iMbNumLeft;
MT_TRACE_LOG (pCtx, WELS_LOG_DEBUG,
"[MT] DynamicAdjustSlicing(), iSliceIdx= %d, pSliceComplexRatio= %.2f, slice_run_org= %d, slice_run_adj= %d\n",
- iSliceIdx, pSliceComplexRatio[iSliceIdx], pSliceCtx->pCountMbNumInSlice[iSliceIdx], iMbNumLeft);
+ iSliceIdx, pSliceComplexRatio[iSliceIdx]* 1.0f / INT_MULTIPLY, pSliceCtx->pCountMbNumInSlice[iSliceIdx], iMbNumLeft);
if (DynamicAdjustSlicePEncCtxAll (pSliceCtx, iRunLen) == 0) {
@@ -329,7 +329,7 @@
&& pPara->iMultipleThreadIdc >= kiSliceNum) {
pSmt->pSliceConsumeTime[iIdx] = (uint32_t*)pMa->WelsMallocz (kiSliceNum * sizeof (uint32_t), "pSliceConsumeTime[]");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pSliceConsumeTime[iIdx]), FreeMemorySvc (ppCtx))
- pSmt->pSliceComplexRatio[iIdx] = (float*)pMa->WelsMalloc (kiSliceNum * sizeof (float), "pSliceComplexRatio[]");
+ pSmt->pSliceComplexRatio[iIdx] = (int32_t*)pMa->WelsMalloc (kiSliceNum * sizeof (int32_t), "pSliceComplexRatio[]");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pSmt->pSliceComplexRatio[iIdx]), FreeMemorySvc (ppCtx))
} else {
pSmt->pSliceConsumeTime[iIdx] = NULL;
--- a/codec/encoder/core/src/svc_enc_slice_segment.cpp
+++ b/codec/encoder/core/src/svc_enc_slice_segment.cpp
@@ -276,7 +276,7 @@
while (uiSliceIdx + 1 < kuiSliceNum) {
// GOM boundary aligned
- int32_t iNumMbAssigning = WELS_ROUND (1.0f * kiMbNumPerSlice / iGomSize) * iGomSize;
+ int32_t iNumMbAssigning = WELS_DIV_ROUND(INT_MULTIPLY * kiMbNumPerSlice, iGomSize * INT_MULTIPLY) * iGomSize;
// make sure one GOM at least in each slice for safe
if (iNumMbAssigning < iMinimalMbNum)
--- a/codec/encoder/core/src/wels_preprocess.cpp
+++ b/codec/encoder/core/src/wels_preprocess.cpp
@@ -663,7 +663,7 @@
void CWelsPreProcess::AdaptiveQuantCalculation (SVAAFrameInfo* pVaaInfo, SPicture* pCurPicture, SPicture* pRefPicture) {
pVaaInfo->sAdaptiveQuantParam.pCalcResult = & (pVaaInfo->sVaaCalcInfo);
- pVaaInfo->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp = 0;
+ pVaaInfo->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp = 0;
{
int32_t iMethodIdx = METHOD_ADAPTIVE_QUANT;
--- a/codec/processing/interface/IWelsVP.h
+++ b/codec/processing/interface/IWelsVP.h
@@ -209,7 +209,7 @@
SMotionTextureUnit* pMotionTextureUnit;
signed char* pMotionTextureIndexToDeltaQp;
- double dAverMotionTextureIndexToDeltaQp;
+ int iAverMotionTextureIndexToDeltaQp; // *AQ_STEP_INT_MULTIPLY
} SAdaptiveQuantizationParam;
typedef enum {
--- a/codec/processing/src/adaptivequantization/AdaptiveQuantization.cpp
+++ b/codec/processing/src/adaptivequantization/AdaptiveQuantization.cpp
@@ -30,16 +30,16 @@
*
*/
#include "AdaptiveQuantization.h"
-
+#include "macros.h"
WELSVP_NAMESPACE_BEGIN
-#define AVERAGE_TIME_MOTION (0.3) //0.3046875 // 1/4 + 1/16 - 1/128 ~ 0.3
-#define AVERAGE_TIME_TEXTURE_QUALITYMODE (1.0) //0.5 // 1/2
-#define AVERAGE_TIME_TEXTURE_BITRATEMODE (0.875) //0.5 // 1/2
-#define MODEL_ALPHA (0.9910) //1.5 //1.1102
-#define MODEL_TIME (5.8185) //9.0 //5.9842
+#define AVERAGE_TIME_MOTION (3000) //0.3046875 // 1/4 + 1/16 - 1/128 ~ 0.3 *AQ_TIME_INT_MULTIPLY
+#define AVERAGE_TIME_TEXTURE_QUALITYMODE (10000) //0.5 // 1/2 *AQ_TIME_INT_MULTIPLY
+#define AVERAGE_TIME_TEXTURE_BITRATEMODE (8750) //0.5 // 1/2 *AQ_TIME_INT_MULTIPLY
+#define MODEL_ALPHA (9910) //1.5 //1.1102 *AQ_TIME_INT_MULTIPLY
+#define MODEL_TIME (58185) //9.0 //5.9842 *AQ_TIME_INT_MULTIPLY
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -65,14 +65,14 @@
SMotionTextureUnit* pMotionTexture = NULL;
SVAACalcResult* pVaaCalcResults = NULL;
- int8_t iMotionTextureIndexToDeltaQp = 0;
+ int32_t iMotionTextureIndexToDeltaQp = 0;
int32_t iAverMotionTextureIndexToDeltaQp = 0; // double to uint32
- double dAverageMotionIndex = 0.0; // double to float
- double dAverageTextureIndex = 0.0;
+ int64_t iAverageMotionIndex = 0; // double to float
+ int64_t iAverageTextureIndex = 0;
- double dQStep = 0.0;
- double dLumaMotionDeltaQp = 0;
- double dLumaTextureDeltaQp = 0;
+ int64_t iQStep = 0;
+ int64_t iLumaMotionDeltaQp = 0;
+ int64_t iLumaTextureDeltaQp = 0;
uint8_t* pRefFrameY = NULL, *pCurFrameY = NULL;
int32_t iRefStride = 0, iCurStride = 0;
@@ -88,8 +88,8 @@
/////////////////////////////////////// motion //////////////////////////////////
// motion MB residual variance
- dAverageMotionIndex = 0.0;
- dAverageTextureIndex = 0.0;
+ iAverageMotionIndex = 0;
+ iAverageTextureIndex = 0;
pMotionTexture = m_sAdaptiveQuantParam.pMotionTextureUnit;
pVaaCalcResults = m_sAdaptiveQuantParam.pCalcResult;
@@ -115,8 +115,8 @@
uiSum = uiSum >> 8;
pMotionTexture->uiTextureIndex = (iSQSum >> 8) - (uiSum * uiSum);
- dAverageMotionIndex += pMotionTexture->uiMotionIndex;
- dAverageTextureIndex += pMotionTexture->uiTextureIndex;
+ iAverageMotionIndex += pMotionTexture->uiMotionIndex;
+ iAverageTextureIndex += pMotionTexture->uiTextureIndex;
pMotionTexture++;
++iMbIndex;
pRefFrameTmp += MB_WIDTH_LUMA;
@@ -131,8 +131,8 @@
pCurFrameTmp = pCurFrameY;
for (i = 0; i < iMbWidth; i++) {
m_pfVar (pRefFrameTmp, iRefStride, pCurFrameTmp, iCurStride, pMotionTexture);
- dAverageMotionIndex += pMotionTexture->uiMotionIndex;
- dAverageTextureIndex += pMotionTexture->uiTextureIndex;
+ iAverageMotionIndex += pMotionTexture->uiMotionIndex;
+ iAverageTextureIndex += pMotionTexture->uiTextureIndex;
pMotionTexture++;
pRefFrameTmp += MB_WIDTH_LUMA;
pCurFrameTmp += MB_WIDTH_LUMA;
@@ -142,50 +142,52 @@
pCurFrameY += (iCurStride) << 4;
}
}
- dAverageMotionIndex = dAverageMotionIndex / iMbTotalNum;
- dAverageTextureIndex = dAverageTextureIndex / iMbTotalNum;
- if ((dAverageMotionIndex <= PESN) && (dAverageMotionIndex >= -PESN)) {
- dAverageMotionIndex = 1.0;
+ iAverageMotionIndex = WELS_DIV_ROUND64(iAverageMotionIndex * AQ_INT_MULTIPLY,iMbTotalNum);
+ iAverageTextureIndex = WELS_DIV_ROUND64(iAverageTextureIndex * AQ_INT_MULTIPLY, iMbTotalNum);
+ if ((iAverageMotionIndex <= AQ_PESN) && (iAverageMotionIndex >= -AQ_PESN)) {
+ iAverageMotionIndex = AQ_INT_MULTIPLY;
}
- if ((dAverageTextureIndex <= PESN) && (dAverageTextureIndex >= -PESN)) {
- dAverageTextureIndex = 1.0;
+ if ((iAverageTextureIndex <= AQ_PESN) && (iAverageTextureIndex >= -AQ_PESN)) {
+ iAverageTextureIndex = AQ_INT_MULTIPLY;
}
// motion mb residual map to QP
// texture mb original map to QP
iAverMotionTextureIndexToDeltaQp = 0;
- dAverageMotionIndex = AVERAGE_TIME_MOTION * dAverageMotionIndex;
+ iAverageMotionIndex = WELS_DIV_ROUND64(AVERAGE_TIME_MOTION * iAverageMotionIndex, AQ_TIME_INT_MULTIPLY);
if (m_sAdaptiveQuantParam.iAdaptiveQuantMode == AQ_QUALITY_MODE) {
- dAverageTextureIndex = AVERAGE_TIME_TEXTURE_QUALITYMODE * dAverageTextureIndex;
+ iAverageTextureIndex = WELS_DIV_ROUND64(AVERAGE_TIME_TEXTURE_QUALITYMODE * iAverageTextureIndex, AQ_TIME_INT_MULTIPLY);
} else {
- dAverageTextureIndex = AVERAGE_TIME_TEXTURE_BITRATEMODE * dAverageTextureIndex;
+ iAverageTextureIndex = WELS_DIV_ROUND64(AVERAGE_TIME_TEXTURE_BITRATEMODE * iAverageTextureIndex, AQ_TIME_INT_MULTIPLY);
}
+ int64_t iAQ_EPSN = -((int64_t)AQ_PESN*AQ_TIME_INT_MULTIPLY*AQ_QSTEP_INT_MULTIPLY/AQ_INT_MULTIPLY);
pMotionTexture = m_sAdaptiveQuantParam.pMotionTextureUnit;
for (j = 0; j < iMbHeight; j ++) {
for (i = 0; i < iMbWidth; i++) {
- double a = pMotionTexture->uiTextureIndex / dAverageTextureIndex;
- dQStep = (a - 1) / (a + MODEL_ALPHA);
- dLumaTextureDeltaQp = MODEL_TIME * dQStep;// range +- 6
+ int64_t a = WELS_DIV_ROUND64((int64_t)(pMotionTexture->uiTextureIndex) *AQ_INT_MULTIPLY * AQ_TIME_INT_MULTIPLY, iAverageTextureIndex);
+ iQStep = WELS_DIV_ROUND64((a - AQ_TIME_INT_MULTIPLY) * AQ_QSTEP_INT_MULTIPLY, (a + MODEL_ALPHA));
+ iLumaTextureDeltaQp = MODEL_TIME * iQStep;// range +- 6
- iMotionTextureIndexToDeltaQp = (int8_t)dLumaTextureDeltaQp;
+ iMotionTextureIndexToDeltaQp = ((int32_t)(iLumaTextureDeltaQp/(AQ_TIME_INT_MULTIPLY)));
- a = pMotionTexture->uiMotionIndex / dAverageMotionIndex;
- dQStep = (a - 1) / (a + MODEL_ALPHA);
- dLumaMotionDeltaQp = MODEL_TIME * dQStep;// range +- 6
+ a = WELS_DIV_ROUND64(((int64_t)pMotionTexture->uiMotionIndex)*AQ_INT_MULTIPLY * AQ_TIME_INT_MULTIPLY, iAverageMotionIndex);
+ iQStep = WELS_DIV_ROUND64((a - AQ_TIME_INT_MULTIPLY) * AQ_QSTEP_INT_MULTIPLY, (a + MODEL_ALPHA));
+ iLumaMotionDeltaQp = MODEL_TIME * iQStep;// range +- 6
- if ((m_sAdaptiveQuantParam.iAdaptiveQuantMode == AQ_QUALITY_MODE && dLumaMotionDeltaQp < -PESN)
+ if ((m_sAdaptiveQuantParam.iAdaptiveQuantMode == AQ_QUALITY_MODE && iLumaMotionDeltaQp < iAQ_EPSN)
|| (m_sAdaptiveQuantParam.iAdaptiveQuantMode == AQ_BITRATE_MODE)) {
- iMotionTextureIndexToDeltaQp += (int8_t)dLumaMotionDeltaQp;
+ iMotionTextureIndexToDeltaQp += ((int32_t)(iLumaMotionDeltaQp/(AQ_TIME_INT_MULTIPLY)));
}
- m_sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[j * iMbWidth + i] = iMotionTextureIndexToDeltaQp;
+ m_sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[j * iMbWidth + i] = (int8_t)(iMotionTextureIndexToDeltaQp/AQ_QSTEP_INT_MULTIPLY);
iAverMotionTextureIndexToDeltaQp += iMotionTextureIndexToDeltaQp;
pMotionTexture++;
}
}
- m_sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp = (1.0 * iAverMotionTextureIndexToDeltaQp) / iMbTotalNum;
+ m_sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp = iAverMotionTextureIndexToDeltaQp / iMbTotalNum;
+
eReturn = RET_SUCCESS;
return eReturn;
@@ -210,7 +212,7 @@
SAdaptiveQuantizationParam* sAdaptiveQuantParam = (SAdaptiveQuantizationParam*)pParam;
- sAdaptiveQuantParam->dAverMotionTextureIndexToDeltaQp = m_sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp;
+ sAdaptiveQuantParam->iAverMotionTextureIndexToDeltaQp = m_sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp;
return RET_SUCCESS;
}
--- a/codec/processing/src/common/util.h
+++ b/codec/processing/src/common/util.h
@@ -58,6 +58,10 @@
#define MAX_HEIGHT (2304)//MAX_FS_LEVEL51 (36864); MAX_FS_LEVEL51*256/4096 = 2304
#define MB_WIDTH_LUMA (16)
#define PESN (1e-6) // desired float precision
+#define AQ_INT_MULTIPLY 10000000
+#define AQ_TIME_INT_MULTIPLY 10000
+#define AQ_QSTEP_INT_MULTIPLY 100
+#define AQ_PESN 10 // (1e-6)*AQ_INT_MULTIPLY
#define MB_TYPE_INTRA4x4 0x00000001
#define MB_TYPE_INTRA16x16 0x00000002
--- a/test/api/decode_encode_test.cpp
+++ b/test/api/decode_encode_test.cpp
@@ -104,8 +104,8 @@
}
static const DecodeEncodeFileParam kFileParamArray[] = {
- {"res/test_vd_1d.264", "c73c1cc9b7dbab51f48cf41453073bb11337a445", 320, 192, 12.0f},
- {"res/test_vd_rc.264", "593ab31fdc67cbad7373abbf7d08daf2771fb229", 320, 192, 12.0f},
+ {"res/test_vd_1d.264", "16b6379ce3711c57ea966e8da3e6b9815bf5ef4e", 320, 192, 12.0f},
+ {"res/test_vd_rc.264", "03a93dbf5482b4a799d52d5fd373fde58a782e12", 320, 192, 12.0f},
};
INSTANTIATE_TEST_CASE_P(DecodeEncodeFile, DecodeEncodeTest,
--- a/test/api/encoder_test.cpp
+++ b/test/api/encoder_test.cpp
@@ -73,31 +73,31 @@
static const EncodeFileParam kFileParamArray[] = {
{
"res/CiscoVT2people_320x192_12fps.yuv",
- "5fa8c8551133b7d7586f498121028d0e05a28e1d", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, false, 1
+ "86ee1314eabf5a6d6083c5260d36e2d908f36ea5", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, false, 1
},
{
"res/CiscoVT2people_160x96_6fps.yuv",
- "c619645a7d46f8fade40d2b0e5ae01adc2e5c3ff", CAMERA_VIDEO_REAL_TIME, 160, 96, 6.0f, SM_SINGLE_SLICE, false, 1
+ "20f3e5cbefe70e5a8793e60672fd70e136bc082a", CAMERA_VIDEO_REAL_TIME, 160, 96, 6.0f, SM_SINGLE_SLICE, false, 1
},
{
"res/Static_152_100.yuv",
- "68cde1b5f790213baab1a10d4a19a3618c138405", CAMERA_VIDEO_REAL_TIME, 152, 100, 6.0f, SM_SINGLE_SLICE, false, 1
+ "035f2e5b35947ab43cad7c5ca4cd8a3b658306ba", CAMERA_VIDEO_REAL_TIME, 152, 100, 6.0f, SM_SINGLE_SLICE, false, 1
},
{
"res/CiscoVT2people_320x192_12fps.yuv",
- "d0d0a087451c2813e9b0fd61bc5b25a4e82519ac", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_ROWMB_SLICE, false, 1 // One slice per MB row
+ "c8b759bcec7ffa048f1d3ded594b8815bed0aead", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_ROWMB_SLICE, false, 1 // One slice per MB row
},
{
"res/CiscoVT2people_320x192_12fps.yuv",
- "d3760e61e38af978d5b59232d8402448812d1540", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, true, 1
+ "6f49cc4e746522d7d91599c9a883072e838ae918", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, true, 1
},
{
"res/CiscoVT2people_320x192_12fps.yuv",
- "a74ae382356098fb5cce216a97f2c0cef00a0a9d", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, false, 2
+ "4da4526a763497cfd777e1a211c67df5e9d48b29", CAMERA_VIDEO_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, false, 2
},
{
"res/Cisco_Absolute_Power_1280x720_30fps.yuv",
- "76b26c32dd3b400d3dccee0e8a52581f5c2588bb", CAMERA_VIDEO_REAL_TIME, 1280, 720, 30.0f, SM_DYN_SLICE, false, 1
+ "6df1ece77c0de63cdf8ab52ccef3a7d139022717", CAMERA_VIDEO_REAL_TIME, 1280, 720, 30.0f, SM_DYN_SLICE, false, 1
},
{
"res/CiscoVT2people_320x192_12fps.yuv",