[x265] [PATCH] rdcost: [EXPERIMENTAL] allow psy-rd factor to be adjusted by CU size

Steve Borho steve at borho.org
Fri Feb 6 02:08:28 CET 2015


# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1423085727 21600
#      Wed Feb 04 15:35:27 2015 -0600
# Node ID d6386941ecfc78462b4b42c48f3575e0e47db40f
# Parent  bea0d617f62547562122399e3688e8ce34c4500f
rdcost: [EXPERIMENTAL] allow psy-rd factor to be adjusted by CU size

This commit does not change outputs, but it allows the user to tune psy-rd per
CU size. The --psy-rd-scales argument takes four floats seperated by commas with
no spaces. 1.0 implies no change from the default psy-rd scale. All values are
relative to the default psy-rd scale. 8x8, 16x16, 32x32, 64x64

The CLI option will be removed once a consensus is reached about the best depth
scaling factor(s)

diff -r bea0d617f625 -r d6386941ecfc source/common/constants.cpp
--- a/source/common/constants.cpp	Thu Feb 05 12:57:40 2015 -0600
+++ b/source/common/constants.cpp	Wed Feb 04 15:35:27 2015 -0600
@@ -119,6 +119,8 @@
     65535
 };
 
+uint32_t x265_psySizeScaleFix8[4] = { 256, 256, 256, 256 }; /* 8x8, 16x16, 32x32, 64x64 */
+
 uint32_t g_maxLog2CUSize = MAX_LOG2_CU_SIZE;
 uint32_t g_maxCUSize     = MAX_CU_SIZE;
 uint32_t g_maxFullDepth  = NUM_FULL_DEPTH - 1;
diff -r bea0d617f625 -r d6386941ecfc source/common/constants.h
--- a/source/common/constants.h	Thu Feb 05 12:57:40 2015 -0600
+++ b/source/common/constants.h	Wed Feb 04 15:35:27 2015 -0600
@@ -35,6 +35,7 @@
 extern double x265_lambda_tab[QP_MAX_MAX + 1];
 extern double x265_lambda2_tab[QP_MAX_MAX + 1];
 extern const uint16_t x265_chroma_lambda2_offset_tab[MAX_CHROMA_LAMBDA_OFFSET + 1];
+extern uint32_t x265_psySizeScaleFix8[4];
 
 enum { ChromaQPMappingTableSize = 70 };
 enum { AngleMapping422TableSize = 36 };
diff -r bea0d617f625 -r d6386941ecfc source/common/param.cpp
--- a/source/common/param.cpp	Thu Feb 05 12:57:40 2015 -0600
+++ b/source/common/param.cpp	Wed Feb 04 15:35:27 2015 -0600
@@ -640,6 +640,20 @@
         else
             p->psyRd = 0.0;
     }
+    OPT("psy-rd-scales")
+    {
+        float a8x8, a16x16, a32x32, a64x64;
+        if (4 == sscanf(value, "%f,%f,%f,%f", &a8x8, &a16x16, &a32x32, &a64x64))
+        {
+            /* float to FIX8 */
+            x265_psySizeScaleFix8[0] = (uint32_t)(a8x8 * 256.0);
+            x265_psySizeScaleFix8[1] = (uint32_t)(a16x16 * 256.0);
+            x265_psySizeScaleFix8[2] = (uint32_t)(a32x32 * 256.0);
+            x265_psySizeScaleFix8[3] = (uint32_t)(a64x64 * 256.0);
+        }
+        else
+            bError = true;
+    }
     OPT("psy-rdoq")
     {
         int bval = atobool(value);
diff -r bea0d617f625 -r d6386941ecfc source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp	Thu Feb 05 12:57:40 2015 -0600
+++ b/source/encoder/analysis.cpp	Wed Feb 04 15:35:27 2015 -0600
@@ -221,6 +221,7 @@
 
     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
+    m_rdCost.setLog2CUSize(*parentCTU.m_slice, cuGeom.log2CUSize);
 
     if (m_param->analysisMode == X265_ANALYSIS_LOAD)
     {
@@ -404,6 +405,7 @@
         slave->m_slice = m_slice;
         slave->m_frame = m_frame;
         slave->setQP(*m_slice, m_rdCost.m_qp);
+        slave->m_rdCost.setLog2CUSize(*m_slice, m_curGeom->log2CUSize);
         slave->invalidateContexts(0);
     }
 
@@ -524,6 +526,7 @@
 
     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
+    m_rdCost.setLog2CUSize(*parentCTU.m_slice, cuGeom.log2CUSize);
     uint32_t minDepth = m_param->rdLevel <= 4 ? topSkipMinDepth(parentCTU, cuGeom) : 0;
 
     X265_CHECK(m_param->rdLevel >= 2, "compressInterCU_dist does not support RD 0 or 1\n");
@@ -797,6 +800,7 @@
 
     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
+    m_rdCost.setLog2CUSize(*parentCTU.m_slice, cuGeom.log2CUSize);
     uint32_t minDepth = topSkipMinDepth(parentCTU, cuGeom);
 
     if (mightNotSplit && depth >= minDepth)
@@ -1080,6 +1084,7 @@
 
     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
+    m_rdCost.setLog2CUSize(*parentCTU.m_slice, cuGeom.log2CUSize);
 
     if (m_param->analysisMode == X265_ANALYSIS_LOAD)
     {
diff -r bea0d617f625 -r d6386941ecfc source/encoder/rdcost.h
--- a/source/encoder/rdcost.h	Thu Feb 05 12:57:40 2015 -0600
+++ b/source/encoder/rdcost.h	Wed Feb 04 15:35:27 2015 -0600
@@ -47,17 +47,7 @@
     void setQP(const Slice& slice, int qp)
     {
         m_qp = qp;
-
-        /* Scale PSY RD factor by a slice type factor */
-        static const uint32_t psyScaleFix8[3] = { 300, 256, 96 }; /* B, P, I */
-        m_psyRd = (m_psyRdBase * psyScaleFix8[slice.m_sliceType]) >> 8;
-
-        /* Scale PSY RD factor by QP, at high QP psy-rd can cause artifacts */
-        if (qp >= 40)
-        {
-            int scale = qp >= QP_MAX_SPEC ? 0 : (QP_MAX_SPEC - qp) * 23;
-            m_psyRd = (m_psyRd * scale) >> 8;
-        }
+        m_psyRd = 0;
 
         int qpCb, qpCr;
         setLambda(x265_lambda2_tab[qp], x265_lambda_tab[qp]);
@@ -78,6 +68,27 @@
         m_chromaDistWeight[1] = lambdaOffset;
     }
 
+    void setLog2CUSize(const Slice& slice, uint32_t log2CUSize)
+    {
+        X265_CHECK(log2CUSize >= 2 && log2CUSize <= 6, "CU size range check failure\n");
+
+        /* Scale PSY RD factor by a slice type factor */
+        static const uint32_t psySliceScaleFix8[3] = { 300, 256, 96 }; /* B, P, I */
+        m_psyRd = (m_psyRdBase * psySliceScaleFix8[slice.m_sliceType]) >> 8;
+
+        /* Scale PSY RD factor by a CU size */
+        m_psyRd = (m_psyRd * x265_psySizeScaleFix8[log2CUSize - 2]) >> 8;
+
+        /* Scale PSY RD factor by QP, at high QP psy-rd can cause artifacts */
+        if (m_qp >= 40)
+        {
+            int scale = m_qp >= QP_MAX_SPEC ? 0 : (QP_MAX_SPEC - m_qp) * 23;
+            m_psyRd = (m_psyRd * scale) >> 8;
+        }
+
+        /* TODO: also scale lambda by depth? */
+    }
+
     void setLambda(double lambda2, double lambda)
     {
         m_lambda2 = (uint64_t)floor(256.0 * lambda2);
@@ -86,6 +97,7 @@
 
     inline uint64_t calcRdCost(uint32_t distortion, uint32_t bits) const
     {
+        X265_CHECK(!m_psyRdBase, "setLog2CUSize() was not called\n");
         X265_CHECK(bits <= (UINT64_MAX - 128) / m_lambda2,
                    "calcRdCost wrap detected dist: %u, bits %u, lambda: "X265_LL"\n", distortion, bits, m_lambda2);
         return distortion + ((bits * m_lambda2 + 128) >> 8);
diff -r bea0d617f625 -r d6386941ecfc source/x265cli.h
--- a/source/x265cli.h	Thu Feb 05 12:57:40 2015 -0600
+++ b/source/x265cli.h	Wed Feb 04 15:35:27 2015 -0600
@@ -137,6 +137,7 @@
     { "crqpoffs",       required_argument, NULL, 0 },
     { "rd",             required_argument, NULL, 0 },
     { "psy-rd",         required_argument, NULL, 0 },
+    { "psy-rd-scales",  required_argument, NULL, 0 },
     { "psy-rdoq",       required_argument, NULL, 0 },
     { "no-psy-rd",            no_argument, NULL, 0 },
     { "no-psy-rdoq",          no_argument, NULL, 0 },
@@ -270,6 +271,8 @@
     H0("   --rd <0..6>                   Level of RD in mode decision 0:least....6:full RDO. Default %d\n", param->rdLevel);
     H0("   --[no-]psy-rd <0..2.0>        Strength of psycho-visual rate distortion optimization, 0 to disable. Default %.1f\n", param->psyRd);
     H0("   --[no-]psy-rdoq <0..50.0>     Strength of psycho-visual optimization in quantization, 0 to disable. Default %.1f\n", param->psyRdoq);
+    H0("   --psy-rd-scales <float>,<float>,<float>,<float>\n");
+    H0("                                 Adjust psy-rd factor at each CU depth (8x8 to 64x64). 1.0 implies no change, Default flat\n");
     H0("   --[no-]early-skip             Enable early SKIP detection. Default %s\n", OPT(param->bEnableEarlySkip));
     H1("   --[no-]fast-cbf               Enable early outs based on whether residual is coded. Default %s\n", OPT(param->bEnableCbfFastMode));
     H1("   --[no-]tskip-fast             Enable fast intra transform skipping. Default %s\n", OPT(param->bEnableTSkipFast));


More information about the x265-devel mailing list