[x265-commits] [x265] param: introduce warnings about measurements with psy-opt...

Steve Borho steve at borho.org
Fri May 23 04:38:04 CEST 2014


details:   http://hg.videolan.org/x265/rev/d66773c5f275
branches:  
changeset: 6911:d66773c5f275
user:      Steve Borho <steve at borho.org>
date:      Thu May 22 14:13:48 2014 -0500
description:
param: introduce warnings about measurements with psy-opts enabled

Disable psy-rd when tuning for psnr or ssim, and validate various combinations
Subject: [x265] api: allow minimum decoder level to be specified

details:   http://hg.videolan.org/x265/rev/29cc8b928868
branches:  
changeset: 6912:29cc8b928868
user:      Steve Borho <steve at borho.org>
date:      Thu May 15 15:26:58 2014 +0530
description:
api: allow minimum decoder level to be specified
Subject: [x265] rdcost: fix dc portion of psy energy calculation

details:   http://hg.videolan.org/x265/rev/8a8b04982694
branches:  
changeset: 6913:8a8b04982694
user:      Steve Borho <steve at borho.org>
date:      Thu May 22 21:21:21 2014 -0500
description:
rdcost: fix dc portion of psy energy calculation

now flat blocks have energy of 0, as expected
Subject: [x265] rdcost: use floating point math to calculate psy rd cost

details:   http://hg.videolan.org/x265/rev/0c05e3b298a5
branches:  
changeset: 6914:0c05e3b298a5
user:      Steve Borho <steve at borho.org>
date:      Thu May 22 21:28:11 2014 -0500
description:
rdcost: use floating point math to calculate psy rd cost

diffstat:

 doc/reST/cli.rst         |  16 +++++++++++++
 doc/reST/presets.rst     |   4 +-
 source/CMakeLists.txt    |   2 +-
 source/common/param.cpp  |  45 +++++++++++++++++++++++++++++++++++++
 source/encoder/api.cpp   |   1 +
 source/encoder/level.cpp |  58 ++++++++++++++++++++++++++++-------------------
 source/encoder/level.h   |   2 +-
 source/encoder/rdcost.h  |  21 ++++++----------
 source/x265.cpp          |   2 +
 source/x265.h            |  10 ++++++++
 10 files changed, 120 insertions(+), 41 deletions(-)

diffs (truncated from 363 to 300 lines):

diff -r 73e8188a48ca -r 0c05e3b298a5 doc/reST/cli.rst
--- a/doc/reST/cli.rst	Thu May 22 08:51:36 2014 -0500
+++ b/doc/reST/cli.rst	Thu May 22 21:28:11 2014 -0500
@@ -520,6 +520,22 @@ Slice decision options
 
 	Use B-frames as references, when possible. Default enabled
 
+.. option:: --level <integer|float>
+
+	Minimum decoder requirement level. Defaults to -1, which implies
+	auto-detection by the encoder. If specified, the encoder will
+	attempt to bring the encode specifications within that specified
+	level. If the encoder is unable to reach the level it issues a
+	warning and emits the actual decoder requirement. If the requested
+	requirement level is higher than the actual level, the actual
+	requirement level is signaled.
+
+	The value is specified as a float or as an integer with the level
+	times 10, for example level **5.1** is specified as "5.1" or "51",
+	and level **5.0** is specified as "5.0" or "50".
+
+	Annex A levels: 1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 5.2, 6, 6.1, 6.2
+
 Quality, rate control and rate distortion options
 =================================================
 
diff -r 73e8188a48ca -r 0c05e3b298a5 doc/reST/presets.rst
--- a/doc/reST/presets.rst	Thu May 22 08:51:36 2014 -0500
+++ b/doc/reST/presets.rst	Thu May 22 21:28:11 2014 -0500
@@ -86,9 +86,9 @@ after the preset.
 +--------------+-----------------------------------------------------+
 | --tune       | effect                                              |
 +==============+=====================================================+
-| psnr         | disables adaptive quant and cutree                  |
+| psnr         | disables adaptive quant, psy-rd, and cutree         |
 +--------------+-----------------------------------------------------+
-| ssim         | enables adaptive quant auto-mode                    |
+| ssim         | enables adaptive quant auto-mode, disables psy-rd   |
 +--------------+-----------------------------------------------------+
 | fastdecode   | no loop filters, no weighted pred, no intra in B    |
 +--------------+-----------------------------------------------------+
diff -r 73e8188a48ca -r 0c05e3b298a5 source/CMakeLists.txt
--- a/source/CMakeLists.txt	Thu May 22 08:51:36 2014 -0500
+++ b/source/CMakeLists.txt	Thu May 22 21:28:11 2014 -0500
@@ -19,7 +19,7 @@ include(CheckSymbolExists)
 include(CheckCXXCompilerFlag)
 
 # X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 19)
