[x265] [PATCH 2 of 3] cuDeltaQP: raise QP of CUs that are far off the meanQP to minimize deltaQP fluctuations
kavitha at multicorewareinc.com
kavitha at multicorewareinc.com
Thu Dec 22 10:59:19 CET 2016
# HG changeset patch
# User Kavitha Sampath <kavitha at multicorewareinc.com>
# Date 1482058180 -19800
# Sun Dec 18 16:19:40 2016 +0530
# Node ID f1b91c4f65a3a5069d326d422134080a5484d540
# Parent 62f0c309ca7057dcdc3e604f74fad58ff885c740
cuDeltaQP: raise QP of CUs that are far off the meanQP to minimize deltaQP fluctuations
diff -r 62f0c309ca70 -r f1b91c4f65a3 source/common/cudata.h
--- a/source/common/cudata.h Wed Dec 21 15:46:09 2016 +0530
+++ b/source/common/cudata.h Sun Dec 18 16:19:40 2016 +0530
@@ -216,6 +216,7 @@
const CUData* m_cuAboveRight; // pointer to above-right neighbor CTU
const CUData* m_cuAbove; // pointer to above neighbor CTU
const CUData* m_cuLeft; // pointer to left neighbor CTU
+ double m_meanQP;
CUData();
diff -r 62f0c309ca70 -r f1b91c4f65a3 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp Wed Dec 21 15:46:09 2016 +0530
+++ b/source/encoder/analysis.cpp Sun Dec 18 16:19:40 2016 +0530
@@ -142,6 +142,7 @@
ctu.setQPSubParts((int8_t)qp, 0, 0);
m_rqt[0].cur.load(initialContext);
+ ctu.m_meanQP = initialContext.m_meanQP;
m_modeDepth[0].fencYuv.copyFromPicYuv(*m_frame->m_fencPic, ctu.m_cuAddr, 0);
uint32_t numPartition = ctu.m_numPartitions;
@@ -197,7 +198,7 @@
compressInterCU_rd5_6(ctu, cuGeom, qp);
}
- if (m_param->bEnableRdRefine)
+ if (m_param->bEnableRdRefine || m_param->bOptCUDeltaQP)
qprdRefine(ctu, cuGeom, qp, qp);
return *m_modeDepth[0].bestMode;
@@ -299,8 +300,13 @@
int cuIdx = (cuGeom.childOffset - 1) / 3;
bestCUCost = origCUCost = cacheCost[cuIdx];
- for (int dir = 2; dir >= -2; dir -= 4)
+ int direction = m_param->bOptCUDeltaQP ? 1 : 2;
+
+ for (int dir = direction; dir >= -direction; dir -= (direction * 2))
{
+ if (m_param->bOptCUDeltaQP && ((dir != 1) || ((qp + 3) >= (int32_t)parentCTU.m_meanQP)))
+ break;
+
int threshold = 1;
int failure = 0;
cuPrevCost = origCUCost;
@@ -308,6 +314,9 @@
int modCUQP = qp + dir;
while (modCUQP >= m_param->rc.qpMin && modCUQP <= QP_MAX_SPEC)
{
+ if (m_param->bOptCUDeltaQP && modCUQP > (int32_t)parentCTU.m_meanQP)
+ break;
+
recodeCU(parentCTU, cuGeom, modCUQP, qp);
cuCost = md.bestMode->rdCost;
diff -r 62f0c309ca70 -r f1b91c4f65a3 source/encoder/entropy.cpp
--- a/source/encoder/entropy.cpp Wed Dec 21 15:46:09 2016 +0530
+++ b/source/encoder/entropy.cpp Sun Dec 18 16:19:40 2016 +0530
@@ -226,6 +226,7 @@
markValid();
m_fracBits = 0;
m_pad = 0;
+ m_meanQP = 0;
X265_CHECK(sizeof(m_contextState) >= sizeof(m_contextState[0]) * MAX_OFF_CTX_MOD, "context state table is too small\n");
}
diff -r 62f0c309ca70 -r f1b91c4f65a3 source/encoder/entropy.h
--- a/source/encoder/entropy.h Wed Dec 21 15:46:09 2016 +0530
+++ b/source/encoder/entropy.h Sun Dec 18 16:19:40 2016 +0530
@@ -111,6 +111,7 @@
int m_bitsLeft;
uint64_t m_fracBits;
EstBitsSbac m_estBitsSbac;
+ double m_meanQP;
Entropy();
diff -r 62f0c309ca70 -r f1b91c4f65a3 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Wed Dec 21 15:46:09 2016 +0530
+++ b/source/encoder/frameencoder.cpp Sun Dec 18 16:19:40 2016 +0530
@@ -1182,6 +1182,65 @@
//m_rows[row - 1].bufferedEntropy.loadContexts(m_initSliceContext);
}
+ // calculate mean QP for consistent deltaQP signalling calculation
+ if (m_param->bOptCUDeltaQP)
+ {
+ ScopedLock self(curRow.lock);
+ if (!curRow.avgQPComputed)
+ {
+ if (m_param->bEnableWavefront || !row)
+ {
+ double meanQPOff = 0;
+ uint32_t loopIncr, count = 0;
+ bool isReferenced = IS_REFERENCED(m_frame);
+ double *qpoffs = (isReferenced && m_param->rc.cuTree) ? m_frame->m_lowres.qpCuTreeOffset : m_frame->m_lowres.qpAqOffset;
+ if (qpoffs)
+ {
+ if (m_param->rc.qgSize == 8)
+ loopIncr = 8;
+ else
+ loopIncr = 16;
+ uint32_t cuYStart = 0, height = m_frame->m_fencPic->m_picHeight;
+ if (m_param->bEnableWavefront)
+ {
+ cuYStart = intRow * m_param->maxCUSize;
+ height = cuYStart + m_param->maxCUSize;
+ }
+
+ uint32_t qgSize = m_param->rc.qgSize, width = m_frame->m_fencPic->m_picWidth;
+ uint32_t maxOffsetCols = (m_frame->m_fencPic->m_picWidth + (loopIncr - 1)) / loopIncr;
+ for (uint32_t cuY = cuYStart; cuY < height && (cuY < m_frame->m_fencPic->m_picHeight); cuY += qgSize)
+ {
+ for (uint32_t cuX = 0; cuX < width; cuX += qgSize)
+ {
+ double qp_offset = 0;
+ uint32_t cnt = 0;
+
+ for (uint32_t block_yy = cuY; block_yy < cuY + qgSize && block_yy < m_frame->m_fencPic->m_picHeight; block_yy += loopIncr)
+ {
+ for (uint32_t block_xx = cuX; block_xx < cuX + qgSize && block_xx < width; block_xx += loopIncr)
+ {
+ int idx = ((block_yy / loopIncr) * (maxOffsetCols)) + (block_xx / loopIncr);
+ qp_offset += qpoffs[idx];
+ cnt++;
+ }
+ }
+ qp_offset /= cnt;
+ meanQPOff += qp_offset;
+ count++;
+ }
+ }
+ meanQPOff /= count;
+ }
+ rowCoder.m_meanQP = slice->m_sliceQp + meanQPOff;
+ }
+ else
+ {
+ rowCoder.m_meanQP = m_rows[0].rowGoOnCoder.m_meanQP;
+ }
+ curRow.avgQPComputed = 1;
+ }
+ }
// TODO: specially case handle on first and last row
diff -r 62f0c309ca70 -r f1b91c4f65a3 source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h Wed Dec 21 15:46:09 2016 +0530
+++ b/source/encoder/frameencoder.h Sun Dec 18 16:19:40 2016 +0530
@@ -95,6 +95,7 @@
/* count of completed CUs in this row */
volatile uint32_t completed;
+ volatile uint32_t avgQPComputed;
/* called at the start of each frame to initialize state */
void init(Entropy& initContext, unsigned int sid)
@@ -102,6 +103,7 @@
active = false;
busy = false;
completed = 0;
+ avgQPComputed = 0;
sliceId = sid;
memset(&rowStats, 0, sizeof(rowStats));
rowGoOnCoder.load(initContext);
More information about the x265-devel
mailing list