[x265] [PATCH] aq: implementation of fine-grained Adaptive Quantization
gopu at multicorewareinc.com
gopu at multicorewareinc.com
Tue Mar 17 12:29:34 CET 2015
# HG changeset patch
# User Gopu Govindaswamy <gopu at multicorewareinc.com>
# Date 1426591748 -19800
# Tue Mar 17 16:59:08 2015 +0530
# Node ID 2d05d87c145538851f6eead3cb7b038a7e93bdd1
# Parent b9948752d5516a72eeaf824e3ee6f0feb097381c
aq: implementation of fine-grained Adaptive Quantization
Currently adaptive quantization adjusts the QP values on 64x64 pixel CodingTree
units (CTUs) across a video frame. the new param option --max-dqp-depth will
enable quantization parameter (QP) to be adjusted to individual quantization
groups (QGs)
diff -r b9948752d551 -r 2d05d87c1455 source/common/cudata.cpp
--- a/source/common/cudata.cpp Mon Mar 16 20:40:12 2015 -0500
+++ b/source/common/cudata.cpp Tue Mar 17 16:59:08 2015 +0530
@@ -298,7 +298,7 @@
}
// initialize Sub partition
-void CUData::initSubCU(const CUData& ctu, const CUGeom& cuGeom)
+void CUData::initSubCU(const CUData& ctu, const CUGeom& cuGeom, int qp)
{
m_absIdxInCTU = cuGeom.absPartIdx;
m_encData = ctu.m_encData;
@@ -312,8 +312,11 @@
m_cuAboveRight = ctu.m_cuAboveRight;
X265_CHECK(m_numPartitions == cuGeom.numPartitions, "initSubCU() size mismatch\n");
- /* sequential memsets */
- m_partSet((uint8_t*)m_qp, (uint8_t)ctu.m_qp[0]);
+ if (cuGeom.depth <= (uint32_t)m_encData->m_param->rc.maxCuDQPDepth)
+ m_partSet((uint8_t*)m_qp, (uint8_t)qp);
+ else
+ m_partSet((uint8_t*)m_qp, (uint8_t)ctu.m_qp[0]);
+
m_partSet(m_log2CUSize, (uint8_t)cuGeom.log2CUSize);
m_partSet(m_lumaIntraDir, (uint8_t)DC_IDX);
m_partSet(m_tqBypass, (uint8_t)m_encData->m_param->bLossless);
diff -r b9948752d551 -r 2d05d87c1455 source/common/cudata.h
--- a/source/common/cudata.h Mon Mar 16 20:40:12 2015 -0500
+++ b/source/common/cudata.h Tue Mar 17 16:59:08 2015 +0530
@@ -182,7 +182,7 @@
static void calcCTUGeoms(uint32_t ctuWidth, uint32_t ctuHeight, uint32_t maxCUSize, uint32_t minCUSize, CUGeom cuDataArray[CUGeom::MAX_GEOMS]);
void initCTU(const Frame& frame, uint32_t cuAddr, int qp);
- void initSubCU(const CUData& ctu, const CUGeom& cuGeom);
+ void initSubCU(const CUData& ctu, const CUGeom& cuGeom, int qp);
void initLosslessCU(const CUData& cu, const CUGeom& cuGeom);
void copyPartFrom(const CUData& cu, const CUGeom& childGeom, uint32_t subPartIdx);
diff -r b9948752d551 -r 2d05d87c1455 source/common/param.cpp
--- a/source/common/param.cpp Mon Mar 16 20:40:12 2015 -0500
+++ b/source/common/param.cpp Tue Mar 17 16:59:08 2015 +0530
@@ -210,6 +210,7 @@
param->rc.zones = NULL;
param->rc.bEnableSlowFirstPass = 0;
param->rc.bStrictCbr = 0;
+ param->rc.maxCuDQPDepth = 0;
/* Video Usability Information (VUI) */
param->vui.aspectRatioIdc = 0;
@@ -839,6 +840,7 @@
OPT2("pools", "numa-pools") p->numaPools = strdup(value);
OPT("lambda-file") p->rc.lambdaFileName = strdup(value);
OPT("analysis-file") p->analysisFileName = strdup(value);
+ OPT("max-dqp-depth") p->rc.maxCuDQPDepth = atoi(value);
else
return X265_PARAM_BAD_NAME;
#undef OPT
diff -r b9948752d551 -r 2d05d87c1455 source/common/quant.cpp
--- a/source/common/quant.cpp Mon Mar 16 20:40:12 2015 -0500
+++ b/source/common/quant.cpp Tue Mar 17 16:59:08 2015 +0530
@@ -225,13 +225,13 @@
X265_FREE(m_fencShortBuf);
}
-void Quant::setQPforQuant(const CUData& cu)
+void Quant::setQPforQuant(const CUData& cu, const int qp)
{
m_tqBypass = !!cu.m_tqBypass[0];
if (m_tqBypass)
return;
m_nr = m_frameNr ? &m_frameNr[cu.m_encData->m_frameEncoderID] : NULL;
- int qpy = cu.m_qp[0];
+ int qpy = qp ? qp : cu.m_qp[0];
m_qpParam[TEXT_LUMA].setQpParam(qpy + QP_BD_OFFSET);
setChromaQP(qpy + cu.m_slice->m_pps->chromaQpOffset[0], TEXT_CHROMA_U, cu.m_chromaFormat);
setChromaQP(qpy + cu.m_slice->m_pps->chromaQpOffset[1], TEXT_CHROMA_V, cu.m_chromaFormat);
diff -r b9948752d551 -r 2d05d87c1455 source/common/quant.h
--- a/source/common/quant.h Mon Mar 16 20:40:12 2015 -0500
+++ b/source/common/quant.h Tue Mar 17 16:59:08 2015 +0530
@@ -103,7 +103,7 @@
bool allocNoiseReduction(const x265_param& param);
/* CU setup */
- void setQPforQuant(const CUData& cu);
+ void setQPforQuant(const CUData& cu, int qp);
uint32_t transformNxN(const CUData& cu, const pixel* fenc, uint32_t fencStride, const int16_t* residual, uint32_t resiStride, coeff_t* coeff,
uint32_t log2TrSize, TextType ttype, uint32_t absPartIdx, bool useTransformSkip);
diff -r b9948752d551 -r 2d05d87c1455 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp Mon Mar 16 20:40:12 2015 -0500
+++ b/source/encoder/analysis.cpp Tue Mar 17 16:59:08 2015 +0530
@@ -127,7 +127,7 @@
m_frame = &frame;
invalidateContexts(0);
- m_quant.setQPforQuant(ctu);
+ m_quant.setQPforQuant(ctu, 0);
m_rqt[0].cur.load(initialContext);
m_modeDepth[0].fencYuv.copyFromPicYuv(*m_frame->m_fencPic, ctu.m_cuAddr, 0);
@@ -225,6 +225,10 @@
bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
+ int32_t qp = 0;
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth)
+ qp = calculateQpforCuSize(parentCTU, cuGeom);
+
if (m_param->analysisMode == X265_ANALYSIS_LOAD)
{
uint8_t* reuseDepth = &m_reuseIntraDataCTU->depth[parentCTU.m_cuAddr * parentCTU.m_numPartitions];
@@ -234,11 +238,11 @@
if (mightNotSplit && depth == reuseDepth[zOrder] && zOrder == cuGeom.absPartIdx)
{
- m_quant.setQPforQuant(parentCTU);
+ m_quant.setQPforQuant(parentCTU, qp);
PartSize size = (PartSize)reusePartSizes[zOrder];
Mode& mode = size == SIZE_2Nx2N ? md.pred[PRED_INTRA] : md.pred[PRED_INTRA_NxN];
- mode.cu.initSubCU(parentCTU, cuGeom);
+ mode.cu.initSubCU(parentCTU, cuGeom, qp);
checkIntra(mode, cuGeom, size, &reuseModes[zOrder], &reuseChromaModes[zOrder]);
checkBestMode(mode, depth);
@@ -255,15 +259,15 @@
}
else if (mightNotSplit)
{
- m_quant.setQPforQuant(parentCTU);
+ m_quant.setQPforQuant(parentCTU, qp);
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);
checkIntra(md.pred[PRED_INTRA], cuGeom, SIZE_2Nx2N, NULL, NULL);
checkBestMode(md.pred[PRED_INTRA], depth);
if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3)
{
- md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);
checkIntra(md.pred[PRED_INTRA_NxN], cuGeom, SIZE_NxN, NULL, NULL);
checkBestMode(md.pred[PRED_INTRA_NxN], depth);
}
@@ -280,7 +284,7 @@
Mode* splitPred = &md.pred[PRED_SPLIT];
splitPred->initCosts();
CUData* splitCU = &splitPred->cu;
- splitCU->initSubCU(parentCTU, cuGeom);
+ splitCU->initSubCU(parentCTU, cuGeom, qp);
uint32_t nextDepth = depth + 1;
ModeDepth& nd = m_modeDepth[nextDepth];
@@ -368,7 +372,7 @@
if (m_param->rdLevel >= 5)
{
slave.m_rqt[pmode.cuGeom.depth].cur.load(m_rqt[pmode.cuGeom.depth].cur);
- slave.m_quant.setQPforQuant(md.pred[PRED_2Nx2N].cu);
+ slave.m_quant.setQPforQuant(md.pred[PRED_2Nx2N].cu, 0);
}
}
@@ -496,6 +500,10 @@
X265_CHECK(m_param->rdLevel >= 2, "compressInterCU_dist does not support RD 0 or 1\n");
+ int32_t qp = 0;
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth)
+ qp = calculateQpforCuSize(parentCTU, cuGeom);
+
if (mightNotSplit && depth >= minDepth)
{
int bTryAmp = m_slice->m_sps->maxAMPDepth > depth && (cuGeom.log2CUSize < 6 || m_param->rdLevel > 4);
@@ -504,28 +512,28 @@
PMODE pmode(*this, cuGeom);
/* Initialize all prediction CUs based on parentCTU */
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);
if (bTryIntra)
{
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);
if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3 && m_param->rdLevel >= 5)
- md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);
pmode.modes[pmode.m_jobTotal++] = PRED_INTRA;
}
- md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2Nx2N;
- md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2Nx2N;
+ md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom, qp);
if (m_param->bEnableRectInter)
{
- md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2NxN;
- md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_Nx2N;
+ md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2NxN;
+ md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_Nx2N;
}
if (bTryAmp)
{
- md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnU;
- md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnD;
- md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_nLx2N;
- md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom); pmode.modes[pmode.m_jobTotal++] = PRED_nRx2N;
+ md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnU;
+ md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_2NxnD;
+ md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_nLx2N;
+ md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom, qp); pmode.modes[pmode.m_jobTotal++] = PRED_nRx2N;
}
pmode.tryBondPeers(*m_frame->m_encData->m_jobProvider, pmode.m_jobTotal);
@@ -654,7 +662,7 @@
if (md.bestMode->rdCost == MAX_INT64 && !bTryIntra)
{
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);
checkIntraInInter(md.pred[PRED_INTRA], cuGeom);
encodeIntraInInter(md.pred[PRED_INTRA], cuGeom);
checkBestMode(md.pred[PRED_INTRA], depth);
@@ -680,7 +688,7 @@
Mode* splitPred = &md.pred[PRED_SPLIT];
splitPred->initCosts();
CUData* splitCU = &splitPred->cu;
- splitCU->initSubCU(parentCTU, cuGeom);
+ splitCU->initSubCU(parentCTU, cuGeom, qp);
uint32_t nextDepth = depth + 1;
ModeDepth& nd = m_modeDepth[nextDepth];
@@ -744,13 +752,17 @@
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
uint32_t minDepth = topSkipMinDepth(parentCTU, cuGeom);
+ int32_t qp = 0;
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth)
+ qp = calculateQpforCuSize(parentCTU, cuGeom);
+
if (mightNotSplit && depth >= minDepth)
{
bool bTryIntra = m_slice->m_sliceType != B_SLICE || m_param->bIntraInBFrames;
/* Compute Merge Cost */
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);
+ 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);
bool earlyskip = false;
@@ -759,24 +771,24 @@
if (!earlyskip)
{
- md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd0_4(md.pred[PRED_2Nx2N], cuGeom, SIZE_2Nx2N);
if (m_slice->m_sliceType == B_SLICE)
{
- md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom, qp);
checkBidir2Nx2N(md.pred[PRED_2Nx2N], md.pred[PRED_BIDIR], cuGeom);
}
Mode *bestInter = &md.pred[PRED_2Nx2N];
if (m_param->bEnableRectInter)
{
- md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd0_4(md.pred[PRED_Nx2N], cuGeom, SIZE_Nx2N);
if (md.pred[PRED_Nx2N].sa8dCost < bestInter->sa8dCost)
bestInter = &md.pred[PRED_Nx2N];
- md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd0_4(md.pred[PRED_2NxN], cuGeom, SIZE_2NxN);
if (md.pred[PRED_2NxN].sa8dCost < bestInter->sa8dCost)
bestInter = &md.pred[PRED_2NxN];
@@ -798,24 +810,24 @@
if (bHor)
{
- md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd0_4(md.pred[PRED_2NxnU], cuGeom, SIZE_2NxnU);
if (md.pred[PRED_2NxnU].sa8dCost < bestInter->sa8dCost)
bestInter = &md.pred[PRED_2NxnU];
- md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd0_4(md.pred[PRED_2NxnD], cuGeom, SIZE_2NxnD);
if (md.pred[PRED_2NxnD].sa8dCost < bestInter->sa8dCost)
bestInter = &md.pred[PRED_2NxnD];
}
if (bVer)
{
- md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd0_4(md.pred[PRED_nLx2N], cuGeom, SIZE_nLx2N);
if (md.pred[PRED_nLx2N].sa8dCost < bestInter->sa8dCost)
bestInter = &md.pred[PRED_nLx2N];
- md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd0_4(md.pred[PRED_nRx2N], cuGeom, SIZE_nRx2N);
if (md.pred[PRED_nRx2N].sa8dCost < bestInter->sa8dCost)
bestInter = &md.pred[PRED_nRx2N];
@@ -847,7 +859,7 @@
if ((bTryIntra && md.bestMode->cu.getQtRootCbf(0)) ||
md.bestMode->sa8dCost == MAX_INT64)
{
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);
checkIntraInInter(md.pred[PRED_INTRA], cuGeom);
encodeIntraInInter(md.pred[PRED_INTRA], cuGeom);
checkBestMode(md.pred[PRED_INTRA], depth);
@@ -865,7 +877,7 @@
if (bTryIntra || md.bestMode->sa8dCost == MAX_INT64)
{
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);
checkIntraInInter(md.pred[PRED_INTRA], cuGeom);
if (md.pred[PRED_INTRA].sa8dCost < md.bestMode->sa8dCost)
md.bestMode = &md.pred[PRED_INTRA];
@@ -893,7 +905,7 @@
{
/* generate recon pixels with no rate distortion considerations */
CUData& cu = md.bestMode->cu;
- m_quant.setQPforQuant(cu);
+ m_quant.setQPforQuant(cu, qp);
uint32_t tuDepthRange[2];
cu.getInterTUQtDepthRange(tuDepthRange, 0);
@@ -918,7 +930,7 @@
{
/* generate recon pixels with no rate distortion considerations */
CUData& cu = md.bestMode->cu;
- m_quant.setQPforQuant(cu);
+ m_quant.setQPforQuant(cu, qp);
uint32_t tuDepthRange[2];
cu.getIntraTUQtDepthRange(tuDepthRange, 0);
@@ -952,7 +964,7 @@
Mode* splitPred = &md.pred[PRED_SPLIT];
splitPred->initCosts();
CUData* splitCU = &splitPred->cu;
- splitCU->initSubCU(parentCTU, cuGeom);
+ splitCU->initSubCU(parentCTU, cuGeom, qp);
uint32_t nextDepth = depth + 1;
ModeDepth& nd = m_modeDepth[nextDepth];
@@ -1025,14 +1037,18 @@
bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
+ int32_t qp = 0;
+ if (depth <= (uint32_t)m_param->rc.maxCuDQPDepth)
+ qp = calculateQpforCuSize(parentCTU, cuGeom);
+
if (m_param->analysisMode == X265_ANALYSIS_LOAD)
{
uint8_t* reuseDepth = &m_reuseInterDataCTU->depth[parentCTU.m_cuAddr * parentCTU.m_numPartitions];
uint8_t* reuseModes = &m_reuseInterDataCTU->modes[parentCTU.m_cuAddr * parentCTU.m_numPartitions];
if (mightNotSplit && depth == reuseDepth[zOrder] && zOrder == cuGeom.absPartIdx && reuseModes[zOrder] == MODE_SKIP)
{
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
checkMerge2Nx2N_rd5_6(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom, true);
if (m_bTryLossless)
@@ -1051,20 +1067,20 @@
if (mightNotSplit)
{
- md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom);
- md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);
+ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
checkMerge2Nx2N_rd5_6(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom, false);
bool earlySkip = m_param->bEnableEarlySkip && md.bestMode && !md.bestMode->cu.getQtRootCbf(0);
if (!earlySkip)
{
- md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd5_6(md.pred[PRED_2Nx2N], cuGeom, SIZE_2Nx2N, false);
checkBestMode(md.pred[PRED_2Nx2N], cuGeom.depth);
if (m_slice->m_sliceType == B_SLICE)
{
- md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_BIDIR].cu.initSubCU(parentCTU, cuGeom, qp);
checkBidir2Nx2N(md.pred[PRED_2Nx2N], md.pred[PRED_BIDIR], cuGeom);
if (md.pred[PRED_BIDIR].sa8dCost < MAX_INT64)
{
@@ -1075,11 +1091,11 @@
if (m_param->bEnableRectInter)
{
- md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_Nx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd5_6(md.pred[PRED_Nx2N], cuGeom, SIZE_Nx2N, false);
checkBestMode(md.pred[PRED_Nx2N], cuGeom.depth);
- md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2NxN].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd5_6(md.pred[PRED_2NxN], cuGeom, SIZE_2NxN, false);
checkBestMode(md.pred[PRED_2NxN], cuGeom.depth);
}
@@ -1102,21 +1118,21 @@
if (bHor)
{
- md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2NxnU].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd5_6(md.pred[PRED_2NxnU], cuGeom, SIZE_2NxnU, bMergeOnly);
checkBestMode(md.pred[PRED_2NxnU], cuGeom.depth);
- md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_2NxnD].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd5_6(md.pred[PRED_2NxnD], cuGeom, SIZE_2NxnD, bMergeOnly);
checkBestMode(md.pred[PRED_2NxnD], cuGeom.depth);
}
if (bVer)
{
- md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_nLx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd5_6(md.pred[PRED_nLx2N], cuGeom, SIZE_nLx2N, bMergeOnly);
checkBestMode(md.pred[PRED_nLx2N], cuGeom.depth);
- md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_nRx2N].cu.initSubCU(parentCTU, cuGeom, qp);
checkInter_rd5_6(md.pred[PRED_nRx2N], cuGeom, SIZE_nRx2N, bMergeOnly);
checkBestMode(md.pred[PRED_nRx2N], cuGeom.depth);
}
@@ -1124,13 +1140,13 @@
if (m_slice->m_sliceType != B_SLICE || m_param->bIntraInBFrames)
{
- md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);
checkIntra(md.pred[PRED_INTRA], cuGeom, SIZE_2Nx2N, NULL, NULL);
checkBestMode(md.pred[PRED_INTRA], depth);
if (cuGeom.log2CUSize == 3 && m_slice->m_sps->quadtreeTULog2MinSize < 3)
{
- md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom);
+ md.pred[PRED_INTRA_NxN].cu.initSubCU(parentCTU, cuGeom, qp);
checkIntra(md.pred[PRED_INTRA_NxN], cuGeom, SIZE_NxN, NULL, NULL);
checkBestMode(md.pred[PRED_INTRA_NxN], depth);
}
@@ -1150,7 +1166,7 @@
Mode* splitPred = &md.pred[PRED_SPLIT];
splitPred->initCosts();
CUData* splitCU = &splitPred->cu;
- splitCU->initSubCU(parentCTU, cuGeom);
+ splitCU->initSubCU(parentCTU, cuGeom, qp);
uint32_t nextDepth = depth + 1;
ModeDepth& nd = m_modeDepth[nextDepth];
@@ -1681,7 +1697,7 @@
CUData& cu = bestMode->cu;
cu.copyFromPic(ctu, cuGeom);
- m_quant.setQPforQuant(cu);
+ m_quant.setQPforQuant(cu, 0);
Yuv& fencYuv = m_modeDepth[cuGeom.depth].fencYuv;
if (cuGeom.depth)
@@ -1897,7 +1913,7 @@
return false;
}
-int Analysis::calculateQpforCuSize(CUData& ctu, const CUGeom& cuGeom)
+int Analysis::calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom)
{
uint32_t ctuAddr = ctu.m_cuAddr;
FrameData& curEncData = *m_frame->m_encData;
diff -r b9948752d551 -r 2d05d87c1455 source/encoder/analysis.h
--- a/source/encoder/analysis.h Mon Mar 16 20:40:12 2015 -0500
+++ b/source/encoder/analysis.h Tue Mar 17 16:59:08 2015 +0530
@@ -139,7 +139,7 @@
/* generate residual and recon pixels for an entire CTU recursively (RD0) */
void encodeResidue(const CUData& parentCTU, const CUGeom& cuGeom);
- int calculateQpforCuSize(CUData& ctu, const CUGeom& cuGeom);
+ int calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom);
/* check whether current mode is the new best */
inline void checkBestMode(Mode& mode, uint32_t depth)
diff -r b9948752d551 -r 2d05d87c1455 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Mon Mar 16 20:40:12 2015 -0500
+++ b/source/encoder/encoder.cpp Tue Mar 17 16:59:08 2015 +0530
@@ -1551,15 +1551,11 @@
bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv))
- {
pps->bUseDQP = true;
- pps->maxCuDQPDepth = 0; /* TODO: make configurable? */
- }
else
- {
pps->bUseDQP = false;
- pps->maxCuDQPDepth = 0;
- }
+
+ pps->maxCuDQPDepth = m_param->rc.maxCuDQPDepth;
pps->chromaQpOffset[0] = m_param->cbQpOffset;
pps->chromaQpOffset[1] = m_param->crQpOffset;
@@ -1778,6 +1774,20 @@
p->analysisMode = X265_ANALYSIS_OFF;
x265_log(p, X265_LOG_WARNING, "Analysis save and load mode not supported for distributed mode analysis\n");
}
+ bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
+ if (!m_param->bLossless && (m_param->rc.aqMode || bIsVbv))
+ {
+ if (p->rc.maxCuDQPDepth > (int32_t)(g_maxCUDepth - 1))
+ {
+ p->rc.maxCuDQPDepth = 0;
+ x265_log(p, X265_LOG_WARNING, "The maxCUDQPDepth should be less than (maxCUDepth - 1) setting maxCUDQPDepth = %d \n", 0);
+ }
+ }
+ else
+ {
+ p->rc.maxCuDQPDepth = 0;
+ x265_log(p, X265_LOG_WARNING, "The maxCUDQPDepth should be zero when vbv and aq Mode is disabled\n");
+ }
}
void Encoder::allocAnalysis(x265_analysis_data* analysis)
diff -r b9948752d551 -r 2d05d87c1455 source/encoder/search.cpp
--- a/source/encoder/search.cpp Mon Mar 16 20:40:12 2015 -0500
+++ b/source/encoder/search.cpp Tue Mar 17 16:59:08 2015 +0530
@@ -1368,7 +1368,7 @@
X265_CHECK(cu.m_partSize[0] == SIZE_2Nx2N, "encodeIntraInInter does not expect NxN intra\n");
X265_CHECK(!m_slice->isIntra(), "encodeIntraInInter does not expect to be used in I slices\n");
- m_quant.setQPforQuant(cu);
+ m_quant.setQPforQuant(cu, 0);
uint32_t tuDepthRange[2];
cu.getIntraTUQtDepthRange(tuDepthRange, 0);
@@ -2534,7 +2534,7 @@
int sizeIdx = log2CUSize - 2;
uint32_t tqBypass = cu.m_tqBypass[0];
- m_quant.setQPforQuant(interMode.cu);
+ m_quant.setQPforQuant(interMode.cu, 0);
resiYuv->subtract(*fencYuv, *predYuv, log2CUSize);
diff -r b9948752d551 -r 2d05d87c1455 source/x265.h
--- a/source/x265.h Mon Mar 16 20:40:12 2015 -0500
+++ b/source/x265.h Tue Mar 17 16:59:08 2015 +0530
@@ -977,6 +977,12 @@
/* Enable stricter conditions to check bitrate deviations in CBR mode. May compromise
* quality to maintain bitrate adherence */
int bStrictCbr;
+
+ /* the new param option --max-dqp-depth will enable adaptive quantization to adjusts the QP values
+ * based on individual quantization groups (QGs), the QGs can be 64x64, 32x32 or 16x16 block
+ * the default : 0, QPs are adjusted for 64x64 pixel Coding tree uint (CTU),
+ * minimum is depth 0 and maximum is maxCUDepth - 1 */
+ int maxCuDQPDepth;
} rc;
/*== Video Usability Information ==*/
diff -r b9948752d551 -r 2d05d87c1455 source/x265cli.h
--- a/source/x265cli.h Mon Mar 16 20:40:12 2015 -0500
+++ b/source/x265cli.h Tue Mar 17 16:59:08 2015 +0530
@@ -202,6 +202,7 @@
{ "strict-cbr", no_argument, NULL, 0 },
{ "temporal-layers", no_argument, NULL, 0 },
{ "no-temporal-layers", no_argument, NULL, 0 },
+ { "max-dqp-depth", required_argument, NULL, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
More information about the x265-devel
mailing list