[x265] [PATCH] rc: update vbv for all b frames
Steve Borho
steve at borho.org
Thu Jul 31 22:04:13 CEST 2014
# HG changeset patch
# User Santhoshini Sekar <santhoshini at multicorewareinc.com>
# Date 1406785082 -19800
# Thu Jul 31 11:08:02 2014 +0530
# Node ID e85b0aaa64e4aaccdfd37de92e14d91a53a789ea
# Parent 88a18a365d56cb6ef67df157f16ff52f5ccbd1db
rc: update vbv for all b frames
HEVC is complex (and slow) enough that we can afford to update/plan the VBV
buffer states for all frames, not just I and P. The leads to smoother rate
control, particularly when there are large stretches of B frames, and less
(over) compensation is necessary for P frames.
diff -r 88a18a365d56 -r e85b0aaa64e4 source/common/lowres.cpp
--- a/source/common/lowres.cpp Thu Jul 31 16:49:02 2014 +0530
+++ b/source/common/lowres.cpp Thu Jul 31 11:08:02 2014 +0530
@@ -135,6 +135,7 @@
sliceType = type;
frameNum = poc;
leadingBframes = 0;
+ indB = 0;
satdCost = (int64_t)-1;
memset(costEst, -1, sizeof(costEst));
memset(weightedCostDelta, 0, sizeof(weightedCostDelta));
diff -r 88a18a365d56 -r e85b0aaa64e4 source/common/lowres.h
--- a/source/common/lowres.h Thu Jul 31 16:49:02 2014 +0530
+++ b/source/common/lowres.h Thu Jul 31 11:08:02 2014 +0530
@@ -121,8 +121,11 @@
uint16_t(*lowresCosts[X265_BFRAME_MAX + 2][X265_BFRAME_MAX + 2]);
int32_t* lowresMvCosts[2][X265_BFRAME_MAX + 1];
MV* lowresMvs[2][X265_BFRAME_MAX + 1];
+
+ /* used for vbvLookahead */
int plannedType[X265_LOOKAHEAD_MAX + 1];
int64_t plannedSatd[X265_LOOKAHEAD_MAX + 1];
+ int indB;
int bframes;
/* rate control / adaptive quant data */
@@ -132,6 +135,7 @@
uint64_t wp_ssd[3]; // This is different than SSDY, this is sum(pixel^2) - sum(pixel)^2 for entire frame
uint64_t wp_sum[3];
+ /* cutree intermediate data */
uint16_t* propagateCost;
double weightedCostDelta[X265_BFRAME_MAX + 2];
diff -r 88a18a365d56 -r e85b0aaa64e4 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Thu Jul 31 16:49:02 2014 +0530
+++ b/source/encoder/ratecontrol.cpp Thu Jul 31 11:08:02 2014 +0530
@@ -1368,6 +1368,11 @@
q += m_pbOffset;
rce->qpNoVbv = q;
double qScale = x265_qp2qScale(q);
+ if (m_bframes > 5 && m_isVbv)
+ {
+ qScale = clipQscale(pic, qScale);
+ m_lastQScaleFor[m_sliceType] = qScale;
+ }
rce->frameSizePlanned = predictSize(&m_predBfromP, qScale, (double)m_leadingNoBSatd);
rce->frameSizeEstimated = rce->frameSizePlanned;
rce->newQScale = qScale;
@@ -1652,11 +1657,15 @@
for (int iterations = 0; iterations < 1000 && loopTerminate != 3; iterations++)
{
double frameQ[3];
- double curBits = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd);
+ double curBits;
+ if (m_sliceType == B_SLICE)
+ curBits = predictSize(&m_predBfromP, q, (double)m_currentSatd);
+ else
+ curBits = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd);
double bufferFillCur = m_bufferFill - curBits;
double targetFill;
double totalDuration = 0;
- frameQ[P_SLICE] = m_sliceType == I_SLICE ? q * m_param->rc.ipFactor : q;
+ frameQ[P_SLICE] = m_sliceType == I_SLICE ? q * m_param->rc.ipFactor : (m_sliceType == B_SLICE ? q / m_param->rc.pbFactor : q);
frameQ[B_SLICE] = frameQ[P_SLICE] * m_param->rc.pbFactor;
frameQ[I_SLICE] = frameQ[P_SLICE] / m_param->rc.ipFactor;
/* Loop over the planned future frames. */
@@ -1695,7 +1704,7 @@
else
{
/* Fallback to old purely-reactive algorithm: no lookahead. */
- if ((m_sliceType == P_SLICE ||
+ if ((m_sliceType == P_SLICE || m_sliceType == B_SLICE ||
(m_sliceType == I_SLICE && m_lastNonBPictType == I_SLICE)) &&
m_bufferFill / m_bufferSize < 0.5)
{
@@ -1726,25 +1735,6 @@
q = X265_MAX(q0, q);
}
- // Check B-frame complexity, and use up any bits that would
- // overflow before the next P-frame.
- if (m_sliceType == P_SLICE && !m_singleFrameVbv)
- {
- int nb = m_bframes;
- double bits = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd);
- double bbits = predictSize(&m_predBfromP, q * m_param->rc.pbFactor, (double)m_currentSatd);
- double space;
- if (bbits > m_bufferRate)
- nb = 0;
- double pbbits = nb * bbits;
-
- space = m_bufferFill + (1 + nb) * m_bufferRate - m_bufferSize;
- if (pbbits < space)
- {
- q *= X265_MAX(pbbits / space, bits / (0.5 * m_bufferSize));
- }
- q = X265_MAX(q0 / 2, q);
- }
if (!m_isCbr)
q = X265_MAX(q0, q);
diff -r 88a18a365d56 -r e85b0aaa64e4 source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Thu Jul 31 16:49:02 2014 +0530
+++ b/source/encoder/slicetype.cpp Thu Jul 31 11:08:02 2014 +0530
@@ -532,13 +532,13 @@
void Lookahead::vbvLookahead(Lowres **frames, int numFrames, int keyframe)
{
int prevNonB = 0, curNonB = 1, idx = 0;
+ bool isNextNonB = false;
while (curNonB < numFrames && frames[curNonB]->sliceType == X265_TYPE_B)
- {
curNonB++;
- }
int nextNonB = keyframe ? prevNonB : curNonB;
+ int nextB = keyframe ? prevNonB + 1 : curNonB + 1;
while (curNonB < numFrames + !keyframe)
{
@@ -557,12 +557,33 @@
frames[nextNonB]->plannedType[idx] = X265_TYPE_B;
}
+ for (int i = nextB; i <= curNonB; i++)
+ {
+ for (int j = frames[i]->indB + i + 1; j <= curNonB; j++, frames[i]->indB++)
+ {
+ if (j == curNonB)
+ {
+ if (isNextNonB)
+ {
+ int p0 = IS_X265_TYPE_I(frames[curNonB]->sliceType) ? curNonB : prevNonB;
+ frames[i]->plannedSatd[frames[i]->indB] = vbvFrameCost(frames, p0, curNonB, curNonB);
+ frames[i]->plannedType[frames[i]->indB] = frames[curNonB]->sliceType;
+ }
+ }
+ else
+ {
+ frames[i]->plannedSatd[frames[i]->indB] = vbvFrameCost(frames, prevNonB, curNonB, j);
+ frames[i]->plannedType[frames[i]->indB] = X265_TYPE_B;
+ }
+ }
+ if (i == curNonB && !isNextNonB)
+ isNextNonB = true;
+ }
+
prevNonB = curNonB;
curNonB++;
while (curNonB <= numFrames && frames[curNonB]->sliceType == X265_TYPE_B)
- {
curNonB++;
- }
}
frames[nextNonB]->plannedType[idx] = X265_TYPE_AUTO;
More information about the x265-devel
mailing list