# HG changeset patch # User Aruna Matheswaran <ar...@multicorewareinc.com> # Date 1576499107 -19800 # Mon Dec 16 17:55:07 2019 +0530 # Node ID 4d870dd7c314334b27413de922d08d9c01d5860b # Parent 52135ffd9bcdd32b944311e9e66c473894c0a2bd De-couple analysis reuse levels of --analysis-save and --analysis-load.
Currently, analysis reuse level of the load encode has to be the same as that of the reuse level of the save encode. This commit de-couples the reuse level constraints and let the load encode re-use a subset of the available analysis info. Two CLI and x265_param options are introduced to get the desired reuse level during save and load. The existing option --analysis-reuse-level is deprecated. diff -r 52135ffd9bcd -r 4d870dd7c314 doc/reST/cli.rst --- a/doc/reST/cli.rst Mon Dec 23 14:40:32 2019 +0530 +++ b/doc/reST/cli.rst Mon Dec 16 17:55:07 2019 +0530 @@ -918,12 +918,14 @@ Specify a filename for `multi-pass-opt-analysis` and `multi-pass-opt-distortion`. If no filename is specified, x265_analysis.dat is used. -.. option:: --analysis-reuse-level <1..10> - - Amount of information stored/reused in :option:`--analysis-reuse-mode` is distributed across levels. +.. option:: --analysis-save-reuse-level <1..10>, --analysis-load-reuse-level <1..10> + + :option:`--analysis-save-reuse-level` denotes the amount of information stored during :option:`--analysis-save` and + :option:`--analysis-load-reuse-level` denotes the amount of information reused during :option:`--analysis-load`. Higher the value, higher the information stored/reused, faster the encode. Default 5. - Note that --analysis-reuse-level must be paired with analysis-reuse-mode. + Note that :option:`--analysis-save-reuse-level` and :option:`--analysis-load-reuse-level` must be paired + with :option:`--analysis-save` and :option:`--analysis-load` respectively. +--------------+------------------------------------------+ | Level | Description | diff -r 52135ffd9bcd -r 4d870dd7c314 source/CMakeLists.txt --- a/source/CMakeLists.txt Mon Dec 23 14:40:32 2019 +0530 +++ b/source/CMakeLists.txt Mon Dec 16 17:55:07 2019 +0530 @@ -29,7 +29,7 @@ option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF) mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD) # X265_BUILD must be incremented each time the public API is changed -set(X265_BUILD 184) +set(X265_BUILD 185) configure_file("${PROJECT_SOURCE_DIR}/x265.def.in" "${PROJECT_BINARY_DIR}/x265.def") configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in" diff -r 52135ffd9bcd -r 4d870dd7c314 source/common/param.cpp --- a/source/common/param.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/common/param.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -319,7 +319,9 @@ param->bOptCUDeltaQP = 0; param->bAQMotion = 0; param->bHDROpt = 0; - param->analysisReuseLevel = 5; + param->analysisReuseLevel = 0; /*DEPRECATED*/ + param->analysisSaveReuseLevel = 0; + param->analysisLoadReuseLevel = 0; param->toneMapFile = NULL; param->bDhdr10opt = 0; param->dolbyProfile = 0; @@ -1219,7 +1221,14 @@ OPT("multi-pass-opt-distortion") p->analysisMultiPassDistortion = atobool(value); OPT("aq-motion") p->bAQMotion = atobool(value); OPT("dynamic-rd") p->dynamicRd = atof(value); - OPT("analysis-reuse-level") p->analysisReuseLevel = atoi(value); + OPT("analysis-reuse-level") + { + p->analysisReuseLevel = atoi(value); + p->analysisSaveReuseLevel = atoi(value); + p->analysisLoadReuseLevel = atoi(value); + } + OPT("analysis-save-reuse-level") p->analysisSaveReuseLevel = atoi(value); + OPT("analysis-load-reuse-level") p->analysisLoadReuseLevel = atoi(value); OPT("ssim-rd") { int bval = atobool(value); @@ -1260,7 +1269,7 @@ } else if (strcmp(strdup(value), "off") == 0) { - p->bAnalysisType = NO_INFO; + p->bAnalysisType = DEFAULT; } else { @@ -1696,8 +1705,10 @@ "Constant QP is incompatible with 2pass"); CHECK(param->rc.bStrictCbr && (param->rc.bitrate <= 0 || param->rc.vbvBufferSize <=0), "Strict-cbr cannot be applied without specifying target bitrate or vbv bufsize"); - CHECK((param->analysisSave || param->analysisLoad) && (param->analysisReuseLevel < 1 || param->analysisReuseLevel > 10), - "Invalid analysis refine level. Value must be between 1 and 10 (inclusive)"); + CHECK(param->analysisSave && (param->analysisSaveReuseLevel < 1 || param->analysisSaveReuseLevel > 10), + "Invalid analysis save refine level. Value must be between 1 and 10 (inclusive)"); + CHECK(param->analysisLoad && (param->analysisLoadReuseLevel < 1 || param->analysisLoadReuseLevel > 10), + "Invalid analysis load refine level. Value must be between 1 and 10 (inclusive)"); CHECK(param->analysisLoad && (param->mvRefine < 1 || param->mvRefine > 3), "Invalid mv refinement level. Value must be between 1 and 3 (inclusive)"); CHECK(param->scaleFactor > 2, "Invalid scale-factor. Supports factor <= 2"); @@ -2160,6 +2171,8 @@ if (p->analysisLoad) s += sprintf(s, " analysis-load"); s += sprintf(s, " analysis-reuse-level=%d", p->analysisReuseLevel); + s += sprintf(s, " analysis-save-reuse-level=%d", p->analysisSaveReuseLevel); + s += sprintf(s, " analysis-load-reuse-level=%d", p->analysisLoadReuseLevel); s += sprintf(s, " scale-factor=%d", p->scaleFactor); s += sprintf(s, " refine-intra=%d", p->intraRefine); s += sprintf(s, " refine-inter=%d", p->interRefine); @@ -2477,6 +2490,8 @@ dst->bEmitHRDSEI = src->bEmitHRDSEI; dst->bHDROpt = src->bHDROpt; dst->analysisReuseLevel = src->analysisReuseLevel; + dst->analysisSaveReuseLevel = src->analysisSaveReuseLevel; + dst->analysisLoadReuseLevel = src->analysisLoadReuseLevel; dst->bLimitSAO = src->bLimitSAO; if (src->toneMapFile) dst->toneMapFile = strdup(src->toneMapFile); else dst->toneMapFile = NULL; diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/analysis.cpp --- a/source/encoder/analysis.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/analysis.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -202,14 +202,17 @@ m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions]; } - if ((m_param->analysisSave || m_param->analysisLoad) && m_slice->m_sliceType != I_SLICE && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel < 10) + int reuseLevel = X265_MAX(m_param->analysisSaveReuseLevel, m_param->analysisLoadReuseLevel); + if ((m_param->analysisSave || m_param->analysisLoad) && m_slice->m_sliceType != I_SLICE && reuseLevel > 1 && reuseLevel < 10) { int numPredDir = m_slice->isInterP() ? 1 : 2; m_reuseInterDataCTU = m_frame->m_analysisData.interData; - m_reuseRef = &m_reuseInterDataCTU->ref [ctu.m_cuAddr * X265_MAX_PRED_MODE_PER_CTU * numPredDir]; + if (((m_param->analysisSaveReuseLevel > 1) && (m_param->analysisSaveReuseLevel < 7)) || + ((m_param->analysisLoadReuseLevel > 1) && (m_param->analysisLoadReuseLevel < 7))) + m_reuseRef = &m_reuseInterDataCTU->ref[ctu.m_cuAddr * X265_MAX_PRED_MODE_PER_CTU * numPredDir]; m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions]; m_reuseModes = &m_reuseInterDataCTU->modes[ctu.m_cuAddr * ctu.m_numPartitions]; - if (m_param->analysisReuseLevel > 4) + if (reuseLevel > 4) { m_reusePartSize = &m_reuseInterDataCTU->partSize[ctu.m_cuAddr * ctu.m_numPartitions]; m_reuseMergeFlag = &m_reuseInterDataCTU->mergeFlag[ctu.m_cuAddr * ctu.m_numPartitions]; @@ -223,7 +226,7 @@ if (m_slice->m_sliceType == I_SLICE) { x265_analysis_intra_data* intraDataCTU = m_frame->m_analysisData.intraData; - if (m_param->analysisLoad && m_param->analysisReuseLevel > 1) + if (m_param->analysisLoadReuseLevel > 1) { memcpy(ctu.m_cuDepth, &intraDataCTU->depth[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition); memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition); @@ -234,9 +237,9 @@ } else { - bool bCopyAnalysis = ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)); - bool BCompressInterCUrd0_4 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel <= 4); - bool BCompressInterCUrd5_6 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel >= 5 && m_param->rdLevel <= 6); + bool bCopyAnalysis = ((m_param->analysisLoadReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7 && ctu.m_numPartitions <= 16)); + bool BCompressInterCUrd0_4 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7 && m_param->rdLevel <= 4); + bool BCompressInterCUrd5_6 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7 && m_param->rdLevel >= 5 && m_param->rdLevel <= 6); bCopyAnalysis = bCopyAnalysis || BCompressInterCUrd0_4 || BCompressInterCUrd5_6; if (bCopyAnalysis) @@ -275,8 +278,8 @@ /* generate residual for entire CTU at once and copy to reconPic */ encodeResidue(ctu, cuGeom); } - else if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10 && (!(m_param->bAnalysisType == HEVC_INFO) || m_slice->m_sliceType != P_SLICE)) || - ((m_param->bAnalysisType == AVC_INFO) && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)) + else if ((m_param->analysisLoadReuseLevel == 10 && (!(m_param->bAnalysisType == HEVC_INFO) || m_slice->m_sliceType != P_SLICE)) || + ((m_param->bAnalysisType == AVC_INFO) && m_param->analysisLoadReuseLevel >= 7 && ctu.m_numPartitions <= 16)) { x265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData; int posCTU = ctu.m_cuAddr * numPartition; @@ -456,7 +459,7 @@ int bestCUQP = qp; int lambdaQP = lqp; bool doQPRefine = (bDecidedDepth && depth <= m_slice->m_pps->maxCuDQPDepth) || (!bDecidedDepth && depth == m_slice->m_pps->maxCuDQPDepth); - if (m_param->analysisReuseLevel >= 7) + if (m_param->analysisLoadReuseLevel >= 7) doQPRefine = false; if (doQPRefine) { @@ -1164,7 +1167,7 @@ SplitData splitCUData; bool bHEVCBlockAnalysis = (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions > 16); - bool bRefineAVCAnalysis = (m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); + bool bRefineAVCAnalysis = (m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); bool bNooffloading = !(m_param->bAnalysisType == AVC_INFO); if (bHEVCBlockAnalysis || bRefineAVCAnalysis || bNooffloading) @@ -1259,7 +1262,7 @@ mightSplit &= !bDecidedDepth; } } - if ((m_param->analysisLoad && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10)) + if ((m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10)) { if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx]) { @@ -1273,7 +1276,7 @@ if (m_param->rdLevel) skipModes = m_param->bEnableEarlySkip && md.bestMode; } - if (m_param->analysisReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) + if (m_param->analysisLoadReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) { if (m_reuseModes[cuGeom.absPartIdx] != MODE_INTRA && m_reuseModes[cuGeom.absPartIdx] != 4) { @@ -1300,7 +1303,8 @@ } } /* Step 1. Evaluate Merge/Skip candidates for likely early-outs, if skip mode was not set above */ - if ((mightNotSplit && depth >= minDepth && !md.bestMode && !bCtuInfoCheck) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) /* TODO: Re-evaluate if analysis load/save still works */ + if ((mightNotSplit && depth >= minDepth && !md.bestMode && !bCtuInfoCheck) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + /* TODO: Re-evaluate if analysis load/save still works */ { /* Compute Merge Cost */ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp); @@ -1310,7 +1314,7 @@ skipModes = (m_param->bEnableEarlySkip || m_refineLevel == 2) && md.bestMode && md.bestMode->cu.isSkipped(0); // TODO: sa8d threshold per depth } - if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck && !(m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck && !(m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) { skipRecursion = md.bestMode->cu.isSkipped(0); if (mightSplit && depth >= minDepth && !skipRecursion) @@ -1321,7 +1325,7 @@ skipRecursion = complexityCheckCU(*md.bestMode); } } - if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisLoadReuseLevel == 7) skipRecursion = true; /* Step 2. Evaluate each of the 4 split sub-blocks in series */ if (mightSplit && !skipRecursion) @@ -1378,7 +1382,7 @@ splitPred->sa8dCost = m_rdCost.calcRdSADCost((uint32_t)splitPred->distortion, splitPred->sa8dBits); } /* If analysis mode is simple do not Evaluate other modes */ - if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7) { if (m_slice->m_sliceType == P_SLICE) { @@ -1857,7 +1861,7 @@ SplitData splitCUData; bool bHEVCBlockAnalysis = (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions > 16); - bool bRefineAVCAnalysis = (m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); + bool bRefineAVCAnalysis = (m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); bool bNooffloading = !(m_param->bAnalysisType == AVC_INFO); if (bHEVCBlockAnalysis || bRefineAVCAnalysis || bNooffloading) @@ -1953,7 +1957,7 @@ mightSplit &= !bDecidedDepth; } } - if (m_param->analysisLoad && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if (m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10) { if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx]) { @@ -1971,7 +1975,7 @@ if (m_param->bEnableRecursionSkip && depth && m_modeDepth[depth - 1].bestMode) skipRecursion = md.bestMode && !md.bestMode->cu.getQtRootCbf(0); } - if (m_param->analysisReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) + if (m_param->analysisLoadReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) skipRectAmp = true && !!md.bestMode; } } @@ -1999,7 +2003,7 @@ } /* Step 1. Evaluate Merge/Skip candidates for likely early-outs */ if ((mightNotSplit && !md.bestMode && !bCtuInfoCheck) || - (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) { md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp); md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp); @@ -2014,7 +2018,7 @@ if (m_param->bEnableRecursionSkip && depth && m_modeDepth[depth - 1].bestMode) skipRecursion = md.bestMode && !md.bestMode->cu.getQtRootCbf(0); } - if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisLoadReuseLevel == 7) skipRecursion = true; // estimate split cost /* Step 2. Evaluate each of the 4 split sub-blocks in series */ @@ -2068,7 +2072,7 @@ checkDQPForSplitPred(*splitPred, cuGeom); } /* If analysis mode is simple do not Evaluate other modes */ - if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7) { if (m_slice->m_sliceType == P_SLICE) { @@ -2461,7 +2465,7 @@ for (uint32_t part = 0; part < numPU; part++) { PredictionUnit pu(mode.cu, cuGeom, part); - if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7)) + if (m_param->analysisLoadReuseLevel == 10 || (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7)) { x265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData; int cuIdx = (mode.cu.m_cuAddr * parentCTU.m_numPartitions) + cuGeom.absPartIdx; @@ -2552,7 +2556,7 @@ checkDQPForSplitPred(*md.bestMode, cuGeom); } - if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7) { for (int list = 0; list < m_slice->isInterB() + 1; list++) { @@ -2607,7 +2611,7 @@ if (m_slice->m_pps->bUseDQP && nextDepth <= m_slice->m_pps->maxCuDQPDepth) nextQP = setLambdaFromQP(parentCTU, calculateQpforCuSize(parentCTU, childGeom)); - int lamdaQP = (m_param->analysisReuseLevel >= 7) ? nextQP : lqp; + int lamdaQP = (m_param->analysisLoadReuseLevel >= 7) ? nextQP : lqp; if (split) m_param->rdLevel > 4 ? compressInterCU_rd5_6(parentCTU, childGeom, nextQP) : compressInterCU_rd0_4(parentCTU, childGeom, nextQP); @@ -3013,7 +3017,7 @@ interMode.cu.setPredModeSubParts(MODE_INTER); int numPredDir = m_slice->isInterP() ? 1 : 2; - if (m_param->analysisLoad && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if (m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3056,7 +3060,7 @@ } interMode.sa8dCost = m_rdCost.calcRdSADCost((uint32_t)interMode.distortion, interMode.sa8dBits); - if (m_param->analysisSave && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1) + if (m_param->analysisSaveReuseLevel > 1 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3078,7 +3082,7 @@ interMode.cu.setPredModeSubParts(MODE_INTER); int numPredDir = m_slice->isInterP() ? 1 : 2; - if (m_param->analysisLoad && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if (m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3113,7 +3117,7 @@ /* predInterSearch sets interMode.sa8dBits, but this is ignored */ encodeResAndCalcRdInterCU(interMode, cuGeom); - if (m_param->analysisSave && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1) + if (m_param->analysisSaveReuseLevel > 1 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3612,7 +3616,7 @@ qp += distortionData->offset[ctu.m_cuAddr]; } - if (m_param->analysisLoad && m_param->analysisReuseLevel == 10 && m_param->rc.cuTree) + if (m_param->analysisLoadReuseLevel == 10 && m_param->rc.cuTree) { int cuIdx = (ctu.m_cuAddr * ctu.m_numPartitions) + cuGeom.absPartIdx; if (ctu.m_slice->m_sliceType == I_SLICE) diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/api.cpp --- a/source/encoder/api.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/api.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -771,6 +771,12 @@ int numDir = 2; //irrespective of P or B slices set direction as 2 uint32_t numPlanes = param->internalCsp == X265_CSP_I400 ? 1 : 3; + int maxReuseLevel = X265_MAX(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel); + int minReuseLevel = (param->analysisSaveReuseLevel && param->analysisLoadReuseLevel) ? + X265_MIN(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel) : maxReuseLevel; + + bool isMultiPassOpt = param->analysisMultiPassRefine || param->analysisMultiPassDistortion; + #if X265_DEPTH < 10 && (LINKED_10BIT || LINKED_12BIT) uint32_t numCUs_sse_t = param->internalBitDepth > 8 ? analysis->numCUsInFrame << 1 : analysis->numCUsInFrame; #elif X265_DEPTH >= 10 && LINKED_8BIT @@ -778,7 +784,7 @@ #else uint32_t numCUs_sse_t = analysis->numCUsInFrame; #endif - if (param->analysisMultiPassRefine || param->analysisMultiPassDistortion || param->ctuDistortionRefine) + if (isMultiPassOpt || param->ctuDistortionRefine) { //Allocate memory for distortionData pointer CHECKED_MALLOC_ZERO(distortionData, x265_analysis_distortion_data, 1); @@ -792,7 +798,7 @@ analysis->distortionData = distortionData; } - if (param->bDisableLookahead && isVbv) + if (!isMultiPassOpt && param->bDisableLookahead && isVbv) { CHECKED_MALLOC_ZERO(analysis->lookahead.intraSatdForVbv, uint32_t, analysis->numCuInHeight); CHECKED_MALLOC_ZERO(analysis->lookahead.satdForVbv, uint32_t, analysis->numCuInHeight); @@ -801,20 +807,23 @@ } //Allocate memory for weightParam pointer - if (!(param->bAnalysisType == AVC_INFO)) + if (!isMultiPassOpt && !(param->bAnalysisType == AVC_INFO)) CHECKED_MALLOC_ZERO(analysis->wt, x265_weight_param, numPlanes * numDir); - if (param->analysisReuseLevel < 2) + if (maxReuseLevel < 2) return; //Allocate memory for intraData pointer CHECKED_MALLOC_ZERO(intraData, x265_analysis_intra_data, 1); CHECKED_MALLOC(intraData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - if (param->rc.cuTree) - CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); + if (!isMultiPassOpt) + { + CHECKED_MALLOC_ZERO(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + if (param->rc.cuTree) + CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); + } analysis->intraData = intraData; //Allocate memory for interData pointer based on ReuseLevels @@ -822,19 +831,19 @@ CHECKED_MALLOC(interData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - if (param->rc.cuTree) + if (param->rc.cuTree && !isMultiPassOpt) CHECKED_MALLOC_ZERO(interData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mvpIdx[0], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mvpIdx[1], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mv[0], x265_analysis_MV, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mv[1], x265_analysis_MV, analysis->numPartitions * analysis->numCUsInFrame); - if (param->analysisReuseLevel > 4) + if (maxReuseLevel > 4) { CHECKED_MALLOC_ZERO(interData->partSize, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mergeFlag, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); } - if (param->analysisReuseLevel >= 7) + if (maxReuseLevel >= 7) { CHECKED_MALLOC_ZERO(interData->interDir, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->sadCost, int64_t, analysis->numPartitions * analysis->numCUsInFrame); @@ -844,14 +853,13 @@ CHECKED_MALLOC_ZERO(analysis->modeFlag[dir], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); } } - else + if ((minReuseLevel >= 2) && (minReuseLevel <= 6)) { - if (param->analysisMultiPassRefine || param->analysisMultiPassDistortion){ - CHECKED_MALLOC_ZERO(interData->ref, int32_t, 2 * analysis->numPartitions * analysis->numCUsInFrame); - } - else - CHECKED_MALLOC_ZERO(interData->ref, int32_t, analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir); + CHECKED_MALLOC_ZERO(interData->ref, int32_t, analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir); } + if (isMultiPassOpt) + CHECKED_MALLOC_ZERO(interData->ref, int32_t, 2 * analysis->numPartitions * analysis->numCUsInFrame); + analysis->interData = interData; return; @@ -862,10 +870,15 @@ void x265_free_analysis_data(x265_param *param, x265_analysis_data* analysis) { + int maxReuseLevel = X265_MAX(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel); + int minReuseLevel = (param->analysisSaveReuseLevel && param->analysisLoadReuseLevel) ? + X265_MIN(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel) : maxReuseLevel; + bool isVbv = param->rc.vbvMaxBitrate > 0 && param->rc.vbvBufferSize > 0; + bool isMultiPassOpt = param->analysisMultiPassRefine || param->analysisMultiPassDistortion; //Free memory for Lookahead pointers - if (param->bDisableLookahead && isVbv) + if (!isMultiPassOpt && param->bDisableLookahead && isVbv) { X265_FREE(analysis->lookahead.satdForVbv); X265_FREE(analysis->lookahead.intraSatdForVbv); @@ -887,21 +900,24 @@ } /* Early exit freeing weights alone if level is 1 (when there is no analysis inter/intra) */ - if (analysis->wt && !(param->bAnalysisType == AVC_INFO)) + if (!isMultiPassOpt && analysis->wt && !(param->bAnalysisType == AVC_INFO)) X265_FREE(analysis->wt); - if (param->analysisReuseLevel < 2) + if (maxReuseLevel < 2) return; //Free memory for intraData pointers if (analysis->intraData) { X265_FREE((analysis->intraData)->depth); - X265_FREE((analysis->intraData)->modes); - X265_FREE((analysis->intraData)->partSizes); - X265_FREE((analysis->intraData)->chromaModes); - if (param->rc.cuTree) - X265_FREE((analysis->intraData)->cuQPOff); + if (!isMultiPassOpt) + { + X265_FREE((analysis->intraData)->modes); + X265_FREE((analysis->intraData)->partSizes); + X265_FREE((analysis->intraData)->chromaModes); + if (param->rc.cuTree) + X265_FREE((analysis->intraData)->cuQPOff); + } X265_FREE(analysis->intraData); analysis->intraData = NULL; } @@ -911,19 +927,19 @@ { X265_FREE((analysis->interData)->depth); X265_FREE((analysis->interData)->modes); - if (param->rc.cuTree) + if (!isMultiPassOpt && param->rc.cuTree) X265_FREE((analysis->interData)->cuQPOff); X265_FREE((analysis->interData)->mvpIdx[0]); X265_FREE((analysis->interData)->mvpIdx[1]); X265_FREE((analysis->interData)->mv[0]); X265_FREE((analysis->interData)->mv[1]); - if (param->analysisReuseLevel > 4) + if (maxReuseLevel > 4) { X265_FREE((analysis->interData)->mergeFlag); X265_FREE((analysis->interData)->partSize); } - if (param->analysisReuseLevel >= 7) + if (maxReuseLevel >= 7) { int numDir = 2; X265_FREE((analysis->interData)->interDir); @@ -932,13 +948,13 @@ { X265_FREE((analysis->interData)->refIdx[dir]); if (analysis->modeFlag[dir] != NULL) - { + { X265_FREE(analysis->modeFlag[dir]); analysis->modeFlag[dir] = NULL; } } } - else + if (((minReuseLevel >= 2) && (minReuseLevel <= 6)) || isMultiPassOpt) X265_FREE((analysis->interData)->ref); X265_FREE(analysis->interData); analysis->interData = NULL; diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/encoder.cpp --- a/source/encoder/encoder.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/encoder.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -650,7 +650,7 @@ if (analysis_data->sliceType == X265_TYPE_IDR || analysis_data->sliceType == X265_TYPE_I) { curFrame->m_analysisData.sliceType = X265_TYPE_I; - if (m_param->analysisReuseLevel < 7) + if (m_param->analysisLoadReuseLevel < 7) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; int num16x16inCUWidth = m_param->maxCUSize >> 4; @@ -680,7 +680,7 @@ else { uint32_t numDir = analysis_data->sliceType == X265_TYPE_P ? 1 : 2; - if (m_param->analysisReuseLevel < 7) + if (m_param->analysisLoadReuseLevel < 7) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; int num16x16inCUWidth = m_param->maxCUSize >> 4; @@ -722,7 +722,7 @@ (interData)->mvpIdx[k][cuPos + cuOffset] = (srcInterData)->mvpIdx[k][(mbIndex * 16) + cuOffset]; (interData)->refIdx[k][cuPos + cuOffset] = (srcInterData)->refIdx[k][(mbIndex * 16) + cuOffset]; memcpy(&(interData)->mv[k][cuPos + cuOffset], &(srcInterData)->mv[k][(mbIndex * 16) + cuOffset], sizeof(MV)); - if (m_param->analysisReuseLevel == 7 && numPU == PU_2Nx2N && + if (m_param->analysisLoadReuseLevel == 7 && numPU == PU_2Nx2N && ((interData)->depth[cuPos + cuOffset] == (m_param->maxCUSize >> 5))) { int mv_x = (interData)->mv[k][cuPos + cuOffset].x; @@ -756,7 +756,7 @@ if (analysis_data->sliceType == X265_TYPE_IDR || analysis_data->sliceType == X265_TYPE_I) { curFrame->m_analysisData.sliceType = X265_TYPE_I; - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; @@ -777,7 +777,7 @@ else { uint32_t numDir = analysis_data->sliceType == X265_TYPE_P ? 1 : 2; - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; @@ -790,7 +790,7 @@ memset(&(currInterData)->depth[count], (interData)->depth[d], bytes); memset(&(currInterData)->modes[count], (interData)->modes[d], bytes); memcpy(&(currInterData)->sadCost[count], &(analysis_data->interData)->sadCost[d], bytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { memset(&(currInterData)->partSize[count], (interData)->partSize[d], bytes); int numPU = nbPartsTable[(interData)->partSize[d]]; @@ -798,7 +798,7 @@ { if (pu) d++; (currInterData)->mergeFlag[count + pu] = (interData)->mergeFlag[d]; - if (m_param->analysisReuseLevel >= 7) + if (m_param->analysisLoadReuseLevel >= 7) { (currInterData)->interDir[count + pu] = (interData)->interDir[d]; for (uint32_t i = 0; i < numDir; i++) @@ -806,7 +806,7 @@ (currInterData)->mvpIdx[i][count + pu] = (interData)->mvpIdx[i][d]; (currInterData)->refIdx[i][count + pu] = (interData)->refIdx[i][d]; memcpy(&(currInterData)->mv[i][count + pu], &(interData)->mv[i][d], sizeof(MV)); - if (m_param->analysisReuseLevel == 7 && numPU == PU_2Nx2N && m_param->num4x4Partitions <= 16) + if (m_param->analysisLoadReuseLevel == 7 && numPU == PU_2Nx2N && m_param->num4x4Partitions <= 16) { int mv_x = (currInterData)->mv[i][count + pu].x; int mv_y = (currInterData)->mv[i][count + pu].y; @@ -3577,10 +3577,46 @@ p->rc.rfConstantMin = 0; } - if (!(p->bAnalysisType == HEVC_INFO) && (p->analysisLoad || p->analysisSave) && p->rc.cuTree && p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "cu-tree works only with analysis reuse level 10, Disabling cu-tree\n"); - p->rc.cuTree = 0; + if (p->analysisSaveReuseLevel && !p->analysisSave) + { + x265_log(p, X265_LOG_WARNING, "analysis-save-reuse-level can be set only when analysis-save is enabled." + " Resetting analysis-save-reuse-level to 0.\n"); + p->analysisSaveReuseLevel = 0; + } + + if (p->analysisLoadReuseLevel && !p->analysisLoad) + { + x265_log(p, X265_LOG_WARNING, "analysis-load-reuse-level can be set only when analysis-load is enabled." + " Resetting analysis-load-reuse-level to 0.\n"); + p->analysisLoadReuseLevel = 0; + } + + if (p->analysisSave && !p->analysisSaveReuseLevel) + { + x265_log(p, X265_LOG_WARNING, "analysis-save-reuse-level must be set when analysis-save is enabled." + " Setting analysis-save-reuse-level to 5.\n"); + p->analysisSaveReuseLevel = 5; + } + + if (p->analysisLoad && !p->analysisLoadReuseLevel) + { + x265_log(p, X265_LOG_WARNING, "analysis-load-reuse-level must be set when analysis-load is enabled." + " Setting analysis-load-reuse-level to 5.\n"); + p->analysisLoadReuseLevel = 5; + } + + if ((p->bAnalysisType == DEFAULT) && p->rc.cuTree) + { + if (p->analysisSaveReuseLevel && p->analysisSaveReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "cu-tree works only with analysis-save-reuse-level 10, Disabling cu-tree\n"); + p->rc.cuTree = 0; + } + if (p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "cu-tree works only with analysis-load-reuse-level 10, Disabling cu-tree\n"); + p->rc.cuTree = 0; + } } if ((p->analysisLoad || p->analysisSave) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation)) @@ -3602,45 +3638,37 @@ { p->scaleFactor = 0; } - else if ((!p->analysisLoad && !p->analysisSave) || (p->analysisReuseLevel > 6 && p->analysisReuseLevel != 10)) + else if ((p->analysisSaveReuseLevel > 6 && p->analysisSaveReuseLevel != 10) || (p->analysisLoadReuseLevel > 6 && p->analysisLoadReuseLevel != 10)) { - x265_log(p, X265_LOG_WARNING, "Input scaling works with analysis load/save and analysis-reuse-level 1-6 and 10. Disabling scale-factor.\n"); + x265_log(p, X265_LOG_WARNING, "Input scaling works with analysis-save/load and analysis-save/load-reuse-level 1-6 and 10. Disabling scale-factor.\n"); p->scaleFactor = 0; } } - if (p->intraRefine) - { - if (!p->analysisLoad || p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "Intra refinement requires analysis load, analysis-reuse-level 10. Disabling intra refine.\n"); - p->intraRefine = 0; - } - } - - if (p->interRefine) - { - if (!p->analysisLoad || p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "Inter refinement requires analysis load, analysis-reuse-level 10. Disabling inter refine.\n"); - p->interRefine = 0; - } - } - - if (p->bDynamicRefine) - { - if (!p->analysisLoad || p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "Dynamic refinement requires analysis load, analysis-reuse-level 10. Disabling dynamic refine.\n"); - p->bDynamicRefine = 0; - } + if (p->intraRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "Intra refinement requires analysis load, analysis-load-reuse-level 10. Disabling intra refine.\n"); + p->intraRefine = 0; + } + + if (p->interRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "Inter refinement requires analysis load, analysis-load-reuse-level 10. Disabling inter refine.\n"); + p->interRefine = 0; + } + + if (p->bDynamicRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "Dynamic refinement requires analysis load, analysis-load-reuse-level 10. Disabling dynamic refine.\n"); + p->bDynamicRefine = 0; + if (p->interRefine) { x265_log(p, X265_LOG_WARNING, "Inter refine cannot be used with dynamic refine. Disabling refine-inter.\n"); p->interRefine = 0; } } - if (p->scaleFactor && p->analysisLoad && !p->interRefine && !p->bDynamicRefine && p->analysisReuseLevel == 10) + if (p->scaleFactor && !p->interRefine && !p->bDynamicRefine && p->analysisLoadReuseLevel == 10) { x265_log(p, X265_LOG_WARNING, "Inter refinement 0 is not supported with scaling and analysis-reuse-level=10. Enabling refine-inter 1.\n"); p->interRefine = 1; @@ -4205,7 +4233,7 @@ { if (m_param->bAnalysisType == HEVC_INFO) return; - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL; @@ -4265,7 +4293,7 @@ uint32_t numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2; uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3; X265_FREAD((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileIn, (picIn->analysisData.wt)); - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL; @@ -4274,9 +4302,9 @@ int8_t* refIdx[2]; int8_t* cuQPBuf = NULL; - int numBuf = m_param->analysisReuseLevel > 4 ? 4 : 2; + int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2; bool bIntraInInter = false; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { numBuf++; bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames); @@ -4299,14 +4327,14 @@ X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes); if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); } - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { partSize = modeBuf + depthBytes; mergeFlag = partSize + depthBytes; X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize); X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { interDir = mergeFlag + depthBytes; X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir); @@ -4337,7 +4365,7 @@ memset(&(analysis->interData)->modes[count], modeBuf[d], bytes); if (m_param->rc.cuTree) memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && partSize[d] == SIZE_NxN) partSize[d] = SIZE_2Nx2N; @@ -4347,7 +4375,7 @@ { if (pu) d++; (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d]; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { (analysis->interData)->interDir[count + pu] = interDir[d]; for (uint32_t i = 0; i < numDir; i++) @@ -4363,7 +4391,7 @@ } } } - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisLoadReuseLevel == 10 && bIntraInInter) memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes); } count += bytes; @@ -4373,7 +4401,7 @@ X265_FREE(cuQPBuf); X265_FREE(tempBuf); } - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { if (m_param->bAnalysisType != HEVC_INFO) { @@ -4556,7 +4584,7 @@ if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) { - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL; @@ -4625,7 +4653,7 @@ uint32_t numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2; uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3; X265_FREAD((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileIn, (picIn->analysisData.wt)); - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL; @@ -4634,9 +4662,9 @@ int8_t* refIdx[2]; int8_t* cuQPBuf = NULL; - int numBuf = m_param->analysisReuseLevel > 4 ? 4 : 2; + int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2; bool bIntraInInter = false; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { numBuf++; bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames); @@ -4652,13 +4680,13 @@ X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth); X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes); if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); } - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { partSize = modeBuf + depthBytes; mergeFlag = partSize + depthBytes; X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize); X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { interDir = mergeFlag + depthBytes; X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir); @@ -4702,10 +4730,10 @@ memset(&(analysis->interData)->modes[count], modeBuf[d], bytes); if (m_param->rc.cuTree) memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes); - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisLoadReuseLevel == 10 && bIntraInInter) memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { puOrientation puOrient; puOrient.init(); @@ -4731,7 +4759,7 @@ d++; (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d]; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { (analysis->interData)->interDir[count + pu] = interDir[d]; MV mvCopy[2]; @@ -4766,7 +4794,7 @@ X265_FREE(cuQPBuf); X265_FREE(tempBuf); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { for (uint32_t i = 0; i < numDir; i++) { @@ -4855,7 +4883,6 @@ X265_PARAM_VALIDATE(saveParam->intraRefresh, sizeof(int), 1, &m_param->bIntraRefresh, intra-refresh); X265_PARAM_VALIDATE(saveParam->maxNumReferences, sizeof(int), 1, &m_param->maxNumReferences, ref); - X265_PARAM_VALIDATE(saveParam->analysisReuseLevel, sizeof(int), 1, &m_param->analysisReuseLevel, analysis-reuse-level); X265_PARAM_VALIDATE(saveParam->keyframeMax, sizeof(int), 1, &m_param->keyframeMax, keyint); X265_PARAM_VALIDATE(saveParam->keyframeMin, sizeof(int), 1, &m_param->keyframeMin, min-keyint); X265_PARAM_VALIDATE(saveParam->openGOP, sizeof(int), 1, &m_param->bOpenGOP, open-gop); @@ -4871,6 +4898,7 @@ int sourceHeight, sourceWidth; if (writeFlag) { + X265_PARAM_VALIDATE(saveParam->analysisReuseLevel, sizeof(int), 1, &m_param->analysisSaveReuseLevel, analysis - save - reuse - level); sourceHeight = m_param->sourceHeight - m_conformanceWindow.bottomOffset; sourceWidth = m_param->sourceWidth - m_conformanceWindow.rightOffset; X265_PARAM_VALIDATE(saveParam->sourceWidth, sizeof(int), 1, &sourceWidth, res-width); @@ -4880,10 +4908,35 @@ else { fileOffset = m_analysisFileIn; + + int saveLevel = 0; + bool isIncompatibleReuseLevel = false; + int loadLevel = m_param->analysisLoadReuseLevel; + + X265_FREAD(&saveLevel, sizeof(int), 1, m_analysisFileIn, &(saveParam->analysisReuseLevel)); + + if (loadLevel == 10 && saveLevel != 10) + isIncompatibleReuseLevel = true; + else if (((loadLevel >= 7) && (loadLevel <= 9)) && ((saveLevel < 7) || (saveLevel > 9))) + isIncompatibleReuseLevel = true; + else if ((loadLevel == 5 || loadLevel == 6) && ((saveLevel != 5) && (saveLevel != 6))) + isIncompatibleReuseLevel = true; + else if ((loadLevel >= 2 && loadLevel <= 4) && (saveLevel < 2 || saveLevel > 6)) + isIncompatibleReuseLevel = true; + else if (!saveLevel) + isIncompatibleReuseLevel = true; + + if (isIncompatibleReuseLevel) + { + x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data. Incompatible reuse-levels.\n"); + m_aborted = true; + return -1; + } + bool error = false; int curSourceHeight = m_param->sourceHeight - m_conformanceWindow.bottomOffset; int curSourceWidth = m_param->sourceWidth - m_conformanceWindow.rightOffset; - + X265_FREAD(&sourceWidth, sizeof(int), 1, m_analysisFileIn, &(saveParam->sourceWidth)); X265_FREAD(&sourceHeight, sizeof(int), 1, m_analysisFileIn, &(saveParam->sourceHeight)); X265_FREAD(&readValue, sizeof(int), 1, m_analysisFileIn, &(saveParam->maxCUSize)); @@ -5205,7 +5258,7 @@ analysis->frameRecordSize += analysis->numCUsInFrame * sizeof(sse_t); } - if (m_param->analysisReuseLevel > 1) + if (m_param->analysisSaveReuseLevel > 1) { if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) @@ -5258,14 +5311,14 @@ interDataCTU->depth[depthBytes] = depth; predMode = ctu->m_predMode[absPartIdx]; - if (m_param->analysisReuseLevel != 10 && ctu->m_refIdx[1][absPartIdx] != -1) + if (m_param->analysisSaveReuseLevel != 10 && ctu->m_refIdx[1][absPartIdx] != -1) predMode = 4; // used as indicator if the block is coded as bidir interDataCTU->modes[depthBytes] = predMode; if (m_param->rc.cuTree) interDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisSaveReuseLevel > 4) { partSize = ctu->m_partSize[absPartIdx]; interDataCTU->partSize[depthBytes] = partSize; @@ -5278,7 +5331,7 @@ if (puIdx) depthBytes++; interDataCTU->mergeFlag[depthBytes] = ctu->m_mergeFlag[puabsPartIdx]; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisSaveReuseLevel == 10) { interDataCTU->interDir[depthBytes] = ctu->m_interDir[puabsPartIdx]; for (uint32_t dir = 0; dir < numDir; dir++) @@ -5289,12 +5342,12 @@ } } } - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisSaveReuseLevel == 10 && bIntraInInter) intraDataCTU->chromaModes[depthBytes] = ctu->m_chromaIntraDir[absPartIdx]; } absPartIdx += ctu->m_numPartitions >> (depth * 2); } - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisSaveReuseLevel == 10 && bIntraInInter) memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions); } } @@ -5309,10 +5362,10 @@ analysis->frameRecordSize += depthBytes * 2; if (m_param->rc.cuTree) analysis->frameRecordSize += (sizeof(int8_t) * depthBytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisSaveReuseLevel > 4) analysis->frameRecordSize += (depthBytes * 2); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisSaveReuseLevel == 10) { /* Add Size of interDir, mvpIdx, refIdx, mv, luma and chroma modes */ analysis->frameRecordSize += depthBytes; @@ -5344,7 +5397,7 @@ if (analysis->sliceType > X265_TYPE_I) X265_FWRITE((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileOut); - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisSaveReuseLevel < 2) return; if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) @@ -5362,11 +5415,11 @@ X265_FWRITE((analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFileOut); if (m_param->rc.cuTree) X265_FWRITE((analysis->interData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisSaveReuseLevel > 4) { X265_FWRITE((analysis->interData)->partSize, sizeof(uint8_t), depthBytes, m_analysisFileOut); X265_FWRITE((analysis->interData)->mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileOut); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisSaveReuseLevel == 10) { X265_FWRITE((analysis->interData)->interDir, sizeof(uint8_t), depthBytes, m_analysisFileOut); if (bIntraInInter) X265_FWRITE((analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFileOut); @@ -5380,7 +5433,7 @@ X265_FWRITE((analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFileOut); } } - if (m_param->analysisReuseLevel != 10) + if (m_param->analysisSaveReuseLevel != 10) X265_FWRITE((analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFileOut); } diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/search.cpp --- a/source/encoder/search.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/search.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -2208,7 +2208,7 @@ x265_analysis_inter_data* interDataCTU = NULL; int cuIdx; cuIdx = (interMode.cu.m_cuAddr * m_param->num4x4Partitions) + cuGeom.absPartIdx; - if (m_param->analysisReuseLevel == 10 && m_param->interRefine > 1) + if (m_param->analysisLoadReuseLevel == 10 && m_param->interRefine > 1) { interDataCTU = m_frame->m_analysisData.interData; if ((cu.m_predMode[pu.puAbsPartIdx] == interDataCTU->modes[cuIdx + pu.puAbsPartIdx]) @@ -2227,7 +2227,7 @@ cu.getNeighbourMV(puIdx, pu.puAbsPartIdx, interMode.interNeighbours); /* Uni-directional prediction */ - if ((m_param->analysisLoad && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if ((m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10) || (m_param->analysisMultiPassRefine && m_param->rc.bStatRead) || (m_param->bAnalysisType == AVC_INFO) || (useAsMVP)) { for (int list = 0; list < numPredDir; list++) diff -r 52135ffd9bcd -r 4d870dd7c314 source/x265.h --- a/source/x265.h Mon Dec 23 14:40:32 2019 +0530 +++ b/source/x265.h Mon Dec 16 17:55:07 2019 +0530 @@ -320,7 +320,7 @@ typedef enum { - NO_INFO = 0, + DEFAULT = 0, AVC_INFO = 1, HEVC_INFO = 2, }AnalysisRefineType; @@ -1656,7 +1656,7 @@ /* A value between 1 and 10 (both inclusive) determines the level of * information stored/reused in analysis save/load. Higher the refine - * level higher the information stored/reused. Default is 5 */ + * level higher the information stored/reused. Default is 5. Now deprecated. */ int analysisReuseLevel; /* Limit Sample Adaptive Offset filter computation by early terminating SAO @@ -1859,6 +1859,16 @@ /* Enable HME search ranges for L0, L1 and L2 respectively. */ int hmeRange[3]; + + /* A value between 1 and 10 (both inclusive) determines the level of + * analysis information stored in analysis-save. Higher the refine level higher + * the information stored. Default is 5 */ + int analysisSaveReuseLevel; + + /* A value between 1 and 10 (both inclusive) determines the level of + * analysis information reused in analysis-load. Higher the refine level higher + * the information reused. Default is 5 */ + int analysisLoadReuseLevel; } x265_param; /* x265_param_alloc: diff -r 52135ffd9bcd -r 4d870dd7c314 source/x265cli.h --- a/source/x265cli.h Mon Dec 23 14:40:32 2019 +0530 +++ b/source/x265cli.h Mon Dec 16 17:55:07 2019 +0530 @@ -275,7 +275,9 @@ { "no-multi-pass-opt-rps", no_argument, NULL, 0 }, { "analysis-reuse-mode", required_argument, NULL, 0 }, /* DEPRECATED */ { "analysis-reuse-file", required_argument, NULL, 0 }, - { "analysis-reuse-level", required_argument, NULL, 0 }, + { "analysis-reuse-level", required_argument, NULL, 0 }, /* DEPRECATED */ + { "analysis-save-reuse-level", required_argument, NULL, 0 }, + { "analysis-load-reuse-level", required_argument, NULL, 0 }, { "analysis-save", required_argument, NULL, 0 }, { "analysis-load", required_argument, NULL, 0 }, { "scale-factor", required_argument, NULL, 0 }, @@ -549,7 +551,9 @@ H0(" --analysis-save <filename> Dump analysis info into the specified file. Default Disabled\n"); H0(" --analysis-load <filename> Load analysis buffers from the file specified. Default Disabled\n"); H0(" --analysis-reuse-file <filename> Specify file name used for either dumping or reading analysis data. Deault x265_analysis.dat\n"); - H0(" --analysis-reuse-level <1..10> Level of analysis reuse indicates amount of info stored/reused in save/load mode, 1:least..10:most. Default %d\n", param->analysisReuseLevel); + H0(" --analysis-reuse-level <1..10> Level of analysis reuse indicates amount of info stored/reused in save/load mode, 1:least..10:most. Now deprecated. Default %d\n", param->analysisReuseLevel); + H0(" --analysis-save-reuse-level <1..10> Indicates the amount of analysis info stored in save mode, 1:least..10:most. Default %d\n", param->analysisSaveReuseLevel); + H0(" --analysis-load-reuse-level <1..10> Indicates the amount of analysis info reused in load mode, 1:least..10:most. Default %d\n", param->analysisLoadReuseLevel); H0(" --refine-analysis-type <string> Reuse anlaysis information received through API call. Supported options are avc and hevc. Default disabled - %d\n", param->bAnalysisType); H0(" --scale-factor <int> Specify factor by which input video is scaled down for analysis save mode. Default %d\n", param->scaleFactor); H0(" --refine-intra <0..4> Enable intra refinement for encode that uses analysis-load.\n"
# HG changeset patch # User Aruna Matheswaran <ar...@multicorewareinc.com> # Date 1576499107 -19800 # Mon Dec 16 17:55:07 2019 +0530 # Node ID 4d870dd7c314334b27413de922d08d9c01d5860b # Parent 52135ffd9bcdd32b944311e9e66c473894c0a2bd De-couple analysis reuse levels of --analysis-save and --analysis-load. Currently, analysis reuse level of the load encode has to be the same as that of the reuse level of the save encode. This commit de-couples the reuse level constraints and let the load encode re-use a subset of the available analysis info. Two CLI and x265_param options are introduced to get the desired reuse level during save and load. The existing option --analysis-reuse-level is deprecated. diff -r 52135ffd9bcd -r 4d870dd7c314 doc/reST/cli.rst --- a/doc/reST/cli.rst Mon Dec 23 14:40:32 2019 +0530 +++ b/doc/reST/cli.rst Mon Dec 16 17:55:07 2019 +0530 @@ -918,12 +918,14 @@ Specify a filename for `multi-pass-opt-analysis` and `multi-pass-opt-distortion`. If no filename is specified, x265_analysis.dat is used. -.. option:: --analysis-reuse-level <1..10> - - Amount of information stored/reused in :option:`--analysis-reuse-mode` is distributed across levels. +.. option:: --analysis-save-reuse-level <1..10>, --analysis-load-reuse-level <1..10> + + :option:`--analysis-save-reuse-level` denotes the amount of information stored during :option:`--analysis-save` and + :option:`--analysis-load-reuse-level` denotes the amount of information reused during :option:`--analysis-load`. Higher the value, higher the information stored/reused, faster the encode. Default 5. - Note that --analysis-reuse-level must be paired with analysis-reuse-mode. + Note that :option:`--analysis-save-reuse-level` and :option:`--analysis-load-reuse-level` must be paired + with :option:`--analysis-save` and :option:`--analysis-load` respectively. +--------------+------------------------------------------+ | Level | Description | diff -r 52135ffd9bcd -r 4d870dd7c314 source/CMakeLists.txt --- a/source/CMakeLists.txt Mon Dec 23 14:40:32 2019 +0530 +++ b/source/CMakeLists.txt Mon Dec 16 17:55:07 2019 +0530 @@ -29,7 +29,7 @@ option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF) mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD) # X265_BUILD must be incremented each time the public API is changed -set(X265_BUILD 184) +set(X265_BUILD 185) configure_file("${PROJECT_SOURCE_DIR}/x265.def.in" "${PROJECT_BINARY_DIR}/x265.def") configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in" diff -r 52135ffd9bcd -r 4d870dd7c314 source/common/param.cpp --- a/source/common/param.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/common/param.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -319,7 +319,9 @@ param->bOptCUDeltaQP = 0; param->bAQMotion = 0; param->bHDROpt = 0; - param->analysisReuseLevel = 5; + param->analysisReuseLevel = 0; /*DEPRECATED*/ + param->analysisSaveReuseLevel = 0; + param->analysisLoadReuseLevel = 0; param->toneMapFile = NULL; param->bDhdr10opt = 0; param->dolbyProfile = 0; @@ -1219,7 +1221,14 @@ OPT("multi-pass-opt-distortion") p->analysisMultiPassDistortion = atobool(value); OPT("aq-motion") p->bAQMotion = atobool(value); OPT("dynamic-rd") p->dynamicRd = atof(value); - OPT("analysis-reuse-level") p->analysisReuseLevel = atoi(value); + OPT("analysis-reuse-level") + { + p->analysisReuseLevel = atoi(value); + p->analysisSaveReuseLevel = atoi(value); + p->analysisLoadReuseLevel = atoi(value); + } + OPT("analysis-save-reuse-level") p->analysisSaveReuseLevel = atoi(value); + OPT("analysis-load-reuse-level") p->analysisLoadReuseLevel = atoi(value); OPT("ssim-rd") { int bval = atobool(value); @@ -1260,7 +1269,7 @@ } else if (strcmp(strdup(value), "off") == 0) { - p->bAnalysisType = NO_INFO; + p->bAnalysisType = DEFAULT; } else { @@ -1696,8 +1705,10 @@ "Constant QP is incompatible with 2pass"); CHECK(param->rc.bStrictCbr && (param->rc.bitrate <= 0 || param->rc.vbvBufferSize <=0), "Strict-cbr cannot be applied without specifying target bitrate or vbv bufsize"); - CHECK((param->analysisSave || param->analysisLoad) && (param->analysisReuseLevel < 1 || param->analysisReuseLevel > 10), - "Invalid analysis refine level. Value must be between 1 and 10 (inclusive)"); + CHECK(param->analysisSave && (param->analysisSaveReuseLevel < 1 || param->analysisSaveReuseLevel > 10), + "Invalid analysis save refine level. Value must be between 1 and 10 (inclusive)"); + CHECK(param->analysisLoad && (param->analysisLoadReuseLevel < 1 || param->analysisLoadReuseLevel > 10), + "Invalid analysis load refine level. Value must be between 1 and 10 (inclusive)"); CHECK(param->analysisLoad && (param->mvRefine < 1 || param->mvRefine > 3), "Invalid mv refinement level. Value must be between 1 and 3 (inclusive)"); CHECK(param->scaleFactor > 2, "Invalid scale-factor. Supports factor <= 2"); @@ -2160,6 +2171,8 @@ if (p->analysisLoad) s += sprintf(s, " analysis-load"); s += sprintf(s, " analysis-reuse-level=%d", p->analysisReuseLevel); + s += sprintf(s, " analysis-save-reuse-level=%d", p->analysisSaveReuseLevel); + s += sprintf(s, " analysis-load-reuse-level=%d", p->analysisLoadReuseLevel); s += sprintf(s, " scale-factor=%d", p->scaleFactor); s += sprintf(s, " refine-intra=%d", p->intraRefine); s += sprintf(s, " refine-inter=%d", p->interRefine); @@ -2477,6 +2490,8 @@ dst->bEmitHRDSEI = src->bEmitHRDSEI; dst->bHDROpt = src->bHDROpt; dst->analysisReuseLevel = src->analysisReuseLevel; + dst->analysisSaveReuseLevel = src->analysisSaveReuseLevel; + dst->analysisLoadReuseLevel = src->analysisLoadReuseLevel; dst->bLimitSAO = src->bLimitSAO; if (src->toneMapFile) dst->toneMapFile = strdup(src->toneMapFile); else dst->toneMapFile = NULL; diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/analysis.cpp --- a/source/encoder/analysis.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/analysis.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -202,14 +202,17 @@ m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions]; } - if ((m_param->analysisSave || m_param->analysisLoad) && m_slice->m_sliceType != I_SLICE && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel < 10) + int reuseLevel = X265_MAX(m_param->analysisSaveReuseLevel, m_param->analysisLoadReuseLevel); + if ((m_param->analysisSave || m_param->analysisLoad) && m_slice->m_sliceType != I_SLICE && reuseLevel > 1 && reuseLevel < 10) { int numPredDir = m_slice->isInterP() ? 1 : 2; m_reuseInterDataCTU = m_frame->m_analysisData.interData; - m_reuseRef = &m_reuseInterDataCTU->ref [ctu.m_cuAddr * X265_MAX_PRED_MODE_PER_CTU * numPredDir]; + if (((m_param->analysisSaveReuseLevel > 1) && (m_param->analysisSaveReuseLevel < 7)) || + ((m_param->analysisLoadReuseLevel > 1) && (m_param->analysisLoadReuseLevel < 7))) + m_reuseRef = &m_reuseInterDataCTU->ref[ctu.m_cuAddr * X265_MAX_PRED_MODE_PER_CTU * numPredDir]; m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions]; m_reuseModes = &m_reuseInterDataCTU->modes[ctu.m_cuAddr * ctu.m_numPartitions]; - if (m_param->analysisReuseLevel > 4) + if (reuseLevel > 4) { m_reusePartSize = &m_reuseInterDataCTU->partSize[ctu.m_cuAddr * ctu.m_numPartitions]; m_reuseMergeFlag = &m_reuseInterDataCTU->mergeFlag[ctu.m_cuAddr * ctu.m_numPartitions]; @@ -223,7 +226,7 @@ if (m_slice->m_sliceType == I_SLICE) { x265_analysis_intra_data* intraDataCTU = m_frame->m_analysisData.intraData; - if (m_param->analysisLoad && m_param->analysisReuseLevel > 1) + if (m_param->analysisLoadReuseLevel > 1) { memcpy(ctu.m_cuDepth, &intraDataCTU->depth[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition); memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition); @@ -234,9 +237,9 @@ } else { - bool bCopyAnalysis = ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)); - bool BCompressInterCUrd0_4 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel <= 4); - bool BCompressInterCUrd5_6 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7 && m_param->rdLevel >= 5 && m_param->rdLevel <= 6); + bool bCopyAnalysis = ((m_param->analysisLoadReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7 && ctu.m_numPartitions <= 16)); + bool BCompressInterCUrd0_4 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7 && m_param->rdLevel <= 4); + bool BCompressInterCUrd5_6 = (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7 && m_param->rdLevel >= 5 && m_param->rdLevel <= 6); bCopyAnalysis = bCopyAnalysis || BCompressInterCUrd0_4 || BCompressInterCUrd5_6; if (bCopyAnalysis) @@ -275,8 +278,8 @@ /* generate residual for entire CTU at once and copy to reconPic */ encodeResidue(ctu, cuGeom); } - else if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10 && (!(m_param->bAnalysisType == HEVC_INFO) || m_slice->m_sliceType != P_SLICE)) || - ((m_param->bAnalysisType == AVC_INFO) && m_param->analysisReuseLevel >= 7 && ctu.m_numPartitions <= 16)) + else if ((m_param->analysisLoadReuseLevel == 10 && (!(m_param->bAnalysisType == HEVC_INFO) || m_slice->m_sliceType != P_SLICE)) || + ((m_param->bAnalysisType == AVC_INFO) && m_param->analysisLoadReuseLevel >= 7 && ctu.m_numPartitions <= 16)) { x265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData; int posCTU = ctu.m_cuAddr * numPartition; @@ -456,7 +459,7 @@ int bestCUQP = qp; int lambdaQP = lqp; bool doQPRefine = (bDecidedDepth && depth <= m_slice->m_pps->maxCuDQPDepth) || (!bDecidedDepth && depth == m_slice->m_pps->maxCuDQPDepth); - if (m_param->analysisReuseLevel >= 7) + if (m_param->analysisLoadReuseLevel >= 7) doQPRefine = false; if (doQPRefine) { @@ -1164,7 +1167,7 @@ SplitData splitCUData; bool bHEVCBlockAnalysis = (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions > 16); - bool bRefineAVCAnalysis = (m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); + bool bRefineAVCAnalysis = (m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); bool bNooffloading = !(m_param->bAnalysisType == AVC_INFO); if (bHEVCBlockAnalysis || bRefineAVCAnalysis || bNooffloading) @@ -1259,7 +1262,7 @@ mightSplit &= !bDecidedDepth; } } - if ((m_param->analysisLoad && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10)) + if ((m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10)) { if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx]) { @@ -1273,7 +1276,7 @@ if (m_param->rdLevel) skipModes = m_param->bEnableEarlySkip && md.bestMode; } - if (m_param->analysisReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) + if (m_param->analysisLoadReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) { if (m_reuseModes[cuGeom.absPartIdx] != MODE_INTRA && m_reuseModes[cuGeom.absPartIdx] != 4) { @@ -1300,7 +1303,8 @@ } } /* Step 1. Evaluate Merge/Skip candidates for likely early-outs, if skip mode was not set above */ - if ((mightNotSplit && depth >= minDepth && !md.bestMode && !bCtuInfoCheck) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) /* TODO: Re-evaluate if analysis load/save still works */ + if ((mightNotSplit && depth >= minDepth && !md.bestMode && !bCtuInfoCheck) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + /* TODO: Re-evaluate if analysis load/save still works */ { /* Compute Merge Cost */ md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp); @@ -1310,7 +1314,7 @@ skipModes = (m_param->bEnableEarlySkip || m_refineLevel == 2) && md.bestMode && md.bestMode->cu.isSkipped(0); // TODO: sa8d threshold per depth } - if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck && !(m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck && !(m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) { skipRecursion = md.bestMode->cu.isSkipped(0); if (mightSplit && depth >= minDepth && !skipRecursion) @@ -1321,7 +1325,7 @@ skipRecursion = complexityCheckCU(*md.bestMode); } } - if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisLoadReuseLevel == 7) skipRecursion = true; /* Step 2. Evaluate each of the 4 split sub-blocks in series */ if (mightSplit && !skipRecursion) @@ -1378,7 +1382,7 @@ splitPred->sa8dCost = m_rdCost.calcRdSADCost((uint32_t)splitPred->distortion, splitPred->sa8dBits); } /* If analysis mode is simple do not Evaluate other modes */ - if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7) { if (m_slice->m_sliceType == P_SLICE) { @@ -1857,7 +1861,7 @@ SplitData splitCUData; bool bHEVCBlockAnalysis = (m_param->bAnalysisType == AVC_INFO && cuGeom.numPartitions > 16); - bool bRefineAVCAnalysis = (m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); + bool bRefineAVCAnalysis = (m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])); bool bNooffloading = !(m_param->bAnalysisType == AVC_INFO); if (bHEVCBlockAnalysis || bRefineAVCAnalysis || bNooffloading) @@ -1953,7 +1957,7 @@ mightSplit &= !bDecidedDepth; } } - if (m_param->analysisLoad && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if (m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10) { if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx]) { @@ -1971,7 +1975,7 @@ if (m_param->bEnableRecursionSkip && depth && m_modeDepth[depth - 1].bestMode) skipRecursion = md.bestMode && !md.bestMode->cu.getQtRootCbf(0); } - if (m_param->analysisReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) + if (m_param->analysisLoadReuseLevel > 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N) skipRectAmp = true && !!md.bestMode; } } @@ -1999,7 +2003,7 @@ } /* Step 1. Evaluate Merge/Skip candidates for likely early-outs */ if ((mightNotSplit && !md.bestMode && !bCtuInfoCheck) || - (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) + (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1]))) { md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp); md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp); @@ -2014,7 +2018,7 @@ if (m_param->bEnableRecursionSkip && depth && m_modeDepth[depth - 1].bestMode) skipRecursion = md.bestMode && !md.bestMode->cu.getQtRootCbf(0); } - if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && md.bestMode && cuGeom.numPartitions <= 16 && m_param->analysisLoadReuseLevel == 7) skipRecursion = true; // estimate split cost /* Step 2. Evaluate each of the 4 split sub-blocks in series */ @@ -2068,7 +2072,7 @@ checkDQPForSplitPred(*splitPred, cuGeom); } /* If analysis mode is simple do not Evaluate other modes */ - if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7) { if (m_slice->m_sliceType == P_SLICE) { @@ -2461,7 +2465,7 @@ for (uint32_t part = 0; part < numPU; part++) { PredictionUnit pu(mode.cu, cuGeom, part); - if ((m_param->analysisLoad && m_param->analysisReuseLevel == 10) || (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel >= 7)) + if (m_param->analysisLoadReuseLevel == 10 || (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel >= 7)) { x265_analysis_inter_data* interDataCTU = m_frame->m_analysisData.interData; int cuIdx = (mode.cu.m_cuAddr * parentCTU.m_numPartitions) + cuGeom.absPartIdx; @@ -2552,7 +2556,7 @@ checkDQPForSplitPred(*md.bestMode, cuGeom); } - if (m_param->bAnalysisType == AVC_INFO && m_param->analysisReuseLevel == 7) + if (m_param->bAnalysisType == AVC_INFO && m_param->analysisLoadReuseLevel == 7) { for (int list = 0; list < m_slice->isInterB() + 1; list++) { @@ -2607,7 +2611,7 @@ if (m_slice->m_pps->bUseDQP && nextDepth <= m_slice->m_pps->maxCuDQPDepth) nextQP = setLambdaFromQP(parentCTU, calculateQpforCuSize(parentCTU, childGeom)); - int lamdaQP = (m_param->analysisReuseLevel >= 7) ? nextQP : lqp; + int lamdaQP = (m_param->analysisLoadReuseLevel >= 7) ? nextQP : lqp; if (split) m_param->rdLevel > 4 ? compressInterCU_rd5_6(parentCTU, childGeom, nextQP) : compressInterCU_rd0_4(parentCTU, childGeom, nextQP); @@ -3013,7 +3017,7 @@ interMode.cu.setPredModeSubParts(MODE_INTER); int numPredDir = m_slice->isInterP() ? 1 : 2; - if (m_param->analysisLoad && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if (m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3056,7 +3060,7 @@ } interMode.sa8dCost = m_rdCost.calcRdSADCost((uint32_t)interMode.distortion, interMode.sa8dBits); - if (m_param->analysisSave && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1) + if (m_param->analysisSaveReuseLevel > 1 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3078,7 +3082,7 @@ interMode.cu.setPredModeSubParts(MODE_INTER); int numPredDir = m_slice->isInterP() ? 1 : 2; - if (m_param->analysisLoad && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if (m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3113,7 +3117,7 @@ /* predInterSearch sets interMode.sa8dBits, but this is ignored */ encodeResAndCalcRdInterCU(interMode, cuGeom); - if (m_param->analysisSave && m_reuseInterDataCTU && m_param->analysisReuseLevel > 1) + if (m_param->analysisSaveReuseLevel > 1 && m_reuseInterDataCTU) { int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2; int index = 0; @@ -3612,7 +3616,7 @@ qp += distortionData->offset[ctu.m_cuAddr]; } - if (m_param->analysisLoad && m_param->analysisReuseLevel == 10 && m_param->rc.cuTree) + if (m_param->analysisLoadReuseLevel == 10 && m_param->rc.cuTree) { int cuIdx = (ctu.m_cuAddr * ctu.m_numPartitions) + cuGeom.absPartIdx; if (ctu.m_slice->m_sliceType == I_SLICE) diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/api.cpp --- a/source/encoder/api.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/api.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -771,6 +771,12 @@ int numDir = 2; //irrespective of P or B slices set direction as 2 uint32_t numPlanes = param->internalCsp == X265_CSP_I400 ? 1 : 3; + int maxReuseLevel = X265_MAX(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel); + int minReuseLevel = (param->analysisSaveReuseLevel && param->analysisLoadReuseLevel) ? + X265_MIN(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel) : maxReuseLevel; + + bool isMultiPassOpt = param->analysisMultiPassRefine || param->analysisMultiPassDistortion; + #if X265_DEPTH < 10 && (LINKED_10BIT || LINKED_12BIT) uint32_t numCUs_sse_t = param->internalBitDepth > 8 ? analysis->numCUsInFrame << 1 : analysis->numCUsInFrame; #elif X265_DEPTH >= 10 && LINKED_8BIT @@ -778,7 +784,7 @@ #else uint32_t numCUs_sse_t = analysis->numCUsInFrame; #endif - if (param->analysisMultiPassRefine || param->analysisMultiPassDistortion || param->ctuDistortionRefine) + if (isMultiPassOpt || param->ctuDistortionRefine) { //Allocate memory for distortionData pointer CHECKED_MALLOC_ZERO(distortionData, x265_analysis_distortion_data, 1); @@ -792,7 +798,7 @@ analysis->distortionData = distortionData; } - if (param->bDisableLookahead && isVbv) + if (!isMultiPassOpt && param->bDisableLookahead && isVbv) { CHECKED_MALLOC_ZERO(analysis->lookahead.intraSatdForVbv, uint32_t, analysis->numCuInHeight); CHECKED_MALLOC_ZERO(analysis->lookahead.satdForVbv, uint32_t, analysis->numCuInHeight); @@ -801,20 +807,23 @@ } //Allocate memory for weightParam pointer - if (!(param->bAnalysisType == AVC_INFO)) + if (!isMultiPassOpt && !(param->bAnalysisType == AVC_INFO)) CHECKED_MALLOC_ZERO(analysis->wt, x265_weight_param, numPlanes * numDir); - if (param->analysisReuseLevel < 2) + if (maxReuseLevel < 2) return; //Allocate memory for intraData pointer CHECKED_MALLOC_ZERO(intraData, x265_analysis_intra_data, 1); CHECKED_MALLOC(intraData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame); - CHECKED_MALLOC_ZERO(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - if (param->rc.cuTree) - CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); + if (!isMultiPassOpt) + { + CHECKED_MALLOC_ZERO(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame); + CHECKED_MALLOC_ZERO(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); + if (param->rc.cuTree) + CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); + } analysis->intraData = intraData; //Allocate memory for interData pointer based on ReuseLevels @@ -822,19 +831,19 @@ CHECKED_MALLOC(interData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); - if (param->rc.cuTree) + if (param->rc.cuTree && !isMultiPassOpt) CHECKED_MALLOC_ZERO(interData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mvpIdx[0], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mvpIdx[1], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mv[0], x265_analysis_MV, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mv[1], x265_analysis_MV, analysis->numPartitions * analysis->numCUsInFrame); - if (param->analysisReuseLevel > 4) + if (maxReuseLevel > 4) { CHECKED_MALLOC_ZERO(interData->partSize, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->mergeFlag, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); } - if (param->analysisReuseLevel >= 7) + if (maxReuseLevel >= 7) { CHECKED_MALLOC_ZERO(interData->interDir, uint8_t, analysis->numPartitions * analysis->numCUsInFrame); CHECKED_MALLOC_ZERO(interData->sadCost, int64_t, analysis->numPartitions * analysis->numCUsInFrame); @@ -844,14 +853,13 @@ CHECKED_MALLOC_ZERO(analysis->modeFlag[dir], uint8_t, analysis->numPartitions * analysis->numCUsInFrame); } } - else + if ((minReuseLevel >= 2) && (minReuseLevel <= 6)) { - if (param->analysisMultiPassRefine || param->analysisMultiPassDistortion){ - CHECKED_MALLOC_ZERO(interData->ref, int32_t, 2 * analysis->numPartitions * analysis->numCUsInFrame); - } - else - CHECKED_MALLOC_ZERO(interData->ref, int32_t, analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir); + CHECKED_MALLOC_ZERO(interData->ref, int32_t, analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir); } + if (isMultiPassOpt) + CHECKED_MALLOC_ZERO(interData->ref, int32_t, 2 * analysis->numPartitions * analysis->numCUsInFrame); + analysis->interData = interData; return; @@ -862,10 +870,15 @@ void x265_free_analysis_data(x265_param *param, x265_analysis_data* analysis) { + int maxReuseLevel = X265_MAX(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel); + int minReuseLevel = (param->analysisSaveReuseLevel && param->analysisLoadReuseLevel) ? + X265_MIN(param->analysisSaveReuseLevel, param->analysisLoadReuseLevel) : maxReuseLevel; + bool isVbv = param->rc.vbvMaxBitrate > 0 && param->rc.vbvBufferSize > 0; + bool isMultiPassOpt = param->analysisMultiPassRefine || param->analysisMultiPassDistortion; //Free memory for Lookahead pointers - if (param->bDisableLookahead && isVbv) + if (!isMultiPassOpt && param->bDisableLookahead && isVbv) { X265_FREE(analysis->lookahead.satdForVbv); X265_FREE(analysis->lookahead.intraSatdForVbv); @@ -887,21 +900,24 @@ } /* Early exit freeing weights alone if level is 1 (when there is no analysis inter/intra) */ - if (analysis->wt && !(param->bAnalysisType == AVC_INFO)) + if (!isMultiPassOpt && analysis->wt && !(param->bAnalysisType == AVC_INFO)) X265_FREE(analysis->wt); - if (param->analysisReuseLevel < 2) + if (maxReuseLevel < 2) return; //Free memory for intraData pointers if (analysis->intraData) { X265_FREE((analysis->intraData)->depth); - X265_FREE((analysis->intraData)->modes); - X265_FREE((analysis->intraData)->partSizes); - X265_FREE((analysis->intraData)->chromaModes); - if (param->rc.cuTree) - X265_FREE((analysis->intraData)->cuQPOff); + if (!isMultiPassOpt) + { + X265_FREE((analysis->intraData)->modes); + X265_FREE((analysis->intraData)->partSizes); + X265_FREE((analysis->intraData)->chromaModes); + if (param->rc.cuTree) + X265_FREE((analysis->intraData)->cuQPOff); + } X265_FREE(analysis->intraData); analysis->intraData = NULL; } @@ -911,19 +927,19 @@ { X265_FREE((analysis->interData)->depth); X265_FREE((analysis->interData)->modes); - if (param->rc.cuTree) + if (!isMultiPassOpt && param->rc.cuTree) X265_FREE((analysis->interData)->cuQPOff); X265_FREE((analysis->interData)->mvpIdx[0]); X265_FREE((analysis->interData)->mvpIdx[1]); X265_FREE((analysis->interData)->mv[0]); X265_FREE((analysis->interData)->mv[1]); - if (param->analysisReuseLevel > 4) + if (maxReuseLevel > 4) { X265_FREE((analysis->interData)->mergeFlag); X265_FREE((analysis->interData)->partSize); } - if (param->analysisReuseLevel >= 7) + if (maxReuseLevel >= 7) { int numDir = 2; X265_FREE((analysis->interData)->interDir); @@ -932,13 +948,13 @@ { X265_FREE((analysis->interData)->refIdx[dir]); if (analysis->modeFlag[dir] != NULL) - { + { X265_FREE(analysis->modeFlag[dir]); analysis->modeFlag[dir] = NULL; } } } - else + if (((minReuseLevel >= 2) && (minReuseLevel <= 6)) || isMultiPassOpt) X265_FREE((analysis->interData)->ref); X265_FREE(analysis->interData); analysis->interData = NULL; diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/encoder.cpp --- a/source/encoder/encoder.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/encoder.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -650,7 +650,7 @@ if (analysis_data->sliceType == X265_TYPE_IDR || analysis_data->sliceType == X265_TYPE_I) { curFrame->m_analysisData.sliceType = X265_TYPE_I; - if (m_param->analysisReuseLevel < 7) + if (m_param->analysisLoadReuseLevel < 7) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; int num16x16inCUWidth = m_param->maxCUSize >> 4; @@ -680,7 +680,7 @@ else { uint32_t numDir = analysis_data->sliceType == X265_TYPE_P ? 1 : 2; - if (m_param->analysisReuseLevel < 7) + if (m_param->analysisLoadReuseLevel < 7) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; int num16x16inCUWidth = m_param->maxCUSize >> 4; @@ -722,7 +722,7 @@ (interData)->mvpIdx[k][cuPos + cuOffset] = (srcInterData)->mvpIdx[k][(mbIndex * 16) + cuOffset]; (interData)->refIdx[k][cuPos + cuOffset] = (srcInterData)->refIdx[k][(mbIndex * 16) + cuOffset]; memcpy(&(interData)->mv[k][cuPos + cuOffset], &(srcInterData)->mv[k][(mbIndex * 16) + cuOffset], sizeof(MV)); - if (m_param->analysisReuseLevel == 7 && numPU == PU_2Nx2N && + if (m_param->analysisLoadReuseLevel == 7 && numPU == PU_2Nx2N && ((interData)->depth[cuPos + cuOffset] == (m_param->maxCUSize >> 5))) { int mv_x = (interData)->mv[k][cuPos + cuOffset].x; @@ -756,7 +756,7 @@ if (analysis_data->sliceType == X265_TYPE_IDR || analysis_data->sliceType == X265_TYPE_I) { curFrame->m_analysisData.sliceType = X265_TYPE_I; - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; @@ -777,7 +777,7 @@ else { uint32_t numDir = analysis_data->sliceType == X265_TYPE_P ? 1 : 2; - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return -1; curFrame->m_analysisData.numPartitions = m_param->num4x4Partitions; @@ -790,7 +790,7 @@ memset(&(currInterData)->depth[count], (interData)->depth[d], bytes); memset(&(currInterData)->modes[count], (interData)->modes[d], bytes); memcpy(&(currInterData)->sadCost[count], &(analysis_data->interData)->sadCost[d], bytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { memset(&(currInterData)->partSize[count], (interData)->partSize[d], bytes); int numPU = nbPartsTable[(interData)->partSize[d]]; @@ -798,7 +798,7 @@ { if (pu) d++; (currInterData)->mergeFlag[count + pu] = (interData)->mergeFlag[d]; - if (m_param->analysisReuseLevel >= 7) + if (m_param->analysisLoadReuseLevel >= 7) { (currInterData)->interDir[count + pu] = (interData)->interDir[d]; for (uint32_t i = 0; i < numDir; i++) @@ -806,7 +806,7 @@ (currInterData)->mvpIdx[i][count + pu] = (interData)->mvpIdx[i][d]; (currInterData)->refIdx[i][count + pu] = (interData)->refIdx[i][d]; memcpy(&(currInterData)->mv[i][count + pu], &(interData)->mv[i][d], sizeof(MV)); - if (m_param->analysisReuseLevel == 7 && numPU == PU_2Nx2N && m_param->num4x4Partitions <= 16) + if (m_param->analysisLoadReuseLevel == 7 && numPU == PU_2Nx2N && m_param->num4x4Partitions <= 16) { int mv_x = (currInterData)->mv[i][count + pu].x; int mv_y = (currInterData)->mv[i][count + pu].y; @@ -3577,10 +3577,46 @@ p->rc.rfConstantMin = 0; } - if (!(p->bAnalysisType == HEVC_INFO) && (p->analysisLoad || p->analysisSave) && p->rc.cuTree && p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "cu-tree works only with analysis reuse level 10, Disabling cu-tree\n"); - p->rc.cuTree = 0; + if (p->analysisSaveReuseLevel && !p->analysisSave) + { + x265_log(p, X265_LOG_WARNING, "analysis-save-reuse-level can be set only when analysis-save is enabled." + " Resetting analysis-save-reuse-level to 0.\n"); + p->analysisSaveReuseLevel = 0; + } + + if (p->analysisLoadReuseLevel && !p->analysisLoad) + { + x265_log(p, X265_LOG_WARNING, "analysis-load-reuse-level can be set only when analysis-load is enabled." + " Resetting analysis-load-reuse-level to 0.\n"); + p->analysisLoadReuseLevel = 0; + } + + if (p->analysisSave && !p->analysisSaveReuseLevel) + { + x265_log(p, X265_LOG_WARNING, "analysis-save-reuse-level must be set when analysis-save is enabled." + " Setting analysis-save-reuse-level to 5.\n"); + p->analysisSaveReuseLevel = 5; + } + + if (p->analysisLoad && !p->analysisLoadReuseLevel) + { + x265_log(p, X265_LOG_WARNING, "analysis-load-reuse-level must be set when analysis-load is enabled." + " Setting analysis-load-reuse-level to 5.\n"); + p->analysisLoadReuseLevel = 5; + } + + if ((p->bAnalysisType == DEFAULT) && p->rc.cuTree) + { + if (p->analysisSaveReuseLevel && p->analysisSaveReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "cu-tree works only with analysis-save-reuse-level 10, Disabling cu-tree\n"); + p->rc.cuTree = 0; + } + if (p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "cu-tree works only with analysis-load-reuse-level 10, Disabling cu-tree\n"); + p->rc.cuTree = 0; + } } if ((p->analysisLoad || p->analysisSave) && (p->bDistributeModeAnalysis || p->bDistributeMotionEstimation)) @@ -3602,45 +3638,37 @@ { p->scaleFactor = 0; } - else if ((!p->analysisLoad && !p->analysisSave) || (p->analysisReuseLevel > 6 && p->analysisReuseLevel != 10)) + else if ((p->analysisSaveReuseLevel > 6 && p->analysisSaveReuseLevel != 10) || (p->analysisLoadReuseLevel > 6 && p->analysisLoadReuseLevel != 10)) { - x265_log(p, X265_LOG_WARNING, "Input scaling works with analysis load/save and analysis-reuse-level 1-6 and 10. Disabling scale-factor.\n"); + x265_log(p, X265_LOG_WARNING, "Input scaling works with analysis-save/load and analysis-save/load-reuse-level 1-6 and 10. Disabling scale-factor.\n"); p->scaleFactor = 0; } } - if (p->intraRefine) - { - if (!p->analysisLoad || p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "Intra refinement requires analysis load, analysis-reuse-level 10. Disabling intra refine.\n"); - p->intraRefine = 0; - } - } - - if (p->interRefine) - { - if (!p->analysisLoad || p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "Inter refinement requires analysis load, analysis-reuse-level 10. Disabling inter refine.\n"); - p->interRefine = 0; - } - } - - if (p->bDynamicRefine) - { - if (!p->analysisLoad || p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "Dynamic refinement requires analysis load, analysis-reuse-level 10. Disabling dynamic refine.\n"); - p->bDynamicRefine = 0; - } + if (p->intraRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "Intra refinement requires analysis load, analysis-load-reuse-level 10. Disabling intra refine.\n"); + p->intraRefine = 0; + } + + if (p->interRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "Inter refinement requires analysis load, analysis-load-reuse-level 10. Disabling inter refine.\n"); + p->interRefine = 0; + } + + if (p->bDynamicRefine && p->analysisLoadReuseLevel && p->analysisLoadReuseLevel < 10) + { + x265_log(p, X265_LOG_WARNING, "Dynamic refinement requires analysis load, analysis-load-reuse-level 10. Disabling dynamic refine.\n"); + p->bDynamicRefine = 0; + if (p->interRefine) { x265_log(p, X265_LOG_WARNING, "Inter refine cannot be used with dynamic refine. Disabling refine-inter.\n"); p->interRefine = 0; } } - if (p->scaleFactor && p->analysisLoad && !p->interRefine && !p->bDynamicRefine && p->analysisReuseLevel == 10) + if (p->scaleFactor && !p->interRefine && !p->bDynamicRefine && p->analysisLoadReuseLevel == 10) { x265_log(p, X265_LOG_WARNING, "Inter refinement 0 is not supported with scaling and analysis-reuse-level=10. Enabling refine-inter 1.\n"); p->interRefine = 1; @@ -4205,7 +4233,7 @@ { if (m_param->bAnalysisType == HEVC_INFO) return; - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL; @@ -4265,7 +4293,7 @@ uint32_t numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2; uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3; X265_FREAD((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileIn, (picIn->analysisData.wt)); - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL; @@ -4274,9 +4302,9 @@ int8_t* refIdx[2]; int8_t* cuQPBuf = NULL; - int numBuf = m_param->analysisReuseLevel > 4 ? 4 : 2; + int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2; bool bIntraInInter = false; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { numBuf++; bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames); @@ -4299,14 +4327,14 @@ X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes); if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); } - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { partSize = modeBuf + depthBytes; mergeFlag = partSize + depthBytes; X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize); X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { interDir = mergeFlag + depthBytes; X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir); @@ -4337,7 +4365,7 @@ memset(&(analysis->interData)->modes[count], modeBuf[d], bytes); if (m_param->rc.cuTree) memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { if (m_param->scaleFactor && modeBuf[d] == MODE_INTRA && partSize[d] == SIZE_NxN) partSize[d] = SIZE_2Nx2N; @@ -4347,7 +4375,7 @@ { if (pu) d++; (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d]; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { (analysis->interData)->interDir[count + pu] = interDir[d]; for (uint32_t i = 0; i < numDir; i++) @@ -4363,7 +4391,7 @@ } } } - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisLoadReuseLevel == 10 && bIntraInInter) memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes); } count += bytes; @@ -4373,7 +4401,7 @@ X265_FREE(cuQPBuf); X265_FREE(tempBuf); } - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { if (m_param->bAnalysisType != HEVC_INFO) { @@ -4556,7 +4584,7 @@ if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) { - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL; @@ -4625,7 +4653,7 @@ uint32_t numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2; uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3; X265_FREAD((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileIn, (picIn->analysisData.wt)); - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisLoadReuseLevel < 2) return; uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL; @@ -4634,9 +4662,9 @@ int8_t* refIdx[2]; int8_t* cuQPBuf = NULL; - int numBuf = m_param->analysisReuseLevel > 4 ? 4 : 2; + int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2; bool bIntraInInter = false; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { numBuf++; bIntraInInter = (analysis->sliceType == X265_TYPE_P || m_param->bIntraInBFrames); @@ -4652,13 +4680,13 @@ X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth); X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes); if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); } - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { partSize = modeBuf + depthBytes; mergeFlag = partSize + depthBytes; X265_FREAD(partSize, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->partSize); X265_FREAD(mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->mergeFlag); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { interDir = mergeFlag + depthBytes; X265_FREAD(interDir, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->interDir); @@ -4702,10 +4730,10 @@ memset(&(analysis->interData)->modes[count], modeBuf[d], bytes); if (m_param->rc.cuTree) memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes); - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisLoadReuseLevel == 10 && bIntraInInter) memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisLoadReuseLevel > 4) { puOrientation puOrient; puOrient.init(); @@ -4731,7 +4759,7 @@ d++; (analysis->interData)->mergeFlag[count + pu] = mergeFlag[d]; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { (analysis->interData)->interDir[count + pu] = interDir[d]; MV mvCopy[2]; @@ -4766,7 +4794,7 @@ X265_FREE(cuQPBuf); X265_FREE(tempBuf); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisLoadReuseLevel == 10) { for (uint32_t i = 0; i < numDir; i++) { @@ -4855,7 +4883,6 @@ X265_PARAM_VALIDATE(saveParam->intraRefresh, sizeof(int), 1, &m_param->bIntraRefresh, intra-refresh); X265_PARAM_VALIDATE(saveParam->maxNumReferences, sizeof(int), 1, &m_param->maxNumReferences, ref); - X265_PARAM_VALIDATE(saveParam->analysisReuseLevel, sizeof(int), 1, &m_param->analysisReuseLevel, analysis-reuse-level); X265_PARAM_VALIDATE(saveParam->keyframeMax, sizeof(int), 1, &m_param->keyframeMax, keyint); X265_PARAM_VALIDATE(saveParam->keyframeMin, sizeof(int), 1, &m_param->keyframeMin, min-keyint); X265_PARAM_VALIDATE(saveParam->openGOP, sizeof(int), 1, &m_param->bOpenGOP, open-gop); @@ -4871,6 +4898,7 @@ int sourceHeight, sourceWidth; if (writeFlag) { + X265_PARAM_VALIDATE(saveParam->analysisReuseLevel, sizeof(int), 1, &m_param->analysisSaveReuseLevel, analysis - save - reuse - level); sourceHeight = m_param->sourceHeight - m_conformanceWindow.bottomOffset; sourceWidth = m_param->sourceWidth - m_conformanceWindow.rightOffset; X265_PARAM_VALIDATE(saveParam->sourceWidth, sizeof(int), 1, &sourceWidth, res-width); @@ -4880,10 +4908,35 @@ else { fileOffset = m_analysisFileIn; + + int saveLevel = 0; + bool isIncompatibleReuseLevel = false; + int loadLevel = m_param->analysisLoadReuseLevel; + + X265_FREAD(&saveLevel, sizeof(int), 1, m_analysisFileIn, &(saveParam->analysisReuseLevel)); + + if (loadLevel == 10 && saveLevel != 10) + isIncompatibleReuseLevel = true; + else if (((loadLevel >= 7) && (loadLevel <= 9)) && ((saveLevel < 7) || (saveLevel > 9))) + isIncompatibleReuseLevel = true; + else if ((loadLevel == 5 || loadLevel == 6) && ((saveLevel != 5) && (saveLevel != 6))) + isIncompatibleReuseLevel = true; + else if ((loadLevel >= 2 && loadLevel <= 4) && (saveLevel < 2 || saveLevel > 6)) + isIncompatibleReuseLevel = true; + else if (!saveLevel) + isIncompatibleReuseLevel = true; + + if (isIncompatibleReuseLevel) + { + x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data. Incompatible reuse-levels.\n"); + m_aborted = true; + return -1; + } + bool error = false; int curSourceHeight = m_param->sourceHeight - m_conformanceWindow.bottomOffset; int curSourceWidth = m_param->sourceWidth - m_conformanceWindow.rightOffset; - + X265_FREAD(&sourceWidth, sizeof(int), 1, m_analysisFileIn, &(saveParam->sourceWidth)); X265_FREAD(&sourceHeight, sizeof(int), 1, m_analysisFileIn, &(saveParam->sourceHeight)); X265_FREAD(&readValue, sizeof(int), 1, m_analysisFileIn, &(saveParam->maxCUSize)); @@ -5205,7 +5258,7 @@ analysis->frameRecordSize += analysis->numCUsInFrame * sizeof(sse_t); } - if (m_param->analysisReuseLevel > 1) + if (m_param->analysisSaveReuseLevel > 1) { if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) @@ -5258,14 +5311,14 @@ interDataCTU->depth[depthBytes] = depth; predMode = ctu->m_predMode[absPartIdx]; - if (m_param->analysisReuseLevel != 10 && ctu->m_refIdx[1][absPartIdx] != -1) + if (m_param->analysisSaveReuseLevel != 10 && ctu->m_refIdx[1][absPartIdx] != -1) predMode = 4; // used as indicator if the block is coded as bidir interDataCTU->modes[depthBytes] = predMode; if (m_param->rc.cuTree) interDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisSaveReuseLevel > 4) { partSize = ctu->m_partSize[absPartIdx]; interDataCTU->partSize[depthBytes] = partSize; @@ -5278,7 +5331,7 @@ if (puIdx) depthBytes++; interDataCTU->mergeFlag[depthBytes] = ctu->m_mergeFlag[puabsPartIdx]; - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisSaveReuseLevel == 10) { interDataCTU->interDir[depthBytes] = ctu->m_interDir[puabsPartIdx]; for (uint32_t dir = 0; dir < numDir; dir++) @@ -5289,12 +5342,12 @@ } } } - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisSaveReuseLevel == 10 && bIntraInInter) intraDataCTU->chromaModes[depthBytes] = ctu->m_chromaIntraDir[absPartIdx]; } absPartIdx += ctu->m_numPartitions >> (depth * 2); } - if (m_param->analysisReuseLevel == 10 && bIntraInInter) + if (m_param->analysisSaveReuseLevel == 10 && bIntraInInter) memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions); } } @@ -5309,10 +5362,10 @@ analysis->frameRecordSize += depthBytes * 2; if (m_param->rc.cuTree) analysis->frameRecordSize += (sizeof(int8_t) * depthBytes); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisSaveReuseLevel > 4) analysis->frameRecordSize += (depthBytes * 2); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisSaveReuseLevel == 10) { /* Add Size of interDir, mvpIdx, refIdx, mv, luma and chroma modes */ analysis->frameRecordSize += depthBytes; @@ -5344,7 +5397,7 @@ if (analysis->sliceType > X265_TYPE_I) X265_FWRITE((WeightParam*)analysis->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFileOut); - if (m_param->analysisReuseLevel < 2) + if (m_param->analysisSaveReuseLevel < 2) return; if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) @@ -5362,11 +5415,11 @@ X265_FWRITE((analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFileOut); if (m_param->rc.cuTree) X265_FWRITE((analysis->interData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut); - if (m_param->analysisReuseLevel > 4) + if (m_param->analysisSaveReuseLevel > 4) { X265_FWRITE((analysis->interData)->partSize, sizeof(uint8_t), depthBytes, m_analysisFileOut); X265_FWRITE((analysis->interData)->mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFileOut); - if (m_param->analysisReuseLevel == 10) + if (m_param->analysisSaveReuseLevel == 10) { X265_FWRITE((analysis->interData)->interDir, sizeof(uint8_t), depthBytes, m_analysisFileOut); if (bIntraInInter) X265_FWRITE((analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFileOut); @@ -5380,7 +5433,7 @@ X265_FWRITE((analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFileOut); } } - if (m_param->analysisReuseLevel != 10) + if (m_param->analysisSaveReuseLevel != 10) X265_FWRITE((analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFileOut); } diff -r 52135ffd9bcd -r 4d870dd7c314 source/encoder/search.cpp --- a/source/encoder/search.cpp Mon Dec 23 14:40:32 2019 +0530 +++ b/source/encoder/search.cpp Mon Dec 16 17:55:07 2019 +0530 @@ -2208,7 +2208,7 @@ x265_analysis_inter_data* interDataCTU = NULL; int cuIdx; cuIdx = (interMode.cu.m_cuAddr * m_param->num4x4Partitions) + cuGeom.absPartIdx; - if (m_param->analysisReuseLevel == 10 && m_param->interRefine > 1) + if (m_param->analysisLoadReuseLevel == 10 && m_param->interRefine > 1) { interDataCTU = m_frame->m_analysisData.interData; if ((cu.m_predMode[pu.puAbsPartIdx] == interDataCTU->modes[cuIdx + pu.puAbsPartIdx]) @@ -2227,7 +2227,7 @@ cu.getNeighbourMV(puIdx, pu.puAbsPartIdx, interMode.interNeighbours); /* Uni-directional prediction */ - if ((m_param->analysisLoad && m_param->analysisReuseLevel > 1 && m_param->analysisReuseLevel != 10) + if ((m_param->analysisLoadReuseLevel > 1 && m_param->analysisLoadReuseLevel != 10) || (m_param->analysisMultiPassRefine && m_param->rc.bStatRead) || (m_param->bAnalysisType == AVC_INFO) || (useAsMVP)) { for (int list = 0; list < numPredDir; list++) diff -r 52135ffd9bcd -r 4d870dd7c314 source/x265.h --- a/source/x265.h Mon Dec 23 14:40:32 2019 +0530 +++ b/source/x265.h Mon Dec 16 17:55:07 2019 +0530 @@ -320,7 +320,7 @@ typedef enum { - NO_INFO = 0, + DEFAULT = 0, AVC_INFO = 1, HEVC_INFO = 2, }AnalysisRefineType; @@ -1656,7 +1656,7 @@ /* A value between 1 and 10 (both inclusive) determines the level of * information stored/reused in analysis save/load. Higher the refine - * level higher the information stored/reused. Default is 5 */ + * level higher the information stored/reused. Default is 5. Now deprecated. */ int analysisReuseLevel; /* Limit Sample Adaptive Offset filter computation by early terminating SAO @@ -1859,6 +1859,16 @@ /* Enable HME search ranges for L0, L1 and L2 respectively. */ int hmeRange[3]; + + /* A value between 1 and 10 (both inclusive) determines the level of + * analysis information stored in analysis-save. Higher the refine level higher + * the information stored. Default is 5 */ + int analysisSaveReuseLevel; + + /* A value between 1 and 10 (both inclusive) determines the level of + * analysis information reused in analysis-load. Higher the refine level higher + * the information reused. Default is 5 */ + int analysisLoadReuseLevel; } x265_param; /* x265_param_alloc: diff -r 52135ffd9bcd -r 4d870dd7c314 source/x265cli.h --- a/source/x265cli.h Mon Dec 23 14:40:32 2019 +0530 +++ b/source/x265cli.h Mon Dec 16 17:55:07 2019 +0530 @@ -275,7 +275,9 @@ { "no-multi-pass-opt-rps", no_argument, NULL, 0 }, { "analysis-reuse-mode", required_argument, NULL, 0 }, /* DEPRECATED */ { "analysis-reuse-file", required_argument, NULL, 0 }, - { "analysis-reuse-level", required_argument, NULL, 0 }, + { "analysis-reuse-level", required_argument, NULL, 0 }, /* DEPRECATED */ + { "analysis-save-reuse-level", required_argument, NULL, 0 }, + { "analysis-load-reuse-level", required_argument, NULL, 0 }, { "analysis-save", required_argument, NULL, 0 }, { "analysis-load", required_argument, NULL, 0 }, { "scale-factor", required_argument, NULL, 0 }, @@ -549,7 +551,9 @@ H0(" --analysis-save <filename> Dump analysis info into the specified file. Default Disabled\n"); H0(" --analysis-load <filename> Load analysis buffers from the file specified. Default Disabled\n"); H0(" --analysis-reuse-file <filename> Specify file name used for either dumping or reading analysis data. Deault x265_analysis.dat\n"); - H0(" --analysis-reuse-level <1..10> Level of analysis reuse indicates amount of info stored/reused in save/load mode, 1:least..10:most. Default %d\n", param->analysisReuseLevel); + H0(" --analysis-reuse-level <1..10> Level of analysis reuse indicates amount of info stored/reused in save/load mode, 1:least..10:most. Now deprecated. Default %d\n", param->analysisReuseLevel); + H0(" --analysis-save-reuse-level <1..10> Indicates the amount of analysis info stored in save mode, 1:least..10:most. Default %d\n", param->analysisSaveReuseLevel); + H0(" --analysis-load-reuse-level <1..10> Indicates the amount of analysis info reused in load mode, 1:least..10:most. Default %d\n", param->analysisLoadReuseLevel); H0(" --refine-analysis-type <string> Reuse anlaysis information received through API call. Supported options are avc and hevc. Default disabled - %d\n", param->bAnalysisType); H0(" --scale-factor <int> Specify factor by which input video is scaled down for analysis save mode. Default %d\n", param->scaleFactor); H0(" --refine-intra <0..4> Enable intra refinement for encode that uses analysis-load.\n"
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel