[x265] [PATCH] aq: implementation of fine-grained adaptive quantization
Deepthi Nandakumar
deepthi at multicorewareinc.com
Thu Apr 2 18:51:19 CEST 2015
Just reviewed this patch, and made the following changes.
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.
2. Fixed all explanations, commit messages and param explanations
3. Fixed a bug explained below.
On Mon, Mar 23, 2015 at 2:23 PM, <gopu at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Gopu Govindaswamy <gopu at multicorewareinc.com>
> # Date 1427100822 -19800
> # Mon Mar 23 14:23:42 2015 +0530
> # Node ID 02f1b991ed9d4d30ad6ec7a4eefca94d5347ceaa
> # Parent cc496665280f9e9e4776327e9a1cc1b2eeffecbc
> 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 cc496665280f -r 02f1b991ed9d source/common/cudata.cpp
> --- a/source/common/cudata.cpp Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/common/cudata.cpp Mon Mar 23 14:23:42 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 &&
> ctu.m_slice->m_pps->bUseDQP)
> + m_partSet((uint8_t*)m_qp, (uint8_t)qp);
> + else
> + m_partSet((uint8_t*)m_qp, (uint8_t)ctu.m_qp[0]);
> +
>
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.
> 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 cc496665280f -r 02f1b991ed9d source/common/cudata.h
> --- a/source/common/cudata.h Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/common/cudata.h Mon Mar 23 14:23:42 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 cc496665280f -r 02f1b991ed9d source/common/param.cpp
> --- a/source/common/param.cpp Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/common/param.cpp Mon Mar 23 14:23:42 2015 +0530
> @@ -208,6 +208,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;
> @@ -841,6 +842,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 cc496665280f -r 02f1b991ed9d source/encoder/analysis.cpp
> --- a/source/encoder/analysis.cpp Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/encoder/analysis.cpp Mon Mar 23 14:23:42 2015 +0530
> @@ -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 &&
> parentCTU.m_slice->m_pps->bUseDQP)
> + 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,10 @@
>
> if (mightNotSplit && depth == reuseDepth[zOrder] && zOrder ==
> cuGeom.absPartIdx)
> {
> - m_quant.setQPforQuant(parentCTU);
> -
> 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);
> + m_quant.setQPforQuant(mode.cu);
> checkIntra(mode, cuGeom, size, &reuseModes[zOrder],
> &reuseChromaModes[zOrder]);
> checkBestMode(mode, depth);
>
> @@ -255,15 +258,14 @@
> }
> else if (mightNotSplit)
> {
> - m_quant.setQPforQuant(parentCTU);
> -
> - md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom);
> + md.pred[PRED_INTRA].cu.initSubCU(parentCTU, cuGeom, qp);
> + m_quant.setQPforQuant(md.pred[PRED_INTRA].cu);
> 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 +282,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];
> @@ -496,6 +498,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 +510,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 +660,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 +686,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 +750,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 &&
> parentCTU.m_slice->m_pps->bUseDQP)
> + 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 +769,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 +808,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 +857,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 +875,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];
> @@ -952,7 +962,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 +1035,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 &&
> parentCTU.m_slice->m_pps->bUseDQP)
> + 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 +1065,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 +1089,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 +1116,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 +1138,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 +1164,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];
> @@ -1897,7 +1911,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 cc496665280f -r 02f1b991ed9d source/encoder/analysis.h
> --- a/source/encoder/analysis.h Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/encoder/analysis.h Mon Mar 23 14:23:42 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 cc496665280f -r 02f1b991ed9d source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/encoder/encoder.cpp Mon Mar 23 14:23:42 2015 +0530
> @@ -1557,15 +1557,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;
> @@ -1788,6 +1784,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 cc496665280f -r 02f1b991ed9d source/x265.h
> --- a/source/x265.h Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/x265.h Mon Mar 23 14:23:42 2015 +0530
> @@ -978,6 +978,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 cc496665280f -r 02f1b991ed9d source/x265cli.h
> --- a/source/x265cli.h Sun Mar 22 22:16:45 2015 -0400
> +++ b/source/x265cli.h Mon Mar 23 14:23:42 2015 +0530
> @@ -204,6 +204,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 },
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20150402/14455ae9/attachment-0001.html>
More information about the x265-devel
mailing list