+set(X265_BUILD 20)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 73e8188a48ca -r 0c05e3b298a5 source/common/param.cpp
--- a/source/common/param.cpp	Thu May 22 08:51:36 2014 -0500
+++ b/source/common/param.cpp	Thu May 22 21:28:11 2014 -0500
@@ -107,6 +107,7 @@ void x265_param_default(x265_param *para
     /* Source specifications */
     param->internalBitDepth = x265_max_bit_depth;
     param->internalCsp = X265_CSP_I420;
+    param->levelIdc = -1;
 
     /* CU definitions */
     param->maxCUSize = 64;
@@ -375,10 +376,12 @@ int x265_param_default_preset(x265_param
         if (!strcmp(tune, "psnr"))
         {
             param->rc.aqStrength = 0.0;
+            param->psyRd = 0.0;
         }
         else if (!strcmp(tune, "ssim"))
         {
             param->rc.aqMode = X265_AQ_AUTO_VARIANCE;
+            param->psyRd = 0.0;
         }
         else if (!strcmp(tune, "fastdecode") ||
                  !strcmp(tune, "fast-decode"))
@@ -527,6 +530,14 @@ int x265_param_parse(x265_param *p, cons
     OPT("csv") p->csvfn = value;
     OPT("threads") p->poolNumThreads = atoi(value);
     OPT("frame-threads") p->frameNumThreads = atoi(value);
+    OPT2("level-idc", "level")
+    {
+        /* allow "5.1" or "51", both converted to integer 51 */
+        if (atof(value) < 7)
+            p->levelIdc = (int)(10 * atof(value) + .5);
+        else
+            p->levelIdc = atoi(value);
+    }
     OPT2("log-level", "log")
     {
         p->logLevel = atoi(value);
@@ -857,6 +868,40 @@ int x265_check_params(x265_param *param)
           "x265 was compiled for 8bit encodes, only 8bit internal depth supported");
 #endif
 
+    if (param->rdLevel < 5)
+        param->psyRd = 0;
+    if (param->rc.aqStrength == 0)
+        param->rc.aqMode = 0;
+    if (param->logLevel < X265_LOG_INFO)
+    {
+        /* don't measure these metrics if they will not be reported */
+        param->bEnablePsnr = 0;
+        param->bEnableSsim = 0;
+    }
+    /* Warn users trying to measure PSNR/SSIM with psy opts on. */
+    if (param->bEnablePsnr || param->bEnableSsim)
+    {
+        const char *s = NULL;
+
+        if (param->psyRd != 0)
+        {
+            s = param->bEnablePsnr ? "psnr" : "ssim";
+            x265_log(param, X265_LOG_WARNING, "--%s used with psy on: results will be invalid!\n", s);
+        }
+        else if (!param->rc.aqMode && param->bEnableSsim)
+        {
+            x265_log(param, X265_LOG_WARNING, "--ssim used with AQ off: results will be invalid!\n");
+            s = "ssim";
+        }
+        else if (param->rc.aqMode && param->bEnablePsnr)
+        {
+            x265_log(param, X265_LOG_WARNING, "--psnr used with AQ on: results will be invalid!\n");
+            s = "psnr";
+        }
+        if (s)
+            x265_log(param, X265_LOG_WARNING, "--tune %s should be used if attempting to benchmark %s!\n", s, s);
+    }
+
     CHECK(param->rc.qp < -6 * (param->internalBitDepth - 8) || param->rc.qp > 51,
           "QP exceeds supported range (-QpBDOffsety to 51)");
     CHECK(param->fpsNum == 0 || param->fpsDenom == 0,
diff -r 73e8188a48ca -r 0c05e3b298a5 source/encoder/api.cpp
--- a/source/encoder/api.cpp	Thu May 22 08:51:36 2014 -0500
+++ b/source/encoder/api.cpp	Thu May 22 21:28:11 2014 -0500
@@ -56,6 +56,7 @@ x265_encoder *x265_encoder_open(x265_par
     {
         // these may change params for auto-detect, etc
         encoder->configure(param);
+        enforceLevel(*param);
         determineLevel(*param, encoder->m_profile, encoder->m_level, encoder->m_levelTier);
 
         x265_print_params(param);
diff -r 73e8188a48ca -r 0c05e3b298a5 source/encoder/level.cpp
--- a/source/encoder/level.cpp	Thu May 22 08:51:36 2014 -0500
+++ b/source/encoder/level.cpp	Thu May 22 21:28:11 2014 -0500
@@ -35,25 +35,26 @@ typedef struct
     uint32_t minCompressionRatio;
     Level::Name levelEnum;
     const char* name;
+    int levelIdc;
 } LevelSpec;
 
 LevelSpec levels[] =
 {
-    { MAX_UINT, MAX_UINT,   MAX_UINT, MAX_UINT, 0, Level::NONE,     "none" },
-    { 36864,    552960,     128,      MAX_UINT, 2, Level::LEVEL1,   "1" },
-    { 122880,   3686400,    1500,     MAX_UINT, 2, Level::LEVEL2,   "2" },
-    { 245760,   7372800,    3000,     MAX_UINT, 2, Level::LEVEL2_1, "2.1" },
-    { 552960,   16588800,   6000,     MAX_UINT, 2, Level::LEVEL3,   "3" },
-    { 983040,   33177600,   10000,    MAX_UINT, 2, Level::LEVEL3_1, "3.1" },
-    { 2228224,  66846720,   12000,    30000,    4, Level::LEVEL4,   "4" },
-    { 2228224,  133693440,  20000,    50000,    4, Level::LEVEL4_1, "4.1" },
-    { 8912896,  267386880,  25000,    100000,   6, Level::LEVEL5,   "5" },
-    { 8912896,  534773760,  40000,    160000,   8, Level::LEVEL5_1, "5.1" },
-    { 8912896,  1069547520, 60000,    240000,   8, Level::LEVEL5_2, "5.2" },
-    { 35651584, 1069547520, 60000,    240000,   8, Level::LEVEL6,   "6" },
-    { 35651584, 2139095040, 120000,   480000,   8, Level::LEVEL6_1, "6.1" },
-    { 35651584, 4278190080U, 240000,  800000,   6, Level::LEVEL6_2, "6.2" },
-    { 0, 0, 0, 0, 0, Level::NONE, "\0" }
+    { MAX_UINT, MAX_UINT,   MAX_UINT, MAX_UINT, 0, Level::NONE,     "none", 0 },
+    { 36864,    552960,     128,      MAX_UINT, 2, Level::LEVEL1,   "1",   10 },
+    { 122880,   3686400,    1500,     MAX_UINT, 2, Level::LEVEL2,   "2",   20 },
+    { 245760,   7372800,    3000,     MAX_UINT, 2, Level::LEVEL2_1, "2.1", 21 },
+    { 552960,   16588800,   6000,     MAX_UINT, 2, Level::LEVEL3,   "3",   30 },
+    { 983040,   33177600,   10000,    MAX_UINT, 2, Level::LEVEL3_1, "3.1", 31 },
+    { 2228224,  66846720,   12000,    30000,    4, Level::LEVEL4,   "4",   40 },
+    { 2228224,  133693440,  20000,    50000,    4, Level::LEVEL4_1, "4.1", 41 },
+    { 8912896,  267386880,  25000,    100000,   6, Level::LEVEL5,   "5",   50 },
+    { 8912896,  534773760,  40000,    160000,   8, Level::LEVEL5_1, "5.1", 51 },
+    { 8912896,  1069547520, 60000,    240000,   8, Level::LEVEL5_2, "5.2", 52 },
+    { 35651584, 1069547520, 60000,    240000,   8, Level::LEVEL6,   "6",   60 },
+    { 35651584, 2139095040, 120000,   480000,   8, Level::LEVEL6_1, "6.1", 61 },
+    { 35651584, 4278190080U, 240000,  800000,   6, Level::LEVEL6_2, "6.2", 62 },
+    { 0, 0, 0, 0, 0, Level::NONE, "\0", 0 }
 };
 
 /* determine minimum decoder level requiremented to decode the described video */
@@ -82,7 +83,7 @@ void determineLevel(const x265_param &pa
 
     uint32_t lumaSamples = param.sourceWidth * param.sourceHeight;
     uint32_t samplesPerSec = (uint32_t)(lumaSamples * ((double)param.fpsNum / param.fpsDenom));
-    uint32_t bitrate = param.rc.bitrate; /* TODO: vbv-maxrate? */
+    uint32_t bitrate = param.rc.bitrate ? param.rc.bitrate : param.rc.vbvMaxBitrate;
 
     /* TODO; Keep in sync with encoder.cpp, or pass in maxDecPicBuffering */
     int numReorderPics = (param.bBPyramid && param.bframes > 1) ? 2 : 1;
@@ -145,12 +146,26 @@ void determineLevel(const x265_param &pa
  * decoder meeting this level of requirement.  Some parameters (resolution and
  * frame rate) are non-negotiable and thus this function may fail. In those
  * circumstances it will be quite noisy */
-void enforceLevel(x265_param& param, int level, bool bHighTier)
+void enforceLevel(x265_param& param)
 {
+    if (param.levelIdc < 0)
+        return;
+
     uint32_t lumaSamples = param.sourceWidth * param.sourceHeight;
     uint32_t samplesPerSec = (uint32_t)(lumaSamples * ((double)param.fpsNum / param.fpsDenom));
+    int level = 1;
+    while (levels[level].levelIdc < param.levelIdc && levels[level].levelIdc)
+        level++;
     LevelSpec& l = levels[level];
 
+    if (!l.levelIdc)
+    {
+        x265_log(&param, X265_LOG_WARNING, "specified level does not exist\n");
+        return;
+    }
+    if (l.levelIdc != param.levelIdc)
+        x265_log(&param, X265_LOG_WARNING, "Using nearest matching level %s\n", l.name);
+
     bool ok = true;
 
     if (lumaSamples > l.maxLumaSamples)
@@ -164,16 +179,11 @@ void enforceLevel(x265_param& param, int
     else if (samplesPerSec > l.maxLumaSamplesPerSecond)
         x265_log(&param, X265_LOG_WARNING, "frame rate is out of range for specified level\n");
 
-    if (bHighTier && param.rc.bitrate > (int)l.maxBitrateHigh && l.maxBitrateHigh != MAX_UINT)
+    if (param.rc.bitrate > (int)l.maxBitrateHigh && l.maxBitrateHigh != MAX_UINT)
     {
         param.rc.bitrate = l.maxBitrateHigh;
         x265_log(&param, X265_LOG_INFO, "Lowering target bitrate to High tier limit of %dKbps\n", param.rc.bitrate);
     }
-    else if (!bHighTier && param.rc.bitrate > (int)l.maxBitrateMain)
-    {
-        param.rc.bitrate = l.maxBitrateMain;
-        x265_log(&param, X265_LOG_INFO, "Lowering target bitrate to Main tier limit of %dKbps\n", param.rc.bitrate);
-    }
 
     const int MaxDpbPicBuf = 6;
     int maxDpbSize = MaxDpbPicBuf;
@@ -198,7 +208,7 @@ void enforceLevel(x265_param& param, int
 
     if (param.maxNumReferences != savedRefCount)
     {
-        x265_log(&param, X265_LOG_INFO, "Lowering max references to %d\n", param.maxNumReferences);
+        x265_log(&param, X265_LOG_INFO, "Lowering max references to %d to meet level requirement\n", param.maxNumReferences);
     }
 }
 }
diff -r 73e8188a48ca -r 0c05e3b298a5 source/encoder/level.h
--- a/source/encoder/level.h	Thu May 22 08:51:36 2014 -0500
+++ b/source/encoder/level.h	Thu May 22 21:28:11 2014 -0500
@@ -30,7 +30,7 @@
 
 namespace x265 {
 void determineLevel(const x265_param &param, Profile::Name& profile, Level::Name& level, Level::Tier& tier);
-void enforceLevel(x265_param& param, int level, bool bHighTier);
+void enforceLevel(x265_param& param);
 }
 
 #endif // ifndef X265_LEVEL_H
diff -r 73e8188a48ca -r 0c05e3b298a5 source/encoder/rdcost.h
--- a/source/encoder/rdcost.h	Thu May 22 08:51:36 2014 -0500
+++ b/source/encoder/rdcost.h	Thu May 22 21:28:11 2014 -0500
@@ -41,7 +41,7 @@ private:
 
     uint64_t  m_crDistortionWeight;
 
-    uint64_t  m_psyRdScale; // Psy RD strength w/ 8 bits of fraction
+    double    m_psyRdScale;
 
 public:
 
@@ -65,12 +65,12 @@ public:
 
     void setPsyRdScale(double scale)
     {
-        m_psyRdScale = (uint64_t)floor(256.0 * scale);
+        m_psyRdScale = scale;
     }
 
     inline bool psyRdEnabled() const
     {
-        return !!m_psyRdScale;
+        return m_psyRdScale != 0;
     }
 
     inline uint64_t calcRdCost(uint32_t distortion, uint32_t bits)
@@ -84,11 +84,10 @@ public:
     /* return the difference in energy between the source block and the recon block */
     inline uint32_t psyCost(int size, pixel *source, intptr_t sstride, pixel *recon, intptr_t rstride)
     {
-        int pixelCountShift = (size + 2) * 2 - 1; // width * height / satd-scale(2)
-        int sdc = primitives.sad_square[size](source, sstride, (pixel*)zeroPel, MAX_CU_SIZE) >> pixelCountShift;
+        int sdc = primitives.sad_square[size](source, sstride, (pixel*)zeroPel, MAX_CU_SIZE) >> 2;
         int sEnergy = primitives.sa8d[size](source, sstride, (pixel*)zeroPel, MAX_CU_SIZE) - sdc;


More information about the x265-commits mailing list