<div dir="ltr"><div><div><div>Just reviewed this patch, and made the following changes. <br><br></div>1. Changed the depth parameter to QGSize. This is a lot simpler to explain and more intuitive to users since it correlates directly to the Quantization Group specified by the HEVC standard. <br><br></div>2. Fixed all explanations, commit messages and param explanations<br><br></div>3. Fixed a bug explained below.<br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Mar 23, 2015 at 2:23 PM, <span dir="ltr"><<a href="mailto:gopu@multicorewareinc.com" target="_blank">gopu@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Gopu Govindaswamy <<a href="mailto:gopu@multicorewareinc.com">gopu@multicorewareinc.com</a>><br>
# Date 1427100822 -19800<br>
# Mon Mar 23 14:23:42 2015 +0530<br>
# Node ID 02f1b991ed9d4d30ad6ec7a4eefca94d5347ceaa<br>
# Parent cc496665280f9e9e4776327e9a1cc1b2eeffecbc<br>
aq: implementation of fine-grained adaptive quantization<br>
<br>
Currently adaptive quantization adjusts the QP values on 64x64 pixel CodingTree<br>
units (CTUs) across a video frame. the new param option --max-dqp-depth will<br>
enable quantization parameter (QP) to be adjusted to individual quantization<br>
groups (QGs)<br>
<br>
diff -r cc496665280f -r 02f1b991ed9d source/common/cudata.cpp<br>
--- a/source/common/cudata.cpp Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/common/cudata.cpp Mon Mar 23 14:23:42 2015 +0530<br>
@@ -298,7 +298,7 @@<br>
}<br>
<br>
// initialize Sub partition<br>
-void CUData::initSubCU(const CUData& ctu, const CUGeom& cuGeom)<br>
+void CUData::initSubCU(const CUData& ctu, const CUGeom& cuGeom, int qp)<br>
{<br>
m_absIdxInCTU = cuGeom.absPartIdx;<br>
m_encData = ctu.m_encData;<br>
@@ -312,8 +312,11 @@<br>
m_cuAboveRight = ctu.m_cuAboveRight;<br>
X265_CHECK(m_numPartitions == cuGeom.numPartitions, "initSubCU() size mismatch\n");<br>
<br>
- /* sequential memsets */<br>
- m_partSet((uint8_t*)m_qp, (uint8_t)ctu.m_qp[0]);<br>
+ if (cuGeom.depth <= (uint32_t)m_encData->m_param->rc.maxCuDQPDepth && ctu.m_slice->m_pps->bUseDQP)<br>
+ m_partSet((uint8_t*)m_qp, (uint8_t)qp);<br>
+ else<br>
+ m_partSet((uint8_t*)m_qp, (uint8_t)ctu.m_qp[0]);<br>
+<br></blockquote><div>This was wrong. If the CU size is smaller than specified QG size, it should take the QP from the smallest QG CUSize, not parentCTU.m_qp[0]. I have fixed this in my commit. With this bug fix, I-frames improve seriously in quality, with lesser bits. Quality increase in P and B frames is less pronounced. <br></div><div><br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
m_partSet(m_log2CUSize, (uint8_t)cuGeom.log2CUSize);<br>
m_partSet(m_lumaIntraDir, (uint8_t)DC_IDX);<br>
m_partSet(m_tqBypass, (uint8_t)m_encData->m_param->bLossless);<br>
diff -r cc496665280f -r 02f1b991ed9d source/common/cudata.h<br>
--- a/source/common/cudata.h Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/common/cudata.h Mon Mar 23 14:23:42 2015 +0530<br>
@@ -182,7 +182,7 @@<br>
static void calcCTUGeoms(uint32_t ctuWidth, uint32_t ctuHeight, uint32_t maxCUSize, uint32_t minCUSize, CUGeom cuDataArray[CUGeom::MAX_GEOMS]);<br>
<br>
void initCTU(const Frame& frame, uint32_t cuAddr, int qp);<br>
- void initSubCU(const CUData& ctu, const CUGeom& cuGeom);<br>
+ void initSubCU(const CUData& ctu, const CUGeom& cuGeom, int qp);<br>
void initLosslessCU(const CUData& cu, const CUGeom& cuGeom);<br>
<br>
void copyPartFrom(const CUData& cu, const CUGeom& childGeom, uint32_t subPartIdx);<br>
diff -r cc496665280f -r 02f1b991ed9d source/common/param.cpp<br>
--- a/source/common/param.cpp Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/common/param.cpp Mon Mar 23 14:23:42 2015 +0530<br>
@@ -208,6 +208,7 @@<br>
param->rc.zones = NULL;<br>
param->rc.bEnableSlowFirstPass = 0;<br>
param->rc.bStrictCbr = 0;<br>
+ param->rc.maxCuDQPDepth = 0;<br>
<br>
/* Video Usability Information (VUI) */<br>
param->vui.aspectRatioIdc = 0;<br>
@@ -841,6 +842,7 @@<br>
OPT2("pools", "numa-pools") p->numaPools = strdup(value);<br>
OPT("lambda-file") p->rc.lambdaFileName = strdup(value);<br>
OPT("analysis-file") p->analysisFileName = strdup(value);<br>
+ OPT("max-dqp-depth") p->rc.maxCuDQPDepth = atoi(value);<br>
else<br>
return X265_PARAM_BAD_NAME;<br>
#undef OPT<br>
diff -r cc496665280f -r 02f1b991ed9d source/encoder/analysis.cpp<br>
--- a/source/encoder/analysis.cpp Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/encoder/analysis.cpp Mon Mar 23 14:23:42 2015 +0530<br>
@@ -225,6 +225,10 @@<br>
bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);<br>
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);<br>
<br>
+ int32_t qp = 0;<br>
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth && parentCTU.m_slice->m_pps->bUseDQP)<br>
+ qp = calculateQpforCuSize(parentCTU, cuGeom);<br>
+<br>
if (m_param->analysisMode == X265_ANALYSIS_LOAD)<br>
{<br>
uint8_t* reuseDepth = &m_reuseIntraDataCTU->depth[parentCTU.m_cuAddr * parentCTU.m_numPartitions];<br>
@@ -234,11 +238,10 @@<br>
<br>
if (mightNotSplit && depth == reuseDepth[zOrder] && zOrder == cuGeom.absPartIdx)<br>
{<br>
- m_quant.setQPforQuant(parentCTU);<br>
-<br>
PartSize size = (PartSize)reusePartSizes[zOrder];<br>
Mode& mode = size == SIZE_2Nx2N ? md.pred[PRED_INTRA] : md.pred[PRED_INTRA_NxN];<br>
- mode.cu.initSubCU(parentCTU, cuGeom);<br>
+ mode.cu.initSubCU(parentCTU, cuGeom, qp);<br>
+ m_quant.setQPforQuant(<a href="http://mode.cu" target="_blank">mode.cu</a>);<br>
checkIntra(mode, cuGeom, size, &reuseModes[zOrder], &reuseChromaModes[zOrder]);<br>
checkBestMode(mode, depth);<br>
<br>
@@ -255,15 +258,14 @@<br>
}<br>
else if (mightNotSplit)<br>
{<br>
- m_quant.setQPforQuant(parentCTU);<br>
-<br>
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);<br>
+ m_quant.setQPforQuant(md.pred[PRED_INTRA].cu);<br>
checkIntra(md.pred[PRED_INTRA], cuGeom, SIZE_2Nx2N, NULL, NULL);<br>
checkBestMode(md.pred[PRED_INTRA], depth);<br>
<br>
if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3)<br>
{<br>
- md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkIntra(md.pred[PRED_INTRA_NxN], cuGeom, SIZE_NxN, NULL, NULL);<br>
checkBestMode(md.pred[PRED_INTRA_NxN], depth);<br>
}<br>
@@ -280,7 +282,7 @@<br>
Mode* splitPred = &md.pred[PRED_SPLIT];<br>
splitPred->initCosts();<br>
CUData* splitCU = &splitPred->cu;<br>
- splitCU->initSubCU(parentCTU, cuGeom);<br>
+ splitCU->initSubCU(parentCTU, cuGeom, qp);<br>
<br>
uint32_t nextDepth = depth + 1;<br>
ModeDepth& nd = m_modeDepth[nextDepth];<br>
@@ -496,6 +498,10 @@<br>
<br>
X265_CHECK(m_param->rdLevel >= 2, "compressInterCU_dist does not support RD 0 or 1\n");<br>
<br>
+ int32_t qp = 0;<br>
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth)<br>
+ qp = calculateQpforCuSize(parentCTU, cuGeom);<br>
+<br>
if (mightNotSplit && depth >= minDepth)<br>
{<br>
int bTryAmp = m_slice->m_sps->maxAMPDepth > depth && (cuGeom.log2CUSize < 6 || m_param->rdLevel > 4);<br>
@@ -504,28 +510,28 @@<br>
PMODE pmode(*this, cuGeom);<br>
<br>
/* Initialize all prediction CUs based on parentCTU */<br>
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);<br>
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);<br>
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);<br>
if (bTryIntra)<br>
{<br>
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);<br>
if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3 && m_param->rdLevel >= 5)<br>
- md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);<br>
pmode.modes[pmode.m_jobTotal++] = PRED_INTRA;<br>
}<br>
- md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2Nx2N;<br>
- md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2Nx2N;<br>
+ md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom, qp);<br>
if (m_param->bEnableRectInter)<br>
{<br>
- md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2NxN;<br>
- md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_Nx2N;<br>
+ md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2NxN;<br>
+ md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_Nx2N;<br>
}<br>
if (bTryAmp)<br>
{<br>
- md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnU;<br>
- md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnD;<br>
- md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_nLx2N;<br>
- md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_nRx2N;<br>
+ md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnU;<br>
+ md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnD;<br>
+ md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_nLx2N;<br>
+ md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_nRx2N;<br>
}<br>
<br>
pmode.tryBondPeers(*m_frame->m_encData->m_jobProvider, pmode.m_jobTotal);<br>
@@ -654,7 +660,7 @@<br>
<br>
if (md.bestMode->rdCost == MAX_INT64 && !bTryIntra)<br>
{<br>
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkIntraInInter(md.pred[PRED_INTRA], cuGeom);<br>
encodeIntraInInter(md.pred[PRED_INTRA], cuGeom);<br>
checkBestMode(md.pred[PRED_INTRA], depth);<br>
@@ -680,7 +686,7 @@<br>
Mode* splitPred = &md.pred[PRED_SPLIT];<br>
splitPred->initCosts();<br>
CUData* splitCU = &splitPred->cu;<br>
- splitCU->initSubCU(parentCTU, cuGeom);<br>
+ splitCU->initSubCU(parentCTU, cuGeom, qp);<br>
<br>
uint32_t nextDepth = depth + 1;<br>
ModeDepth& nd = m_modeDepth[nextDepth];<br>
@@ -744,13 +750,17 @@<br>
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);<br>
uint32_t minDepth = topSkipMinDepth(parentCTU, cuGeom);<br>
<br>
+ int32_t qp = 0;<br>
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth && parentCTU.m_slice->m_pps->bUseDQP)<br>
+ qp = calculateQpforCuSize(parentCTU, cuGeom);<br>
+<br>
if (mightNotSplit && depth >= minDepth)<br>
{<br>
bool bTryIntra = m_slice->m_sliceType != B_SLICE || m_param->bIntraInBFrames;<br>
<br>
/* Compute Merge Cost */<br>
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);<br>
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);<br>
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkMerge2Nx2N_rd0_4(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom);<br>
<br>
bool earlyskip = false;<br>
@@ -759,24 +769,24 @@<br>
<br>
if (!earlyskip)<br>
{<br>
- md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd0_4(md.pred[PRED_2Nx2N], cuGeom, SIZE_2Nx2N);<br>
<br>
if (m_slice->m_sliceType == B_SLICE)<br>
{<br>
- md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkBidir2Nx2N(md.pred[PRED_2Nx2N], md.pred[PRED_BIDIR], cuGeom);<br>
}<br>
<br>
Mode *bestInter = &md.pred[PRED_2Nx2N];<br>
if (m_param->bEnableRectInter)<br>
{<br>
- md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd0_4(md.pred[PRED_Nx2N], cuGeom, SIZE_Nx2N);<br>
if (md.pred[PRED_Nx2N].sa8dCost < bestInter->sa8dCost)<br>
bestInter = &md.pred[PRED_Nx2N];<br>
<br>
- md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd0_4(md.pred[PRED_2NxN], cuGeom, SIZE_2NxN);<br>
if (md.pred[PRED_2NxN].sa8dCost < bestInter->sa8dCost)<br>
bestInter = &md.pred[PRED_2NxN];<br>
@@ -798,24 +808,24 @@<br>
<br>
if (bHor)<br>
{<br>
- md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd0_4(md.pred[PRED_2NxnU], cuGeom, SIZE_2NxnU);<br>
if (md.pred[PRED_2NxnU].sa8dCost < bestInter->sa8dCost)<br>
bestInter = &md.pred[PRED_2NxnU];<br>
<br>
- md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd0_4(md.pred[PRED_2NxnD], cuGeom, SIZE_2NxnD);<br>
if (md.pred[PRED_2NxnD].sa8dCost < bestInter->sa8dCost)<br>
bestInter = &md.pred[PRED_2NxnD];<br>
}<br>
if (bVer)<br>
{<br>
- md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd0_4(md.pred[PRED_nLx2N], cuGeom, SIZE_nLx2N);<br>
if (md.pred[PRED_nLx2N].sa8dCost < bestInter->sa8dCost)<br>
bestInter = &md.pred[PRED_nLx2N];<br>
<br>
- md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd0_4(md.pred[PRED_nRx2N], cuGeom, SIZE_nRx2N);<br>
if (md.pred[PRED_nRx2N].sa8dCost < bestInter->sa8dCost)<br>
bestInter = &md.pred[PRED_nRx2N];<br>
@@ -847,7 +857,7 @@<br>
if ((bTryIntra && md.bestMode->cu.getQtRootCbf(0)) ||<br>
md.bestMode->sa8dCost == MAX_INT64)<br>
{<br>
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkIntraInInter(md.pred[PRED_INTRA], cuGeom);<br>
encodeIntraInInter(md.pred[PRED_INTRA], cuGeom);<br>
checkBestMode(md.pred[PRED_INTRA], depth);<br>
@@ -865,7 +875,7 @@<br>
<br>
if (bTryIntra || md.bestMode->sa8dCost == MAX_INT64)<br>
{<br>
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkIntraInInter(md.pred[PRED_INTRA], cuGeom);<br>
if (md.pred[PRED_INTRA].sa8dCost < md.bestMode->sa8dCost)<br>
md.bestMode = &md.pred[PRED_INTRA];<br>
@@ -952,7 +962,7 @@<br>
Mode* splitPred = &md.pred[PRED_SPLIT];<br>
splitPred->initCosts();<br>
CUData* splitCU = &splitPred->cu;<br>
- splitCU->initSubCU(parentCTU, cuGeom);<br>
+ splitCU->initSubCU(parentCTU, cuGeom, qp);<br>
<br>
uint32_t nextDepth = depth + 1;<br>
ModeDepth& nd = m_modeDepth[nextDepth];<br>
@@ -1025,14 +1035,18 @@<br>
bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);<br>
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);<br>
<br>
+ int32_t qp = 0;<br>
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth && parentCTU.m_slice->m_pps->bUseDQP)<br>
+ qp = calculateQpforCuSize(parentCTU, cuGeom);<br>
+<br>
if (m_param->analysisMode == X265_ANALYSIS_LOAD)<br>
{<br>
uint8_t* reuseDepth = &m_reuseInterDataCTU->depth[parentCTU.m_cuAddr * parentCTU.m_numPartitions];<br>
uint8_t* reuseModes = &m_reuseInterDataCTU->modes[parentCTU.m_cuAddr * parentCTU.m_numPartitions];<br>
if (mightNotSplit && depth == reuseDepth[zOrder] && zOrder == cuGeom.absPartIdx && reuseModes[zOrder] == MODE_SKIP)<br>
{<br>
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);<br>
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);<br>
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkMerge2Nx2N_rd5_6(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom, true);<br>
<br>
if (m_bTryLossless)<br>
@@ -1051,20 +1065,20 @@<br>
<br>
if (mightNotSplit)<br>
{<br>
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);<br>
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);<br>
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkMerge2Nx2N_rd5_6(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom, false);<br>
bool earlySkip = m_param->bEnableEarlySkip && md.bestMode && !md.bestMode->cu.getQtRootCbf(0);<br>
<br>
if (!earlySkip)<br>
{<br>
- md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd5_6(md.pred[PRED_2Nx2N], cuGeom, SIZE_2Nx2N, false);<br>
checkBestMode(md.pred[PRED_2Nx2N], cuGeom.depth);<br>
<br>
if (m_slice->m_sliceType == B_SLICE)<br>
{<br>
- md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkBidir2Nx2N(md.pred[PRED_2Nx2N], md.pred[PRED_BIDIR], cuGeom);<br>
if (md.pred[PRED_BIDIR].sa8dCost < MAX_INT64)<br>
{<br>
@@ -1075,11 +1089,11 @@<br>
<br>
if (m_param->bEnableRectInter)<br>
{<br>
- md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd5_6(md.pred[PRED_Nx2N], cuGeom, SIZE_Nx2N, false);<br>
checkBestMode(md.pred[PRED_Nx2N], cuGeom.depth);<br>
<br>
- md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd5_6(md.pred[PRED_2NxN], cuGeom, SIZE_2NxN, false);<br>
checkBestMode(md.pred[PRED_2NxN], cuGeom.depth);<br>
}<br>
@@ -1102,21 +1116,21 @@<br>
<br>
if (bHor)<br>
{<br>
- md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd5_6(md.pred[PRED_2NxnU], cuGeom, SIZE_2NxnU, bMergeOnly);<br>
checkBestMode(md.pred[PRED_2NxnU], cuGeom.depth);<br>
<br>
- md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd5_6(md.pred[PRED_2NxnD], cuGeom, SIZE_2NxnD, bMergeOnly);<br>
checkBestMode(md.pred[PRED_2NxnD], cuGeom.depth);<br>
}<br>
if (bVer)<br>
{<br>
- md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd5_6(md.pred[PRED_nLx2N], cuGeom, SIZE_nLx2N, bMergeOnly);<br>
checkBestMode(md.pred[PRED_nLx2N], cuGeom.depth);<br>
<br>
- md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkInter_rd5_6(md.pred[PRED_nRx2N], cuGeom, SIZE_nRx2N, bMergeOnly);<br>
checkBestMode(md.pred[PRED_nRx2N], cuGeom.depth);<br>
}<br>
@@ -1124,13 +1138,13 @@<br>
<br>
if (m_slice->m_sliceType != B_SLICE || m_param->bIntraInBFrames)<br>
{<br>
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkIntra(md.pred[PRED_INTRA], cuGeom, SIZE_2Nx2N, NULL, NULL);<br>
checkBestMode(md.pred[PRED_INTRA], depth);<br>
<br>
if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3)<br>
{<br>
- md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom);<br>
+ md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);<br>
checkIntra(md.pred[PRED_INTRA_NxN], cuGeom, SIZE_NxN, NULL, NULL);<br>
checkBestMode(md.pred[PRED_INTRA_NxN], depth);<br>
}<br>
@@ -1150,7 +1164,7 @@<br>
Mode* splitPred = &md.pred[PRED_SPLIT];<br>
splitPred->initCosts();<br>
CUData* splitCU = &splitPred->cu;<br>
- splitCU->initSubCU(parentCTU, cuGeom);<br>
+ splitCU->initSubCU(parentCTU, cuGeom, qp);<br>
<br>
uint32_t nextDepth = depth + 1;<br>
ModeDepth& nd = m_modeDepth[nextDepth];<br>
@@ -1897,7 +1911,7 @@<br>
return false;<br>
}<br>
<br>
-int Analysis::calculateQpforCuSize(CUData& ctu, const CUGeom& cuGeom)<br>
+int Analysis::calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom)<br>
{<br>
uint32_t ctuAddr = ctu.m_cuAddr;<br>
FrameData& curEncData = *m_frame->m_encData;<br>
diff -r cc496665280f -r 02f1b991ed9d source/encoder/analysis.h<br>
--- a/source/encoder/analysis.h Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/encoder/analysis.h Mon Mar 23 14:23:42 2015 +0530<br>
@@ -139,7 +139,7 @@<br>
/* generate residual and recon pixels for an entire CTU recursively (RD0) */<br>
void encodeResidue(const CUData& parentCTU, const CUGeom& cuGeom);<br>
<br>
- int calculateQpforCuSize(CUData& ctu, const CUGeom& cuGeom);<br>
+ int calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom);<br>
<br>
/* check whether current mode is the new best */<br>
inline void checkBestMode(Mode& mode, uint32_t depth)<br>
diff -r cc496665280f -r 02f1b991ed9d source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/encoder/encoder.cpp Mon Mar 23 14:23:42 2015 +0530<br>
@@ -1557,15 +1557,11 @@<br>
bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;<br>
<br>
if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv))<br>
- {<br>
pps->bUseDQP = true;<br>
- pps->maxCuDQPDepth = 0; /* TODO: make configurable? */<br>
- }<br>
else<br>
- {<br>
pps->bUseDQP = false;<br>
- pps->maxCuDQPDepth = 0;<br>
- }<br>
+<br>
+ pps->maxCuDQPDepth = m_param->rc.maxCuDQPDepth;<br>
<br>
pps->chromaQpOffset[0] = m_param->cbQpOffset;<br>
pps->chromaQpOffset[1] = m_param->crQpOffset;<br>
@@ -1788,6 +1784,20 @@<br>
p->analysisMode = X265_ANALYSIS_OFF;<br>
x265_log(p, X265_LOG_WARNING, "Analysis save and load mode not supported for distributed mode analysis\n");<br>
}<br>
+ bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;<br>
+ if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv))<br>
+ {<br>
+ if (p->rc.maxCuDQPDepth > (int32_t)(g_maxCUDepth - 1))<br>
+ {<br>
+ p->rc.maxCuDQPDepth = 0;<br>
+ x265_log(p, X265_LOG_WARNING, "The maxCUDQPDepth should be less than (maxCUDepth - 1) setting maxCUDQPDepth = %d \n", 0);<br>
+ }<br>
+ }<br>
+ else<br>
+ {<br>
+ p->rc.maxCuDQPDepth = 0;<br>
+ x265_log(p, X265_LOG_WARNING, "The maxCUDQPDepth should be zero when vbv and aq Mode is disabled\n");<br>
+ }<br>
}<br>
<br>
void Encoder::allocAnalysis(x265_analysis_data* analysis)<br>
diff -r cc496665280f -r 02f1b991ed9d source/x265.h<br>
--- a/source/x265.h Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/x265.h Mon Mar 23 14:23:42 2015 +0530<br>
@@ -978,6 +978,12 @@<br>
/* Enable stricter conditions to check bitrate deviations in CBR mode. May compromise<br>
* quality to maintain bitrate adherence */<br>
int bStrictCbr;<br>
+<br>
+ /* the new param option --max-dqp-depth will enable adaptive quantization to adjusts the QP values<br>
+ * based on individual quantization groups (QGs), the QGs can be 64x64, 32x32 or 16x16 block<br>
+ * the default : 0, QPs are adjusted for 64x64 pixel Coding tree uint (CTU),<br>
+ * minimum is depth 0 and maximum is maxCUDepth - 1 */<br>
+ int maxCuDQPDepth;<br>
} rc;<br>
<br>
/*== Video Usability Information ==*/<br>
diff -r cc496665280f -r 02f1b991ed9d source/x265cli.h<br>
--- a/source/x265cli.h Sun Mar 22 22:16:45 2015 -0400<br>
+++ b/source/x265cli.h Mon Mar 23 14:23:42 2015 +0530<br>
@@ -204,6 +204,7 @@<br>
{ "strict-cbr", no_argument, NULL, 0 },<br>
{ "temporal-layers", no_argument, NULL, 0 },<br>
{ "no-temporal-layers", no_argument, NULL, 0 },<br>
+ { "max-dqp-depth", required_argument, NULL, 0 },<br>
{ 0, 0, 0, 0 },<br>
{ 0, 0, 0, 0 },<br>
{ 0, 0, 0, 0 },<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br></div></div>