[x265] [PATCH] rc: fix Rate Control for grainy content
Aarthi Priya Thirumalai
aarthi at multicorewareinc.com
Wed Jan 27 06:32:08 CET 2016
# HG changeset patch
# User Aarthi Thirumalai
# Date 1452501832 -19800
# Mon Jan 11 14:13:52 2016 +0530
# Node ID cee55e38a09310c1c3384ee72e548bd72a00a4e7
# Parent f548abe8eae8fb75513a85d1b09233e706c7b5ba
rc: fix Rate Control for grainy content
optimize params for tune grain, reduce frequent qp fluctions to prevent
grain loss
diff -r f548abe8eae8 -r cee55e38a093 source/common/param.cpp
--- a/source/common/param.cpp Wed Jan 20 18:27:42 2016 +0530
+++ b/source/common/param.cpp Mon Jan 11 14:13:52 2016 +0530
@@ -454,16 +454,11 @@
}
else if (!strcmp(tune, "grain"))
{
- param->deblockingFilterBetaOffset = -2;
- param->deblockingFilterTCOffset = -2;
- param->bIntraInBFrames = 0;
- param->rdoqLevel = 2;
- param->psyRdoq = 10.0;
- param->psyRd = 0.5;
param->rc.ipFactor = 1.1;
- param->rc.pbFactor = 1.1;
- param->rc.aqStrength = 0.3;
- param->rc.qCompress = 0.8;
+ param->rc.pbFactor = 1.0;
+ param->rc.cuTree = 0;
+ param->rc.aqMode = 0;
+ param->rc.qpStep = 1.0;
}
else
return -1;
diff -r f548abe8eae8 -r cee55e38a093 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Wed Jan 20 18:27:42 2016 +0530
+++ b/source/encoder/ratecontrol.cpp Mon Jan 11 14:13:52 2016 +0530
@@ -190,6 +190,8 @@
m_numEntries = 0;
m_isSceneTransition = false;
m_lastPredictorReset = 0;
+ m_avgPFrameQp = 0;
+ m_isFirstMiniGop = false;
if (m_param->rc.rateControlMode == X265_RC_CRF)
{
m_param->rc.qp = (int)m_param->rc.rfConstant;
@@ -288,9 +290,13 @@
m_ipOffset = 6.0 * X265_LOG2(m_param->rc.ipFactor);
m_pbOffset = 6.0 * X265_LOG2(m_param->rc.pbFactor);
+ for (int i = 0; i < QP_MAX_MAX; i++)
+ m_qpToEncodedBits[i] = 0;
+
/* Adjust the first frame in order to stabilize the quality level
compared to the rest */
#define ABR_INIT_QP_MIN (24)
#define ABR_INIT_QP_MAX (40)
+#define ABR_INIT_QP_GRAIN_MAX (32)
#define ABR_SCENECUT_INIT_QP_MIN (12)
#define CRF_INIT_QP (int)m_param->rc.rfConstant
for (int i = 0; i < 3; i++)
@@ -361,6 +367,7 @@
m_amortizeFraction = 0.85;
m_amortizeFrames = m_param->totalFrames / 2;
}
+
for (int i = 0; i < s_slidingWindowFrames; i++)
{
m_satdCostWindow[i] = 0;
@@ -370,15 +377,19 @@
m_isPatternPresent = false;
m_numBframesInPattern = 0;
+ m_isGrainEnabled = false;
+ if(m_param->rc.pbFactor <= 1.1 && !m_param->rc.cuTree) // tune for
grainy content OR equal p-b frame sizes
+ m_isGrainEnabled = true;
+
/* 720p videos seem to be a good cutoff for cplxrSum */
- double tuneCplxFactor = (m_param->rc.cuTree && m_ncu > 3600) ? 2.5 : 1;
-
+ double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree) ? 2.5 :
m_isGrainEnabled ? 1.9 : 1;
/* estimated ratio that produces a reasonable QP for the first I-frame
*/
m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) *
tuneCplxFactor;
m_wantedBitsWindow = m_bitrate * m_frameDuration;
m_accumPNorm = .01;
m_accumPQp = (m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP
: ABR_INIT_QP_MIN) * m_accumPNorm;
+
/* Frame Predictors used in vbv */
initFramePredictors();
if (!m_statFileOut && (m_param->rc.bStatWrite ||
m_param->rc.bStatRead))
@@ -1049,12 +1060,12 @@
}
m_pred[0].coeff = m_pred[3].coeff = 0.75;
m_pred[0].coeffMin = m_pred[3].coeffMin = 0.75 / 4;
- if (m_param->rc.qCompress >= 0.8) // when tuned for grain
+ if (m_isGrainEnabled) // when tuned for grain
{
m_pred[1].coeffMin = 0.75 / 4;
m_pred[1].coeff = 0.75;
- m_pred[0].coeff = m_pred[3].coeff = 0.5;
- m_pred[0].coeffMin = m_pred[3].coeffMin = 0.5 / 4;
+ m_pred[0].coeff = m_pred[3].coeff = 0.75;
+ m_pred[0].coeffMin = m_pred[3].coeffMin = 0.75 / 4;
}
}
@@ -1089,10 +1100,12 @@
}
rce->isActive = true;
bool isRefFrameScenecut = m_sliceType!= I_SLICE &&
m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut;
+ m_isFirstMiniGop = m_sliceType == I_SLICE ? true : m_isFirstMiniGop;
if (curFrame->m_lowres.bScenecut)
{
m_isSceneTransition = true;
m_lastPredictorReset = rce->encodeOrder;
+
initFramePredictors();
}
else if (m_sliceType != B_SLICE && !isRefFrameScenecut)
@@ -1197,7 +1210,7 @@
double q = x265_qScale2qp(rateEstimateQscale(curFrame, rce));
q = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, q);
m_qp = int(q + 0.5);
- rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = q;
+ rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = int(q +
0.5);
/* copy value of lastRceq into thread local rce struct *to be used
in RateControlEnd() */
rce->qRceq = m_lastRceq;
accumPQpUpdate();
@@ -1450,7 +1463,7 @@
}
if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames
||
- m_param->rc.bStrictCbr))
+ m_param->rc.bStrictCbr || m_isGrainEnabled))
{
abrBuffer *= X265_MAX(1, sqrt(timeDone));
overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits -
wantedBits) / abrBuffer);
@@ -1460,6 +1473,22 @@
return qScale;
}
+double RateControl::tuneQScaleForGrain(double rcOverflow)
+{
+ double qpstepBy1 = pow(2, 0.5 / 6.0);
+ double qScaleAvg = x265_qp2qScale(m_avgPFrameQp);
+ double q = m_lastQScaleFor[P_SLICE];
+ int curQp = int (x265_qScale2qp(m_lastQScaleFor[P_SLICE]) + 0.5);
+ double curBitrate = m_qpToEncodedBits[curQp] * int(m_fps + 0.5);
+ int newQp = rcOverflow > 1 ? curQp + 1 : curQp - 1 ;
+ double projectedBitrate = int(m_fps + 0.5) * m_qpToEncodedBits[newQp];
+ if (curBitrate > 0 && projectedBitrate > 0)
+ q = abs(projectedBitrate - m_bitrate) < abs (curBitrate -
m_bitrate) ? x265_qp2qScale(newQp) : m_lastQScaleFor[P_SLICE];
+ else
+ q = rcOverflow > 1 ? qScaleAvg * qpstepBy1 : rcOverflow < 1 ?
qScaleAvg / qpstepBy1 : m_lastQScaleFor[P_SLICE];
+ return q;
+}
+
double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry
*rce)
{
double q;
@@ -1525,6 +1554,7 @@
q0 = q1;
}
}
+
if (prevRefSlice->m_sliceType == B_SLICE &&
IS_REFERENCED(m_curSlice->m_refFrameList[0][0]))
q0 -= m_pbOffset / 2;
if (nextRefSlice->m_sliceType == B_SLICE &&
IS_REFERENCED(m_curSlice->m_refFrameList[1][0]))
@@ -1535,7 +1565,9 @@
q = q1;
else if (i1)
q = q0;
- else
+ else if(m_isGrainEnabled)
+ q = q1;
+ else
q = (q0 * dt1 + q1 * dt0) / (dt0 + dt1);
if (IS_REFERENCED(curFrame))
@@ -1543,7 +1575,7 @@
else
q += m_pbOffset;
- /* Set a min qp at scenechanges and transitions */
+ /* Set a min qp at scenechanges and transitions */
if (m_isSceneTransition)
{
q = X265_MAX(ABR_SCENECUT_INIT_QP_MIN, q);
@@ -1553,11 +1585,28 @@
double qScale = x265_qp2qScale(q);
rce->qpNoVbv = q;
double lmin = 0, lmax = 0;
+ if (m_isGrainEnabled && m_isFirstMiniGop)
+ {
+ lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
+ lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
+ double tunedQscale = tuneAbrQScaleFromFeedback(qScale);
+ double overflow = tunedQscale / qScale;
+ if (!m_isAbrReset)
+ qScale = x265_clip3(lmin, lmax, qScale);
+ m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
m_avgPFrameQp;
+ if (overflow != 1)
+ {
+ qScale = tuneQScaleForGrain(overflow);
+ q = x265_qScale2qp(qScale);
+ }
+ rce->qpNoVbv = q;
+ }
if (m_isVbv)
{
lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
- if (m_isCbr)
+
+ if (m_isCbr && !m_isGrainEnabled)
{
qScale = tuneAbrQScaleFromFeedback(qScale);
if (!m_isAbrReset)
@@ -1581,7 +1630,10 @@
rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned,
rce->frameSizeMaximum);
rce->frameSizeEstimated = rce->frameSizePlanned;
}
+
rce->newQScale = qScale;
+ if(rce->bLastMiniGopBFrame)
+ m_isFirstMiniGop = false;
return qScale;
}
else
@@ -1675,8 +1727,17 @@
if (!m_param->rc.bStatRead)
checkAndResetABR(rce, false);
double initialQScale = getQScale(rce, m_wantedBitsWindow /
m_cplxrSum);
- q = tuneAbrQScaleFromFeedback(initialQScale);
- overflow = q / initialQScale;
+ double tunedQScale =
tuneAbrQScaleFromFeedback(initialQScale);
+ overflow = tunedQScale / initialQScale;
+ q = !m_partialResidualFrames? tunedQScale : initialQScale;
+ bool isEncodeEnd = (m_param->totalFrames &&
+ m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;
+ bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);
+ if(m_isGrainEnabled && m_sliceType!= I_SLICE &&
!isEncodeEnd &&
+ ((overflow < 1.05 && overflow > 0.95) || isEncodeBeg))
+ {
+ q = tuneQScaleForGrain(overflow);
+ }
}
if (m_sliceType == I_SLICE && m_param->keyframeMax > 1
&& m_lastNonBPictType != I_SLICE && !m_isAbrReset)
@@ -1684,6 +1745,7 @@
if (!m_param->rc.bStrictCbr)
q = x265_qp2qScale(m_accumPQp / m_accumPNorm);
q /= fabs(m_param->rc.ipFactor);
+ m_avgPFrameQp = 0;
}
else if (m_framesDone > 0)
{
@@ -1708,8 +1770,18 @@
else if (m_framesDone == 0 && !m_isVbv &&
m_param->rc.rateControlMode == X265_RC_ABR)
{
/* for ABR alone, clip the first I frame qp */
- lqmax = x265_qp2qScale(ABR_INIT_QP_MAX) * m_lstep;
- q = X265_MIN(lqmax, q);
+ if (m_isGrainEnabled)
+ {
+ /* to maintain grain uniformity, set I frame qp in a
fixed range */
+ lqmax = x265_qp2qScale(ABR_INIT_QP_GRAIN_MAX) *
(m_lstep * m_lstep);
+ lqmin = x265_qp2qScale(ABR_INIT_QP_GRAIN_MAX) /
(m_lstep * m_lstep);
+ q = x265_clip3(lqmin, lqmax, q);
+ }
+ else
+ {
+ lqmax = x265_qp2qScale(ABR_INIT_QP_MAX) * m_lstep;
+ q = X265_MIN(lqmax, q);
+ }
}
q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
/* Set a min qp at scenechanges and transitions */
@@ -1720,6 +1792,11 @@
m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale,
m_lastQScaleFor[P_SLICE]);
}
rce->qpNoVbv = x265_qScale2qp(q);
+ if(m_sliceType == P_SLICE)
+ {
+ m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
m_avgPFrameQp;
+ m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2;
+ }
q = clipQscale(curFrame, rce, q);
/* clip qp to permissible range after vbv-lookahead
estimation to avoid possible
* mispredictions by initial frame size predictors, after each
scenecut */
@@ -2426,6 +2503,11 @@
int pos = m_sliderPos - m_param->frameNumThreads;
if (pos >= 0)
m_encodedBitsWindow[pos % s_slidingWindowFrames] = actualBits;
+ if(rce->sliceType != I_SLICE)
+ {
+ int qp = int (rce->qpaRc + 0.5);
+ m_qpToEncodedBits[qp] = m_qpToEncodedBits[qp] == 0 ? actualBits :
(m_qpToEncodedBits[qp] + actualBits) * 0.5;
+ }
}
if (m_2pass)
diff -r f548abe8eae8 -r cee55e38a093 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Wed Jan 20 18:27:42 2016 +0530
+++ b/source/encoder/ratecontrol.h Mon Jan 11 14:13:52 2016 +0530
@@ -126,7 +126,7 @@
bool m_isVbv;
bool m_isCbr;
bool m_singleFrameVbv;
-
+ bool m_isGrainEnabled;
bool m_isAbrReset;
int m_lastAbrResetPoc;
@@ -141,7 +141,8 @@
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;
+ 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 */
@@ -178,7 +179,7 @@
bool m_isPatternPresent;
bool m_isSceneTransition;
int m_lastPredictorReset;
-
+ double m_qpToEncodedBits[QP_MAX_MAX];
/* a common variable on which rateControlStart, rateControlEnd and
rateControUpdateStats waits to
* sync the calls to these functions. For example
* -F2:
@@ -269,6 +270,7 @@
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);
};
}
#endif // ifndef X265_RATECONTROL_H
On Wed, Jan 20, 2016 at 2:33 PM, <aarthi at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Aarthi Thirumalai
> # Date 1452501832 -19800
> # Mon Jan 11 14:13:52 2016 +0530
> # Node ID 46e5a95c852732058200d9a7bb34261011341cff
> # Parent 808ece071d225f300feaf08709a9f5e0872edc89
> rc: fix Rate Control for grainy content
>
> optimize params for tune grain, reduce frequent qp fluctions to prevent
> grain loss
>
> diff -r 808ece071d22 -r 46e5a95c8527 source/common/param.cpp
> --- a/source/common/param.cpp Mon Jan 18 21:21:25 2016 +0530
> +++ b/source/common/param.cpp Mon Jan 11 14:13:52 2016 +0530
> @@ -454,16 +454,11 @@
> }
> else if (!strcmp(tune, "grain"))
> {
> - param->deblockingFilterBetaOffset = -2;
> - param->deblockingFilterTCOffset = -2;
> - param->bIntraInBFrames = 0;
> - param->rdoqLevel = 2;
> - param->psyRdoq = 10.0;
> - param->psyRd = 0.5;
> param->rc.ipFactor = 1.1;
> - param->rc.pbFactor = 1.1;
> - param->rc.aqStrength = 0.3;
> - param->rc.qCompress = 0.8;
> + param->rc.pbFactor = 1.0;
> + param->rc.cuTree = 0;
> + param->rc.aqMode = 0;
> + param->rc.qpStep = 1.0;
> }
> else
> return -1;
> diff -r 808ece071d22 -r 46e5a95c8527 source/encoder/ratecontrol.cpp
> --- a/source/encoder/ratecontrol.cpp Mon Jan 18 21:21:25 2016 +0530
> +++ b/source/encoder/ratecontrol.cpp Mon Jan 11 14:13:52 2016 +0530
> @@ -190,6 +190,8 @@
> m_numEntries = 0;
> m_isSceneTransition = false;
> m_lastPredictorReset = 0;
> + m_avgPFrameQp = 0;
> + m_isFirstMiniGop = false;
> if (m_param->rc.rateControlMode == X265_RC_CRF)
> {
> m_param->rc.qp = (int)m_param->rc.rfConstant;
> @@ -288,6 +290,9 @@
> m_ipOffset = 6.0 * X265_LOG2(m_param->rc.ipFactor);
> m_pbOffset = 6.0 * X265_LOG2(m_param->rc.pbFactor);
>
> + for (int i = 0; i < QP_MAX_MAX; i++)
> + m_qpToEncodedBits[i] = 0;
> +
> /* Adjust the first frame in order to stabilize the quality level
> compared to the rest */
> #define ABR_INIT_QP_MIN (24)
> #define ABR_INIT_QP_MAX (40)
> @@ -361,6 +366,7 @@
> m_amortizeFraction = 0.85;
> m_amortizeFrames = m_param->totalFrames / 2;
> }
> +
> for (int i = 0; i < s_slidingWindowFrames; i++)
> {
> m_satdCostWindow[i] = 0;
> @@ -370,15 +376,19 @@
> m_isPatternPresent = false;
> m_numBframesInPattern = 0;
>
> + m_isGrainEnabled = false;
> + if(m_param->rc.pbFactor <= 1.1 && !m_param->rc.cuTree) // tune
> for grainy content OR equal p-b frame sizes
> + m_isGrainEnabled = true;
> +
> /* 720p videos seem to be a good cutoff for cplxrSum */
> - double tuneCplxFactor = (m_param->rc.cuTree && m_ncu > 3600) ? 2.5 :
> 1;
> -
> + double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree) ? 2.5 :
> m_isGrainEnabled ? 2 : 1;
> /* estimated ratio that produces a reasonable QP for the first
> I-frame */
> m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) *
> tuneCplxFactor;
> m_wantedBitsWindow = m_bitrate * m_frameDuration;
> m_accumPNorm = .01;
> m_accumPQp = (m_param->rc.rateControlMode == X265_RC_CRF ?
> CRF_INIT_QP : ABR_INIT_QP_MIN) * m_accumPNorm;
>
> +
> /* Frame Predictors used in vbv */
> initFramePredictors();
> if (!m_statFileOut && (m_param->rc.bStatWrite ||
> m_param->rc.bStatRead))
> @@ -1049,7 +1059,7 @@
> }
> m_pred[0].coeff = m_pred[3].coeff = 0.75;
> m_pred[0].coeffMin = m_pred[3].coeffMin = 0.75 / 4;
> - if (m_param->rc.qCompress >= 0.8) // when tuned for grain
> + if (m_isGrainEnabled) // when tuned for grain
> {
> m_pred[1].coeffMin = 0.75 / 4;
> m_pred[1].coeff = 0.75;
> @@ -1089,10 +1099,12 @@
> }
> rce->isActive = true;
> bool isRefFrameScenecut = m_sliceType!= I_SLICE &&
> m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut;
> + m_isFirstMiniGop = m_sliceType == I_SLICE ? true : m_isFirstMiniGop;
> if (curFrame->m_lowres.bScenecut)
> {
> m_isSceneTransition = true;
> m_lastPredictorReset = rce->encodeOrder;
> +
> initFramePredictors();
> }
> else if (m_sliceType != B_SLICE && !isRefFrameScenecut)
> @@ -1197,7 +1209,7 @@
> double q = x265_qScale2qp(rateEstimateQscale(curFrame, rce));
> q = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, q);
> m_qp = int(q + 0.5);
> - rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = q;
> + rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = int(q
> + 0.5);
> /* copy value of lastRceq into thread local rce struct *to be
> used in RateControlEnd() */
> rce->qRceq = m_lastRceq;
> accumPQpUpdate();
> @@ -1450,7 +1462,7 @@
> }
>
> if (wantedBits > 0 && encodedBits > 0 &&
> (!m_partialResidualFrames ||
> - m_param->rc.bStrictCbr))
> + m_param->rc.bStrictCbr || m_isGrainEnabled))
> {
> abrBuffer *= X265_MAX(1, sqrt(timeDone));
> overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits -
> wantedBits) / abrBuffer);
> @@ -1460,6 +1472,22 @@
> return qScale;
> }
>
> +double RateControl::tuneQScaleForGrain(double rcOverflow)
> +{
> + double qpstepBy1 = pow(2, 0.5 / 6.0);
> + double qScaleAvg = x265_qp2qScale(m_avgPFrameQp);
> + double q = m_lastQScaleFor[P_SLICE];
> + int curQp = int (x265_qScale2qp(m_lastQScaleFor[P_SLICE]) + 0.5);
> + double curBitrate = m_qpToEncodedBits[curQp] * int(m_fps + 0.5);
> + int newQp = rcOverflow > 1 ? curQp + 1 : curQp - 1 ;
> + double projectedBitrate = int(m_fps + 0.5) *
> m_qpToEncodedBits[newQp];
> + if (curBitrate > 0 && projectedBitrate > 0)
> + q = abs(projectedBitrate - m_bitrate) < abs (curBitrate -
> m_bitrate) ? x265_qp2qScale(newQp) : m_lastQScaleFor[P_SLICE];
> + else
> + q = rcOverflow > 1 ? qScaleAvg * qpstepBy1 : rcOverflow < 1 ?
> qScaleAvg / qpstepBy1 : m_lastQScaleFor[P_SLICE];
> + return q;
> +}
> +
> double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry
> *rce)
> {
> double q;
> @@ -1525,6 +1553,7 @@
> q0 = q1;
> }
> }
> +
> if (prevRefSlice->m_sliceType == B_SLICE &&
> IS_REFERENCED(m_curSlice->m_refFrameList[0][0]))
> q0 -= m_pbOffset / 2;
> if (nextRefSlice->m_sliceType == B_SLICE &&
> IS_REFERENCED(m_curSlice->m_refFrameList[1][0]))
> @@ -1535,7 +1564,9 @@
> q = q1;
> else if (i1)
> q = q0;
> - else
> + else if(m_isGrainEnabled)
> + q = q1;
> + else
> q = (q0 * dt1 + q1 * dt0) / (dt0 + dt1);
>
> if (IS_REFERENCED(curFrame))
> @@ -1543,7 +1574,7 @@
> else
> q += m_pbOffset;
>
> - /* Set a min qp at scenechanges and transitions */
> + /* Set a min qp at scenechanges and transitions */
> if (m_isSceneTransition)
> {
> q = X265_MAX(ABR_SCENECUT_INIT_QP_MIN, q);
> @@ -1553,11 +1584,28 @@
> double qScale = x265_qp2qScale(q);
> rce->qpNoVbv = q;
> double lmin = 0, lmax = 0;
> + if (m_isGrainEnabled && m_isFirstMiniGop)
> + {
> + lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
> + lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
> + double tunedQscale = tuneAbrQScaleFromFeedback(qScale);
> + double overflow = tunedQscale / qScale;
> + if (!m_isAbrReset)
> + qScale = x265_clip3(lmin, lmax, qScale);
> + m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
> m_avgPFrameQp;
> + if (overflow != 1)
> + {
> + qScale = tuneQScaleForGrain(overflow);
> + q = x265_qScale2qp(qScale);
> + }
> + rce->qpNoVbv = q;
> + }
> if (m_isVbv)
> {
> lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
> lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
> - if (m_isCbr)
> +
> + if (m_isCbr && !m_isGrainEnabled)
> {
> qScale = tuneAbrQScaleFromFeedback(qScale);
> if (!m_isAbrReset)
> @@ -1581,7 +1629,10 @@
> rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned,
> rce->frameSizeMaximum);
> rce->frameSizeEstimated = rce->frameSizePlanned;
> }
> +
> rce->newQScale = qScale;
> + if(rce->bLastMiniGopBFrame)
> + m_isFirstMiniGop = false;
> return qScale;
> }
> else
> @@ -1675,8 +1726,17 @@
> if (!m_param->rc.bStatRead)
> checkAndResetABR(rce, false);
> double initialQScale = getQScale(rce, m_wantedBitsWindow
> / m_cplxrSum);
> - q = tuneAbrQScaleFromFeedback(initialQScale);
> - overflow = q / initialQScale;
> + double tunedQScale =
> tuneAbrQScaleFromFeedback(initialQScale);
> + overflow = tunedQScale / initialQScale;
> + q = !m_partialResidualFrames? tunedQScale : initialQScale;
> + bool isEncodeEnd = (m_param->totalFrames &&
> + m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;
> + bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);
> + if(m_isGrainEnabled && m_sliceType!= I_SLICE &&
> !isEncodeEnd &&
> + ((overflow < 1.05 && overflow > 0.95) || isEncodeBeg))
> + {
> + q = tuneQScaleForGrain(overflow);
> + }
> }
> if (m_sliceType == I_SLICE && m_param->keyframeMax > 1
> && m_lastNonBPictType != I_SLICE && !m_isAbrReset)
> @@ -1684,6 +1744,7 @@
> if (!m_param->rc.bStrictCbr)
> q = x265_qp2qScale(m_accumPQp / m_accumPNorm);
> q /= fabs(m_param->rc.ipFactor);
> + m_avgPFrameQp = 0;
> }
> else if (m_framesDone > 0)
> {
> @@ -1720,6 +1781,11 @@
> m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale,
> m_lastQScaleFor[P_SLICE]);
> }
> rce->qpNoVbv = x265_qScale2qp(q);
> + if(m_sliceType == P_SLICE)
> + {
> + m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
> m_avgPFrameQp;
> + m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2;
> + }
> q = clipQscale(curFrame, rce, q);
> /* clip qp to permissible range after vbv-lookahead
> estimation to avoid possible
> * mispredictions by initial frame size predictors, after
> each scenecut */
> @@ -2426,6 +2492,11 @@
> int pos = m_sliderPos - m_param->frameNumThreads;
> if (pos >= 0)
> m_encodedBitsWindow[pos % s_slidingWindowFrames] = actualBits;
> + if(rce->sliceType != I_SLICE)
> + {
> + int qp = int (rce->qpaRc + 0.5);
> + m_qpToEncodedBits[qp] = m_qpToEncodedBits[qp] == 0 ? actualBits
> : (m_qpToEncodedBits[qp] + actualBits) * 0.5;
> + }
> }
>
> if (m_2pass)
> diff -r 808ece071d22 -r 46e5a95c8527 source/encoder/ratecontrol.h
> --- a/source/encoder/ratecontrol.h Mon Jan 18 21:21:25 2016 +0530
> +++ b/source/encoder/ratecontrol.h Mon Jan 11 14:13:52 2016 +0530
> @@ -126,7 +126,7 @@
> bool m_isVbv;
> bool m_isCbr;
> bool m_singleFrameVbv;
> -
> + bool m_isGrainEnabled;
> bool m_isAbrReset;
> int m_lastAbrResetPoc;
>
> @@ -141,7 +141,8 @@
> 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;
> + 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 */
> @@ -178,7 +179,7 @@
> bool m_isPatternPresent;
> bool m_isSceneTransition;
> int m_lastPredictorReset;
> -
> + double m_qpToEncodedBits[QP_MAX_MAX];
> /* a common variable on which rateControlStart, rateControlEnd and
> rateControUpdateStats waits to
> * sync the calls to these functions. For example
> * -F2:
> @@ -269,6 +270,7 @@
> 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);
> };
> }
> #endif // ifndef X265_RATECONTROL_H
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20160127/4ce89453/attachment-0001.html>
More information about the x265-devel
mailing list