<div>In fact, this skip is not a fast skip algorithm.</div><div>As the sum of split cost is larger than none split CU's best cost (both rdcost of sub-cu and none split CU are without split flag cost), which means splitting into 4 parts at this depth of cu is a worse case compared with none split CU. So that, the remain N * 1/4 parts of CU analysis is useless.</div><div><br></div><div>....................</div><div>.    A   .    B   .</div><div>.         .         .</div><div>....................</div><div>.    C   .    D   .</div><div>.         .         .</div><div>....................   (A B C D is the 4 parts of a CU)</div><div>If sum of sub CU split cost(A_Cost + B_Cost) larger than non-split cost(NSCost), assume  NSCost < A_Cost + B_Cost, the remain parts (C, D) continue to analysis rd. </div><div>C_Cost + D_Cost >= 0 ---></div><div>NSCost < A_Cost + B_Cost + C_Cost + D_Cost ---> (likely that)</div><div>NSCost + splitCost(splitflag = 0) < A_Cost + B_Cost + C_Cost + D_Cost + splitCost(splitflag = 1)  ---> choose none split</div><div><br></div><div>So, C and D rd analysis can be skipped.</div><div>So in my test cases, the MD5 checksum of the output bitstream is the same with the original after this skip.</div><div><br></div><div><div style="font-size: 12px;font-family: Arial Narrow;padding:2px 0 2px 0;">------------------ Original ------------------</div><div style="font-size: 12px;background:#efefef;padding:8px;"><div><b>From: </b> "Ximing Cheng";<chengximing1989@foxmail.com>;</div><div><b>Send time:</b> Friday, Aug 4, 2017 1:56 AM</div><div><b>To:</b> "x265-devel"<x265-devel@videolan.org>; <wbr></div><div></div><div><b>Subject: </b> [x265] [PATCH] intra: skip RD analysis when sum of sub CUsplitcostbigger than non-split cost</div></div><div><br></div># HG changeset patch<br># User Ximing Cheng <ximingcheng@tencent.com><br># Date 1501782508 -28800<br>#      Fri Aug 04 01:48:28 2017 +0800<br># Node ID 5943a1f73d5814a3a723f814a4dd0635b1fe2b35<br># Parent  d11482e5fedbcdaf62ee3c6872f43827d99ad181<br>intra: skip RD analysis when sum of sub CUsplitcost bigger than non-split cost<br><br>diff -r d11482e5fedb -r 5943a1f73d58 source/CMakeLists.txt<br>--- a/source/CMakeLists.txt    Mon Jul 24 11:15:38 2017 +0530<br>+++ b/source/CMakeLists.txt     Fri Aug 04 01:48:28 2017 +0800<br>@@ -29,7 +29,7 @@<br> option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br> mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br> # X265_BUILD must be incremented each time the public API is changed<br>-set(X265_BUILD 131)<br>+set(X265_BUILD 132)<br> configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"<br>                "${PROJECT_BINARY_DIR}/x265.def")<br> configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"<br>diff -r d11482e5fedb -r 5943a1f73d58 source/common/param.cpp<br>--- a/source/common/param.cpp    Mon Jul 24 11:15:38 2017 +0530<br>+++ b/source/common/param.cpp   Fri Aug 04 01:48:28 2017 +0800<br>@@ -157,6 +157,7 @@<br>     param->bEnableConstrainedIntra = 0;<br>     param->bEnableStrongIntraSmoothing = 1;<br>     param->bEnableFastIntra = 0;<br>+    param->bEnableSplitRdSkip = 0;<br> <br>     /* Inter Coding tools */<br>     param->searchMethod = X265_HEX_SEARCH;<br>@@ -975,6 +976,7 @@<br>         OPT("refine-inter")p->interRefine = atobool(value);<br>         OPT("refine-mv")p->mvRefine = atobool(value);<br>         OPT("force-flush")p->forceFlush = atoi(value);<br>+        OPT("splitrd-skip") p->bEnableSplitRdSkip = atobool(value);<br>         else<br>             return X265_PARAM_BAD_NAME;<br>     }<br>@@ -1431,6 +1433,7 @@<br>     TOOLOPT(param->bEnableRdRefine, "rd-refine");<br>     TOOLOPT(param->bEnableEarlySkip, "early-skip");<br>     TOOLOPT(param->bEnableRecursionSkip, "rskip");<br>+    TOOLOPT(param->bEnableSplitRdSkip, "splitrd-skip");<br>     TOOLVAL(param->noiseReductionIntra, "nr-intra=%d");<br>     TOOLVAL(param->noiseReductionInter, "nr-inter=%d");<br>     TOOLOPT(param->bEnableTSkipFast, "tskip-fast");<br>@@ -1560,6 +1563,7 @@<br>     BOOL(p->bEnableTSkipFast, "tskip-fast");<br>     BOOL(p->bCULossless, "cu-lossless");<br>     BOOL(p->bIntraInBFrames, "b-intra");<br>+    BOOL(p->bEnableSplitRdSkip, "splitrd-skip");<br>     s += sprintf(s, " rdpenalty=%d", p->rdPenalty);<br>     s += sprintf(s, " psy-rd=%.2f", p->psyRd);<br>     s += sprintf(s, " psy-rdoq=%.2f", p->psyRdoq);<br>diff -r d11482e5fedb -r 5943a1f73d58 source/encoder/analysis.cpp<br>--- a/source/encoder/analysis.cpp       Mon Jul 24 11:15:38 2017 +0530<br>+++ b/source/encoder/analysis.cpp       Fri Aug 04 01:48:28 2017 +0800<br>@@ -485,7 +485,7 @@<br>     md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);<br> }<br> <br>-void Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp)<br>+uint64_t Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp)<br> {<br>     uint32_t depth = cuGeom.depth;<br>     ModeDepth& md = m_modeDepth[depth];<br>@@ -560,6 +560,8 @@<br>         invalidateContexts(nextDepth);<br>         Entropy* nextContext = &m_rqt[depth].cur;<br>         int32_t nextQP = qp;<br>+        uint64_t curCost = 0;<br>+        int skipSplitCheck = 0;<br> <br>         for (uint32_t subPartIdx = 0; subPartIdx < 4; subPartIdx++)<br>         {<br>@@ -572,7 +574,17 @@<br>                 if (m_slice->m_pps->bUseDQP && nextDepth <= m_slice->m_pps->maxCuDQPDepth)<br>                     nextQP = setLambdaFromQP(parentCTU, calculateQpforCuSize(parentCTU, childGeom));<br> <br>-                compressIntraCU(parentCTU, childGeom, nextQP);<br>+                if (m_param->bEnableSplitRdSkip)<br>+                {<br>+                    curCost += compressIntraCU(parentCTU, childGeom, nextQP);<br>+                    if (m_modeDepth[depth].bestMode && curCost > m_modeDepth[depth].bestMode->rdCost)<br>+                    {<br>+                        skipSplitCheck = 1;<br>+                        break;<br>+                    }<br>+                }<br>+                else<br>+                    compressIntraCU(parentCTU, childGeom, nextQP);<br> <br>                 // Save best CU and pred data for this sub CU<br>                 splitCU->copyPartFrom(nd.bestMode->cu, childGeom, subPartIdx);<br>@@ -590,14 +602,17 @@<br>                     memset(parentCTU.m_cuDepth + childGeom.absPartIdx, 0, childGeom.numPartitions);<br>             }<br>         }<br>-        nextContext->store(splitPred->contexts);<br>-        if (mightNotSplit)<br>-            addSplitFlagCost(*splitPred, cuGeom.depth);<br>-        else<br>-            updateModeCost(*splitPred);<br>-<br>-        checkDQPForSplitPred(*splitPred, cuGeom);<br>-        checkBestMode(*splitPred, depth);<br>+        if (!skipSplitCheck)<br>+        {<br>+            nextContext->store(splitPred->contexts);<br>+            if (mightNotSplit)<br>+                addSplitFlagCost(*splitPred, cuGeom.depth);<br>+            else<br>+                updateModeCost(*splitPred);<br>+<br>+            checkDQPForSplitPred(*splitPred, cuGeom);<br>+            checkBestMode(*splitPred, depth);<br>+        }<br>     }<br> <br>     if (m_param->bEnableRdRefine && depth <= m_slice->m_pps->maxCuDQPDepth)<br>@@ -620,6 +635,8 @@<br>     md.bestMode->cu.copyToPic(depth);<br>     if (md.bestMode != &md.pred[PRED_SPLIT])<br>         md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>+<br>+    return md.bestMode->rdCost;<br> }<br> <br> void Analysis::PMODE::processTasks(int workerThreadId)<br>diff -r d11482e5fedb -r 5943a1f73d58 source/encoder/analysis.h<br>--- a/source/encoder/analysis.h     Mon Jul 24 11:15:38 2017 +0530<br>+++ b/source/encoder/analysis.h Fri Aug 04 01:48:28 2017 +0800<br>@@ -145,7 +145,7 @@<br>     void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t lqp);<br> <br>     /* full analysis for an I-slice CU */<br>-    void compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);<br>+    uint64_t compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);<br> <br>     /* full analysis for a P or B slice CU */<br>     uint32_t compressInterCU_dist(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);<br>diff -r d11482e5fedb -r 5943a1f73d58 source/x265.h<br>--- a/source/x265.h Mon Jul 24 11:15:38 2017 +0530<br>+++ b/source/x265.h     Fri Aug 04 01:48:28 2017 +0800<br>@@ -1482,6 +1482,9 @@<br> <br>     /* Force flushing the frames from encoder */<br>     int       forceFlush;<br>+<br>+    /* Enable skipping split RD analysis when sum of split CU rdCost larger than none split CU rdCost for Intra CU */<br>+    int       bEnableSplitRdSkip;<br> } x265_param;<br> <br> /* x265_param_alloc:<br>diff -r d11482e5fedb -r 5943a1f73d58 source/x265cli.h<br>--- a/source/x265cli.h   Mon Jul 24 11:15:38 2017 +0530<br>+++ b/source/x265cli.h  Fri Aug 04 01:48:28 2017 +0800<br>@@ -281,6 +281,8 @@<br>     { "refine-mv",            no_argument, NULL, 0 },<br>     { "no-refine-mv",         no_argument, NULL, 0 },<br>     { "force-flush",    required_argument, NULL, 0 },<br>+    { "splitrd-skip",         no_argument, NULL, 0 },<br>+    { "no-splitrd-skip",      no_argument, NULL, 0 },<br>     { 0, 0, 0, 0 },<br>     { 0, 0, 0, 0 },<br>     { 0, 0, 0, 0 },<br>@@ -375,6 +377,7 @@<br>     H0("   --[no-]early-skip             Enable early SKIP detection. Default %s\n", OPT(param->bEnableEarlySkip));<br>     H0("   --[no-]rskip                  Enable early exit from recursion. Default %s\n", OPT(param->bEnableRecursionSkip));<br>     H1("   --[no-]tskip-fast             Enable fast intra transform skipping. Default %s\n", OPT(param->bEnableTSkipFast));<br>+    H1("   --[no-]splitrd-skip           Enable skipping split RD analysis when sum of split CU rdCost larger than none split CU rdCost for Intra CU. Default %s\n", OPT(param->bEnableSplitRdSkip));<br>     H1("   --nr-intra <integer>          An integer value in range of 0 to 2000, which denotes strength of noise reduction in intra CUs. Default 0\n");<br>     H1("   --nr-inter <integer>          An integer value in range of 0 to 2000, which denotes strength of noise reduction in inter CUs. Default 0\n");<br>     H0("   --ctu-info <integer>          Enable receiving ctu information asynchronously and determine reaction to the CTU information (0, 1, 2, 4, 6) Default 0\n"<br><br><br>_______________________________________________<br>x265-devel mailing list<br>x265-devel@videolan.org<br>https://mailman.videolan.org/listinfo/x265-devel<br></div>