[x265-commits] [x265] api: allow lambda tables to be user-specified via a text ...
Steve Borho
steve at borho.org
Thu Jul 3 06:48:30 CEST 2014
details: http://hg.videolan.org/x265/rev/44dc246b7835
branches:
changeset: 7224:44dc246b7835
user: Steve Borho <steve at borho.org>
date: Wed Jul 02 17:21:02 2014 -0500
description:
api: allow lambda tables to be user-specified via a text file
This change allows easy experimentation with the lambda tables. One can
cut-paste the existing tables from TComRom.cpp into a text file and hash(#)
comment the C constructs (variable names and braces) and arrive at a functional
lambda file, then edit to taste.
Subject: [x265] simplify: getLumaIntraDir()[x] -> getLumaIntraDir(x)
details: http://hg.videolan.org/x265/rev/959ff37cdd31
branches:
changeset: 7225:959ff37cdd31
user: Min Chen <chenm003 at 163.com>
date: Wed Jul 02 15:54:58 2014 -0700
description:
simplify: getLumaIntraDir()[x] -> getLumaIntraDir(x)
Subject: [x265] lambda-file: detect and report if lamda file containts too many values
details: http://hg.videolan.org/x265/rev/0013dbcac349
branches:
changeset: 7226:0013dbcac349
user: Steve Borho <steve at borho.org>
date: Wed Jul 02 18:03:10 2014 -0500
description:
lambda-file: detect and report if lamda file containts too many values
It seems likely that this is an unintended error the user would want to be
made aware of.
Subject: [x265] lamba-file: make improper number of constants a fatal error
details: http://hg.videolan.org/x265/rev/1e94a2b12d15
branches:
changeset: 7227:1e94a2b12d15
user: Steve Borho <steve at borho.org>
date: Wed Jul 02 18:09:20 2014 -0500
description:
lamba-file: make improper number of constants a fatal error
Having an invalid set of lambdas is likelty to be completely useless
diffstat:
doc/reST/cli.rst | 20 ++++++++++
source/CMakeLists.txt | 2 +-
source/Lib/TLibCommon/TComRom.cpp | 4 +-
source/Lib/TLibCommon/TComRom.h | 4 +-
source/Lib/TLibEncoder/TEncCu.cpp | 8 ++--
source/common/param.cpp | 73 +++++++++++++++++++++++++++++++++++++++
source/common/param.h | 1 +
source/encoder/encoder.cpp | 2 +
source/x265.cpp | 5 ++
source/x265.h | 8 ++++
10 files changed, 118 insertions(+), 9 deletions(-)
diffs (271 lines):
diff -r b90fdc3ffb96 -r 1e94a2b12d15 doc/reST/cli.rst
--- a/doc/reST/cli.rst Wed Jul 02 14:31:51 2014 -0500
+++ b/doc/reST/cli.rst Wed Jul 02 18:09:20 2014 -0500
@@ -274,6 +274,26 @@ Input Options
Specifying QP (integer) is optional, and if specified they are
clamped within the encoder to qpmin/qpmax.
+.. option:: --lambda-file <filename>
+
+ Specify a text file containing values for x265_lambda_tab and
+ x265_lambda2_tab. Each table requires MAX_MAX_QP+1 (70) float
+ values.
+
+ The text file syntax is simple. Comma is considered to be
+ white-space. All white-space is ignored. Lines must be less than 2k
+ bytes in length. Content following hash (#) characters are ignored.
+ The values read from the file are logged at :option:`--log-level`
+ debug.
+
+ Note that the lambda tables are process-global and so the new values
+ affect all encoders running in the same process.
+
+ Lambda values affect encoder mode decisions, the lower the lambda
+ the more bits it will try to spend on signaling information (motion
+ vectors and splits) and less on residual. This feature is intended
+ for experimentation.
+
Quad-Tree analysis
==================
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/CMakeLists.txt
--- a/source/CMakeLists.txt Wed Jul 02 14:31:51 2014 -0500
+++ b/source/CMakeLists.txt Wed Jul 02 18:09:20 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 24)
+set(X265_BUILD 25)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/Lib/TLibCommon/TComRom.cpp
--- a/source/Lib/TLibCommon/TComRom.cpp Wed Jul 02 14:31:51 2014 -0500
+++ b/source/Lib/TLibCommon/TComRom.cpp Wed Jul 02 18:09:20 2014 -0500
@@ -124,7 +124,7 @@ public:
};
// lambda = pow(2, (double)q / 6 - 2);
-const double x265_lambda_tab[MAX_MAX_QP + 1] =
+double x265_lambda_tab[MAX_MAX_QP + 1] =
{
0.2500, 0.2806, 0.3150, 0.3536, 0.3969,
0.4454, 0.5000, 0.5612, 0.6300, 0.7071,
@@ -143,7 +143,7 @@ const double x265_lambda_tab[MAX_MAX_QP
};
// lambda2 = pow(lambda, 2) * scale (0.85);
-const double x265_lambda2_tab[MAX_MAX_QP + 1] =
+double x265_lambda2_tab[MAX_MAX_QP + 1] =
{
0.0531, 0.0669, 0.0843, 0.1063, 0.1339,
0.1687, 0.2125, 0.2677, 0.3373, 0.4250,
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/Lib/TLibCommon/TComRom.h
--- a/source/Lib/TLibCommon/TComRom.h Wed Jul 02 14:31:51 2014 -0500
+++ b/source/Lib/TLibCommon/TComRom.h Wed Jul 02 18:09:20 2014 -0500
@@ -270,8 +270,8 @@ extern const uint32_t g_scalingListNum[S
extern const int g_winUnitX[MAX_CHROMA_FORMAT_IDC + 1];
extern const int g_winUnitY[MAX_CHROMA_FORMAT_IDC + 1];
-extern const double x265_lambda_tab[MAX_MAX_QP + 1];
-extern const double x265_lambda2_tab[MAX_MAX_QP + 1];
+extern double x265_lambda_tab[MAX_MAX_QP + 1];
+extern double x265_lambda2_tab[MAX_MAX_QP + 1];
extern const uint16_t x265_chroma_lambda2_offset_tab[MAX_CHROMA_LAMBDA_OFFSET+1];
// CABAC tables
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/Lib/TLibEncoder/TEncCu.cpp
--- a/source/Lib/TLibEncoder/TEncCu.cpp Wed Jul 02 14:31:51 2014 -0500
+++ b/source/Lib/TLibEncoder/TEncCu.cpp Wed Jul 02 18:09:20 2014 -0500
@@ -351,10 +351,10 @@ void TEncCu::compressCU(TComDataCU* cu)
else
{
m_log->cntIntra[part]++;
- if (cu->getLumaIntraDir()[i] > 1)
+ if (cu->getLumaIntraDir(i) > 1)
m_log->cuIntraDistribution[part][ANGULAR_MODE_ID]++;
else
- m_log->cuIntraDistribution[part][cu->getLumaIntraDir()[i]]++;
+ m_log->cuIntraDistribution[part][cu->getLumaIntraDir(i)]++;
}
i += next;
}
@@ -408,10 +408,10 @@ void TEncCu::compressCU(TComDataCU* cu)
else
{
m_log->cntIntra[part]++;
- if (cu->getLumaIntraDir()[0] > 1)
+ if (cu->getLumaIntraDir(0) > 1)
m_log->cuIntraDistribution[part][ANGULAR_MODE_ID]++;
else
- m_log->cuIntraDistribution[part][cu->getLumaIntraDir()[0]]++;
+ m_log->cuIntraDistribution[part][cu->getLumaIntraDir(0)]++;
}
}
}
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/common/param.cpp
--- a/source/common/param.cpp Wed Jul 02 14:31:51 2014 -0500
+++ b/source/common/param.cpp Wed Jul 02 18:09:20 2014 -0500
@@ -31,6 +31,7 @@
#if _MSC_VER
#pragma warning(disable: 4996) // POSIX functions are just fine, thanks
#pragma warning(disable: 4706) // assignment within conditional
+#pragma warning(disable: 4127) // conditional expression is constant
#endif
#if _WIN32
@@ -103,6 +104,7 @@ void x265_param_default(x265_param *para
param->frameNumThreads = 0;
param->poolNumThreads = 0;
param->csvfn = NULL;
+ param->rc.lambdaFileName = NULL;
param->bLogCuStats = 0;
/* Source specifications */
@@ -541,6 +543,7 @@ int x265_param_parse(x265_param *p, cons
}
}
OPT("csv") p->csvfn = value;
+ OPT("lambda-file") p->rc.lambdaFileName = value;
OPT("threads") p->poolNumThreads = atoi(value);
OPT("frame-threads") p->frameNumThreads = atoi(value);
OPT2("level-idc", "level")
@@ -1288,4 +1291,74 @@ char *x265_param2string(x265_param *p)
#undef BOOL
return buf;
}
+
+bool parseLambdaFile(x265_param *param)
+{
+ if (!param->rc.lambdaFileName)
+ return false;
+
+ FILE *lfn = fopen(param->rc.lambdaFileName, "r");
+ if (!lfn)
+ {
+ x265_log(param, X265_LOG_ERROR, "unable to read lambda file <%s>\n", param->rc.lambdaFileName);
+ return true;
+ }
+
+ char line[2048];
+ char *toksave, *tok = NULL, *buf;
+
+ for (int t = 0; t < 3; t++)
+ {
+ double *table = t ? x265_lambda2_tab : x265_lambda_tab;
+
+ for (int i = 0; i < MAX_MAX_QP + 1; i++)
+ {
+ double value;
+
+ do
+ {
+ if (!tok)
+ {
+ /* consume a line of text file */
+ if (!fgets(line, sizeof(line), lfn))
+ {
+ fclose(lfn);
+
+ if (t < 2)
+ {
+ x265_log(param, X265_LOG_ERROR, "lambda file is incomplete\n");
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /* truncate at first hash */
+ char *hash = strchr(line, '#');
+ if (hash) *hash = 0;
+ buf = line;
+ }
+
+ tok = strtok_r(buf, " ,", &toksave);
+ buf = NULL;
+ if (tok && sscanf(tok, "%lf", &value) == 1)
+ break;
+ }
+ while (1);
+
+ if (t == 2)
+ {
+ x265_log(param, X265_LOG_ERROR, "lambda file contains too many values\n");
+ return true;
+ }
+ else
+ x265_log(param, X265_LOG_DEBUG, "lambda%c[%d] = %lf\n", t ? '2' : ' ', i, value);
+ table[i] = value;
+ }
+ }
+
+ fclose(lfn);
+ return false;
}
+
+}
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/common/param.h
--- a/source/common/param.h Wed Jul 02 14:31:51 2014 -0500
+++ b/source/common/param.h Wed Jul 02 18:09:20 2014 -0500
@@ -33,6 +33,7 @@ int x265_atoi(const char *str, bool& b
int parseCpuName(const char *value, bool& bError);
void setParamAspectRatio(x265_param *p, int width, int height);
void getParamAspectRatio(x265_param *p, int& width, int& height);
+bool parseLambdaFile(x265_param *param);
/* this table is kept internal to avoid confusion, since log level indices start at -1 */
static const char * const logLevelNames[] = { "none", "error", "warning", "info", "debug", "full", 0 };
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Wed Jul 02 14:31:51 2014 -0500
+++ b/source/encoder/encoder.cpp Wed Jul 02 18:09:20 2014 -0500
@@ -142,6 +142,8 @@ void Encoder::create()
}
}
}
+
+ m_aborted |= parseLambdaFile(m_param);
}
void Encoder::destroy()
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/x265.cpp
--- a/source/x265.cpp Wed Jul 02 14:31:51 2014 -0500
+++ b/source/x265.cpp Wed Jul 02 18:09:20 2014 -0500
@@ -185,6 +185,7 @@ static const struct option long_options[
{ "aud", no_argument, NULL, 0 },
{ "no-aud", no_argument, NULL, 0 },
{ "qpfile", required_argument, NULL, 0 },
+ { "lambda-file", required_argument, NULL, 0 },
{ "b-intra", no_argument, NULL, 0 },
{ "no-b-intra", no_argument, NULL, 0 },
{ "nr", required_argument, NULL, 0 },
@@ -336,6 +337,10 @@ void CLIOptions::showHelp(x265_param *pa
H0(" Format of each line: framenumber frametype QP\n");
H0(" QP is optional (none lets x265 choose). Frametypes: I,i,P,B,b.\n");
H0(" QPs are restricted by qpmin/qpmax.\n");
+ H0(" --lambda-file <string> Specify a file containing replacement values for the lambda tables\n");
+ H0(" MAX_MAX_QP+1 floats for lambda table, then again for lambda2 table\n");
+ H0(" Blank lines and lines starting with hash(#) are ignored\n");
+ H0(" Comma is considered to be white-space\n");
H0("\nPresets:\n");
H0("-f/--frames <integer> Maximum number of frames to encode. Default all\n");
H0("-p/--preset <string> Trade off performance for compression efficiency. Default medium\n");
diff -r b90fdc3ffb96 -r 1e94a2b12d15 source/x265.h
--- a/source/x265.h Wed Jul 02 14:31:51 2014 -0500
+++ b/source/x265.h Wed Jul 02 18:09:20 2014 -0500
@@ -766,6 +766,14 @@ typedef struct x265_param
/* temporally blur complexity */
double complexityBlur;
+
+ /* specify a text file which contains MAX_MAX_QP + 1 floating point
+ * values to be copied into x265_lambda_tab and a second set of
+ * MAX_MAX_QP + 1 floating point values for x265_lambda2_tab. All values
+ * are separated by comma, space or newline. Text after a hash (#) is
+ * ignored. The lambda tables are process-global, so these new lambda
+ * values will affect all encoders in the same process */
+ const char* lambdaFileName;
} rc;
/*== Video Usability Information ==*/
More information about the x265-commits
mailing list