[x265] [PATCH] aq: implementation of fine-grained adaptive quantization
Steve Borho
steve at borho.org
Tue Mar 24 15:29:20 CET 2015
On 03/23, 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)
I have this flagged so I don't forget it, but I'm not going to review
output changing patches until the regression tests run clean.
> 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]);
> +
> 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
--
Steve Borho
More information about the x265-devel
mailing list