[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