[x265] [PATCH 2 of 5] Influence depth decisions based on CTUInfo recieved through API
vignesh at multicorewareinc.com
vignesh at multicorewareinc.com
Tue May 9 10:44:13 CEST 2017
# HG changeset patch
# User Vignesh Vijayakumar
# Date 1491887898 -19800
# Tue Apr 11 10:48:18 2017 +0530
# Node ID cf414fc0a459dea19015ca07d130e1234890541a
# Parent b5f7b13bf089d09bba8c121e11bdfce824f42e64
Influence depth decisions based on CTUInfo recieved through API
diff -r b5f7b13bf089 -r cf414fc0a459 source/common/frame.cpp
--- a/source/common/frame.cpp Mon Apr 24 10:13:57 2017 +0530
+++ b/source/common/frame.cpp Tue Apr 11 10:48:18 2017 +0530
@@ -50,6 +50,8 @@
m_reconfigureRc = false;
m_ctuInfo = NULL;
m_prevCtuInfoChange = NULL;
+ m_addOnDepth = NULL;
+ m_addOnCtuInfo = NULL;
}
bool Frame::create(x265_param *param, float* quantOffsets)
@@ -58,6 +60,20 @@
m_param = param;
CHECKED_MALLOC_ZERO(m_rcData, RcStats, 1);
+ if (param->bCTUInfo)
+ {
+ uint32_t widthInCTU = (m_param->sourceWidth + g_maxCUSize - 1) >> g_maxLog2CUSize;
+ uint32_t heightInCTU = (m_param->sourceHeight + g_maxCUSize - 1) >> g_maxLog2CUSize;
+ uint32_t numCTUsInFrame = widthInCTU * heightInCTU;
+ CHECKED_MALLOC_ZERO(m_addOnDepth, uint8_t *, numCTUsInFrame);
+ CHECKED_MALLOC_ZERO(m_addOnCtuInfo, uint8_t *, numCTUsInFrame);
+ for (uint32_t i = 0; i < numCTUsInFrame; i++)
+ {
+ CHECKED_MALLOC_ZERO(m_addOnDepth[i], uint8_t, uint32_t(NUM_4x4_PARTITIONS));
+ CHECKED_MALLOC_ZERO(m_addOnCtuInfo[i], uint8_t, uint32_t(NUM_4x4_PARTITIONS));
+ }
+ }
+
if (m_fencPic->create(param->sourceWidth, param->sourceHeight, param->internalCsp) &&
m_lowres.create(m_fencPic, param->bframes, !!param->rc.aqMode || !!param->bAQMotion, param->rc.qgSize))
{
@@ -177,6 +193,10 @@
{
X265_FREE((*m_ctuInfo + i)->ctuInfo);
(*m_ctuInfo + i)->ctuInfo = NULL;
+ X265_FREE(m_addOnDepth[i]);
+ m_addOnDepth[i] = NULL;
+ X265_FREE(m_addOnCtuInfo[i]);
+ m_addOnCtuInfo[i] = NULL;
}
X265_FREE(*m_ctuInfo);
*m_ctuInfo = NULL;
@@ -184,6 +204,11 @@
m_ctuInfo = NULL;
X265_FREE(m_prevCtuInfoChange);
m_prevCtuInfoChange = NULL;
+ X265_FREE(m_addOnDepth);
+ m_addOnDepth = NULL;
+ X265_FREE(m_addOnCtuInfo);
+ m_addOnCtuInfo = NULL;
+
}
m_lowres.destroy();
X265_FREE(m_rcData);
diff -r b5f7b13bf089 -r cf414fc0a459 source/common/frame.h
--- a/source/common/frame.h Mon Apr 24 10:13:57 2017 +0530
+++ b/source/common/frame.h Tue Apr 11 10:48:18 2017 +0530
@@ -112,6 +112,9 @@
int* m_prevCtuInfoChange;
int64_t m_encodeStartTime;
+
+ uint8_t** m_addOnDepth;
+ uint8_t** m_addOnCtuInfo;
Frame();
bool create(x265_param *param, float* quantOffsets);
diff -r b5f7b13bf089 -r cf414fc0a459 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp Mon Apr 24 10:13:57 2017 +0530
+++ b/source/encoder/analysis.cpp Tue Apr 11 10:48:18 2017 +0530
@@ -150,6 +150,33 @@
calculateNormFactor(ctu, qp);
uint32_t numPartition = ctu.m_numPartitions;
+ if (m_param->bCTUInfo && (*m_frame->m_ctuInfo + ctu.m_cuAddr))
+ {
+ x265_ctu_info_t* ctuTemp = *m_frame->m_ctuInfo + ctu.m_cuAddr;
+ if (ctuTemp->ctuPartitions)
+ {
+ int32_t depthIdx = 0;
+ uint8_t* depthInfoPtr = m_frame->m_addOnDepth[ctu.m_cuAddr];
+ uint8_t* contentInfoPtr = m_frame->m_addOnCtuInfo[ctu.m_cuAddr];
+ do
+ {
+ uint8_t depth = (uint8_t)ctuTemp->ctuPartitions[depthIdx];
+ uint8_t content = (uint8_t)(*((int32_t *)ctuTemp->ctuInfo + depthIdx));
+ memset(depthInfoPtr, depth, sizeof(uint8_t) * numPartition >> 2 * depth);
+ memset(contentInfoPtr, content, sizeof(uint8_t) * numPartition >> 2 * depth);
+ depthInfoPtr += ctu.m_numPartitions >> 2 * depth;
+ contentInfoPtr += ctu.m_numPartitions >> 2 * depth;
+ depthIdx++;
+ } while (ctuTemp->ctuPartitions[depthIdx] != 0);
+
+ m_additionalCtuInfo = m_frame->m_addOnCtuInfo[ctu.m_cuAddr];
+ memcpy(ctu.m_cuDepth, m_frame->m_addOnDepth[ctu.m_cuAddr], sizeof(uint8_t) * numPartition);
+ //Calculate log2CUSize from depth
+ for (uint32_t i = 0; i < cuGeom.numPartitions; i++)
+ ctu.m_log2CUSize[i] = (uint8_t)g_maxLog2CUSize - ctu.m_cuDepth[i];
+ }
+ }
+
if (m_param->analysisMultiPassRefine && m_param->rc.bStatRead)
{
m_multipassAnalysis = (analysis2PassFrameData*)m_frame->m_analysis2Pass.analysisFramedata;
@@ -1017,11 +1044,13 @@
bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
uint32_t minDepth = topSkipMinDepth(parentCTU, cuGeom);
+ bool bDecidedDepth = parentCTU.m_cuDepth[cuGeom.absPartIdx] == depth;
bool skipModes = false; /* Skip any remaining mode analyses at current depth */
bool skipRecursion = false; /* Skip recursion */
bool splitIntra = true;
bool skipRectAmp = false;
bool chooseMerge = false;
+ bool bCtuInfoCheck = false;
if ((m_limitTU & X265_TU_LIMIT_NEIGH) && cuGeom.log2CUSize >= 4)
m_maxTUDepth = loadTUDepth(cuGeom, parentCTU);
@@ -1040,6 +1069,26 @@
md.pred[PRED_2Nx2N].sa8dCost = 0;
}
+ if (m_param->bCTUInfo && depth <= parentCTU.m_cuDepth[cuGeom.absPartIdx])
+ {
+ if (depth < parentCTU.m_cuDepth[cuGeom.absPartIdx])
+ {
+ mightNotSplit &= bDecidedDepth;
+ bCtuInfoCheck = skipRecursion = false;
+ skipModes = true;
+ }
+ else if (mightNotSplit && bDecidedDepth)
+ {
+ if (m_additionalCtuInfo[cuGeom.absPartIdx])
+ bCtuInfoCheck = skipRecursion = true;
+ mightSplit &= !bDecidedDepth;
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);
+ checkMerge2Nx2N_rd0_4(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom);
+ if (m_param->rdLevel)
+ skipModes = m_param->bEnableEarlySkip && md.bestMode && md.bestMode->cu.isSkipped(0);
+ }
+ }
if (m_param->analysisMode == X265_ANALYSIS_LOAD && m_param->analysisRefineLevel > 1)
{
if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx])
@@ -1082,7 +1131,7 @@
}
/* Step 1. Evaluate Merge/Skip candidates for likely early-outs, if skip mode was not set above */
- if (mightNotSplit && depth >= minDepth && !md.bestMode) /* TODO: Re-evaluate if analysis load/save still works */
+ if (mightNotSplit && depth >= minDepth && !md.bestMode && !bCtuInfoCheck) /* TODO: Re-evaluate if analysis load/save still works */
{
/* Compute Merge Cost */
md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
@@ -1092,7 +1141,7 @@
skipModes = m_param->bEnableEarlySkip && md.bestMode && md.bestMode->cu.isSkipped(0); // TODO: sa8d threshold per depth
}
- if (md.bestMode && m_param->bEnableRecursionSkip)
+ if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck)
{
skipRecursion = md.bestMode->cu.isSkipped(0);
if (mightSplit && depth >= minDepth && !skipRecursion)
@@ -1584,10 +1633,12 @@
bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
+ bool bDecidedDepth = parentCTU.m_cuDepth[cuGeom.absPartIdx] == depth;
bool skipRecursion = false;
bool skipModes = false;
bool splitIntra = true;
bool skipRectAmp = false;
+ bool bCtuInfoCheck = false;
// avoid uninitialize value in below reference
if (m_param->limitModes)
@@ -1607,6 +1658,29 @@
splitData[3].initSplitCUData();
uint32_t allSplitRefs = splitData[0].splitRefs | splitData[1].splitRefs | splitData[2].splitRefs | splitData[3].splitRefs;
uint32_t refMasks[2];
+ if (m_param->bCTUInfo && depth <= parentCTU.m_cuDepth[cuGeom.absPartIdx])
+ {
+ if (depth < parentCTU.m_cuDepth[cuGeom.absPartIdx])
+ {
+ mightNotSplit &= bDecidedDepth;
+ bCtuInfoCheck = skipRecursion = false;
+ skipModes = true;
+ }
+ else if (mightNotSplit && bDecidedDepth)
+ {
+ if (m_additionalCtuInfo[cuGeom.absPartIdx])
+ bCtuInfoCheck = skipRecursion = true;
+ mightSplit &= !bDecidedDepth;
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);
+ checkMerge2Nx2N_rd5_6(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom);
+ skipModes = !!m_param->bEnableEarlySkip && md.bestMode;
+ refMasks[0] = allSplitRefs;
+ md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);
+ checkInter_rd5_6(md.pred[PRED_2Nx2N], cuGeom, SIZE_2Nx2N, refMasks);
+ checkBestMode(md.pred[PRED_2Nx2N], cuGeom.depth);
+ }
+ }
if (m_param->analysisMode == X265_ANALYSIS_LOAD && m_param->analysisRefineLevel > 1)
{
if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx])
@@ -1653,7 +1727,7 @@
}
/* Step 1. Evaluate Merge/Skip candidates for likely early-outs */
- if (mightNotSplit && !md.bestMode)
+ if (mightNotSplit && !md.bestMode && !bCtuInfoCheck)
{
md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);
md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
diff -r b5f7b13bf089 -r cf414fc0a459 source/encoder/analysis.h
--- a/source/encoder/analysis.h Mon Apr 24 10:13:57 2017 +0530
+++ b/source/encoder/analysis.h Tue Apr 11 10:48:18 2017 +0530
@@ -137,6 +137,8 @@
int* m_multipassMvpIdx[2];
int32_t* m_multipassRef[2];
uint8_t* m_multipassModes;
+
+ uint8_t* m_additionalCtuInfo;
/* refine RD based on QP for rd-levels 5 and 6 */
void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t lqp);
More information about the x265-devel
mailing list