[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(¶m, X265_LOG_WARNING, "specified level does not exist\n");
+ return;
+ }
+ if (l.levelIdc != param.levelIdc)
+ x265_log(¶m, 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(¶m, 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(¶m, 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(¶m, 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(¶m, X265_LOG_INFO, "Lowering max references to %d\n", param.maxNumReferences);
+ x265_log(¶m, 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 ¶m, 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