[x265] [PATCH] api: allow minimum decoder level to be specified
Steve Borho
steve at borho.org
Thu May 22 18:54:25 CEST 2014
# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1400147818 -19800
# Thu May 15 15:26:58 2014 +0530
# Node ID ed0cdcbce1659a0bffcae7a5c9f90006a3ec5bd4
# Parent 73e8188a48cabe3366b14dab97a8da282fb9d02a
api: allow minimum decoder level to be specified
diff -r 73e8188a48ca -r ed0cdcbce165 doc/reST/cli.rst
--- a/doc/reST/cli.rst Thu May 22 08:51:36 2014 -0500
+++ b/doc/reST/cli.rst Thu May 15 15:26:58 2014 +0530
@@ -520,6 +520,22 @@
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 an specified as 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 ed0cdcbce165 source/common/param.cpp
--- a/source/common/param.cpp Thu May 22 08:51:36 2014 -0500
+++ b/source/common/param.cpp Thu May 15 15:26:58 2014 +0530
@@ -107,6 +107,7 @@
/* Source specifications */
param->internalBitDepth = x265_max_bit_depth;
param->internalCsp = X265_CSP_I420;
+ param->levelIdc = -1;
/* CU definitions */
param->maxCUSize = 64;
@@ -527,6 +528,14 @@
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);
diff -r 73e8188a48ca -r ed0cdcbce165 source/encoder/api.cpp
--- a/source/encoder/api.cpp Thu May 22 08:51:36 2014 -0500
+++ b/source/encoder/api.cpp Thu May 15 15:26:58 2014 +0530
@@ -56,6 +56,7 @@
{
// 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 ed0cdcbce165 source/encoder/level.cpp
--- a/source/encoder/level.cpp Thu May 22 08:51:36 2014 -0500
+++ b/source/encoder/level.cpp Thu May 15 15:26:58 2014 +0530
@@ -35,25 +35,26 @@
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 @@
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 @@
* 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 @@
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 @@
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 ed0cdcbce165 source/encoder/level.h
--- a/source/encoder/level.h Thu May 22 08:51:36 2014 -0500
+++ b/source/encoder/level.h Thu May 15 15:26:58 2014 +0530
@@ -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 ed0cdcbce165 source/x265.cpp
--- a/source/x265.cpp Thu May 22 08:51:36 2014 -0500
+++ b/source/x265.cpp Thu May 15 15:26:58 2014 +0530
@@ -69,6 +69,7 @@
{ "tune", required_argument, NULL, 't' },
{ "frame-threads", required_argument, NULL, 'F' },
{ "log-level", required_argument, NULL, 0 },
+ { "level", required_argument, NULL, 0 },
{ "csv", required_argument, NULL, 0 },
{ "y4m", no_argument, NULL, 0 },
{ "no-progress", no_argument, NULL, 0 },
@@ -317,6 +318,7 @@
H0(" --nr <integer> An integer value in range of 100 to 1000, which denotes strength of noise reduction. Default disabled\n");
H0(" --input-res WxH Source picture size [w x h], auto-detected if Y4M\n");
H0(" --input-csp <string> Source color space: i420, i444 or i422, auto-detected if Y4M. Default: i420\n");
+ H0(" --level <integer|float> Force a minumum required decoder level (as '5.0' or '50')\n");
H0(" --fps <float|rational> Source frame rate (float or num/denom), auto-detected if Y4M\n");
H0(" --[no-]interlace <bff|tff> Indicate input pictures are interlace fields in temporal order. Default progressive\n");
H0(" --seek <integer> First frame to encode\n");
diff -r 73e8188a48ca -r ed0cdcbce165 source/x265.h
--- a/source/x265.h Thu May 22 08:51:36 2014 -0500
+++ b/source/x265.h Thu May 15 15:26:58 2014 +0530
@@ -386,6 +386,16 @@
* minimum requirement. All valid HEVC heights are supported */
int sourceHeight;
+ /* 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
+ * an specified as an integer with the level times 10, for example level
+ * "5.1" is specified as 51, and level "5.0" is specified as 50. */
+ int levelIdc;
+
/* Interlace type of source pictures. 0 - progressive pictures (default).
* 1 - top field first, 2 - bottom field first. HEVC encodes interlaced
* content as fields, they must be provided to the encoder in the correct
More information about the x265-devel
mailing list