# HG changeset patch # User Steve Borho <st...@borho.org> # Date 1404339662 18000 # Wed Jul 02 17:21:02 2014 -0500 # Node ID 6da77093c4b2db20dfafa7ff5994294ba3773f24 # Parent b90fdc3ffb962ddd4baf1309a5d6ffa3908f0486 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. diff -r b90fdc3ffb96 -r 6da77093c4b2 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 17:21:02 2014 -0500 @@ -274,6 +274,26 @@ 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 the x265_lambda_tab and + x265_lambda2_tab. Each table requires MAX_MAX_QP (69) float values + to be read from the file. + + 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 may 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 6da77093c4b2 source/CMakeLists.txt --- a/source/CMakeLists.txt Wed Jul 02 14:31:51 2014 -0500 +++ b/source/CMakeLists.txt Wed Jul 02 17:21:02 2014 -0500 @@ -19,7 +19,7 @@ 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 6da77093c4b2 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 17:21:02 2014 -0500 @@ -124,7 +124,7 @@ }; // 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 @@ }; // 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 6da77093c4b2 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 17:21:02 2014 -0500 @@ -270,8 +270,8 @@ 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 6da77093c4b2 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 17:21:02 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 @@ param->frameNumThreads = 0; param->poolNumThreads = 0; param->csvfn = NULL; + param->rc.lambdaFileName = NULL; param->bLogCuStats = 0; /* Source specifications */ @@ -541,6 +543,7 @@ } } 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,61 @@ #undef BOOL return buf; } + +void parseLambdaFile(x265_param *param) +{ + if (!param->rc.lambdaFileName) + return; + + FILE *lfn = fopen(param->rc.lambdaFileName, "r"); + if (!lfn) + { + x265_log(param, X265_LOG_WARNING, "unable to read lambda file <%s>\n", param->rc.lambdaFileName); + return; + } + + char line[2048]; + char *toksave, *tok = NULL, *buf; + + for (int t = 0; t < 2; 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)) + { + x265_log(param, X265_LOG_WARNING, "lambda file is incomplete\n"); + fclose(lfn); + return; + } + + /* 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); + + x265_log(param, X265_LOG_DEBUG, "lambda%c[%d] = %lf\n", t ? '2' : ' ', i, value); + table[i] = value; + } + } + + fclose(lfn); } + +} diff -r b90fdc3ffb96 -r 6da77093c4b2 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 17:21:02 2014 -0500 @@ -33,6 +33,7 @@ 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); +void 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 6da77093c4b2 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 17:21:02 2014 -0500 @@ -142,6 +142,8 @@ } } } + + parseLambdaFile(m_param); } void Encoder::destroy() diff -r b90fdc3ffb96 -r 6da77093c4b2 source/x265.cpp --- a/source/x265.cpp Wed Jul 02 14:31:51 2014 -0500 +++ b/source/x265.cpp Wed Jul 02 17:21:02 2014 -0500 @@ -185,6 +185,7 @@ { "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 @@ 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 lambdas to be used by all encoders\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 6da77093c4b2 source/x265.h --- a/source/x265.h Wed Jul 02 14:31:51 2014 -0500 +++ b/source/x265.h Wed Jul 02 17:21:02 2014 -0500 @@ -766,6 +766,14 @@ /* 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 ==*/ _______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel