[x265] [PATCH] Add support for customizing logging

Andrey Semashev andrey.semashev at gmail.com
Mon Jan 1 13:35:03 CET 2018


# HG changeset patch
# User Andrey Semashev <andrey.semashev at gmail.com>
# Date 1514810081 -10800
#      Mon Jan 01 15:34:41 2018 +0300
# Branch add_custom_logging
# Node ID 248f862033e9fb01ee54d3e466dc284eeeb30365
# Parent  ff02513b92c000c3bb3dcc51deb79af57f5358d5
Add support for customizing logging.

This commit adds support for customizing logging behavior. This can be used
by the application using libx265 to override the default behavior of printing
messages to the console with the application-specific logging system. This is
especially important if the console is not available or monitored for the
application (e.g. if it runs as a service or daemon).

diff -r ff02513b92c0 -r 248f862033e9 source/common/common.cpp
--- a/source/common/common.cpp	Fri Dec 22 18:23:24 2017 +0530
+++ b/source/common/common.cpp	Mon Jan 01 15:34:41 2018 +0300
@@ -102,49 +102,9 @@
     return (x265_exp2_lut[i & 63] + 256) << (i >> 6) >> 8;
 }
 
-void general_log(const x265_param* param, const char* caller, int level, const char* fmt, ...)
-{
-    if (param && level > param->logLevel)
-        return;
-    const int bufferSize = 4096;
-    char buffer[bufferSize];
-    int p = 0;
-    const char* log_level;
-    switch (level)
-    {
-    case X265_LOG_ERROR:
-        log_level = "error";
-        break;
-    case X265_LOG_WARNING:
-        log_level = "warning";
-        break;
-    case X265_LOG_INFO:
-        log_level = "info";
-        break;
-    case X265_LOG_DEBUG:
-        log_level = "debug";
-        break;
-    case X265_LOG_FULL:
-        log_level = "full";
-        break;
-    default:
-        log_level = "unknown";
-        break;
-    }
+x265_log_t g_x265_log = &general_log;
 
-    if (caller)
-        p += sprintf(buffer, "%-4s [%s]: ", caller, log_level);
-    va_list arg;
-    va_start(arg, fmt);
-    vsnprintf(buffer + p, bufferSize - p, fmt, arg);
-    va_end(arg);
-    fputs(buffer, stderr);
-}
-
-#if _WIN32
-/* For Unicode filenames in Windows we convert UTF-8 strings to UTF-16 and we use _w functions.
- * For other OS we do not make any changes. */
-void general_log_file(const x265_param* param, const char* caller, int level, const char* fmt, ...)
+void general_log(const x265_param* param, const char* caller, int national, int level, const char* fmt, ...)
 {
     if (param && level > param->logLevel)
         return;
@@ -181,19 +141,31 @@
     vsnprintf(buffer + p, bufferSize - p, fmt, arg);
     va_end(arg);
 
-    HANDLE console = GetStdHandle(STD_ERROR_HANDLE);
-    DWORD mode;
-    if (GetConsoleMode(console, &mode))
+#if _WIN32
+    if (national)
     {
-        wchar_t buf_utf16[bufferSize];
-        int length_utf16 = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t)) - 1;
-        if (length_utf16 > 0)
-            WriteConsoleW(console, buf_utf16, length_utf16, &mode, NULL);
+        HANDLE console = GetStdHandle(STD_ERROR_HANDLE);
+        DWORD mode;
+        if (GetConsoleMode(console, &mode))
+        {
+            wchar_t buf_utf16[bufferSize];
+            int length_utf16 = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t)) - 1;
+            if (length_utf16 > 0)
+                WriteConsoleW(console, buf_utf16, length_utf16, &mode, NULL);
+            return;
+        }
     }
-    else
-        fputs(buffer, stderr);
+#else
+    // Suppress warnings about unused argument
+    (void)national;
+#endif
+
+    fputs(buffer, stderr);
 }
 
+#if _WIN32
+/* For Unicode filenames in Windows we convert UTF-8 strings to UTF-16 and we use _w functions.
+ * For other OS we do not make any changes. */
 FILE* x265_fopen(const char* fileName, const char* mode)
 {
     wchar_t buf_utf16[MAX_PATH * 2], mode_utf16[16];
diff -r ff02513b92c0 -r 248f862033e9 source/common/common.h
--- a/source/common/common.h	Fri Dec 22 18:23:24 2017 +0530
+++ b/source/common/common.h	Mon Jan 01 15:34:41 2018 +0300
@@ -411,16 +411,15 @@
 
 /* located in common.cpp */
 int64_t  x265_mdate(void);
-#define  x265_log(param, ...) general_log(param, "x265", __VA_ARGS__)
-#define  x265_log_file(param, ...) general_log_file(param, "x265", __VA_ARGS__)
-void     general_log(const x265_param* param, const char* caller, int level, const char* fmt, ...);
+extern x265_log_t g_x265_log;
+#define  x265_log(param, ...) X265_NS::g_x265_log(param, "x265", 0, __VA_ARGS__)
+#define  x265_log_file(param, ...) X265_NS::g_x265_log(param, "x265", 1, __VA_ARGS__)
+void     general_log(const x265_param* param, const char* caller, int national, int level, const char* fmt, ...);
 #if _WIN32
-void     general_log_file(const x265_param* param, const char* caller, int level, const char* fmt, ...);
 FILE*    x265_fopen(const char* fileName, const char* mode);
 int      x265_unlink(const char* fileName);
 int      x265_rename(const char* oldName, const char* newName);
 #else
-#define  general_log_file(param, caller, level, fmt, ...) general_log(param, caller, level, fmt, __VA_ARGS__)
 #define  x265_fopen(fileName, mode) fopen(fileName, mode)
 #define  x265_unlink(fileName) unlink(fileName)
 #define  x265_rename(oldName, newName) rename(oldName, newName)
diff -r ff02513b92c0 -r 248f862033e9 source/encoder/api.cpp
--- a/source/encoder/api.cpp	Fri Dec 22 18:23:24 2017 +0530
+++ b/source/encoder/api.cpp	Mon Jan 01 15:34:41 2018 +0300
@@ -414,6 +414,11 @@
     return x265_free(p);
 }
 
+void x265_set_log(x265_log_t log)
+{
+    X265_NS::g_x265_log = log;
+}
+
 static const x265_api libapi =
 {
     X265_MAJOR_VERSION,
@@ -456,7 +461,9 @@
     &x265_csvlog_frame,
     &x265_csvlog_encode,
     &x265_dither_image,
-    &x265_set_analysis_data
+    &x265_set_analysis_data,
+
+    &x265_set_log
 };
 
 typedef const x265_api* (*api_get_func)(int bitDepth);
diff -r ff02513b92c0 -r 248f862033e9 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Fri Dec 22 18:23:24 2017 +0530
+++ b/source/encoder/encoder.cpp	Mon Jan 01 15:34:41 2018 +0300
@@ -1774,10 +1774,10 @@
             p += sprintf(buffer + p, ", SSIM Mean Y: %.7f (%6.3f dB)", m_analyzeAll.m_globalSsim / m_analyzeAll.m_numPics, x265_ssim2dB(m_analyzeAll.m_globalSsim / m_analyzeAll.m_numPics));
 
         sprintf(buffer + p, "\n");
-        general_log(m_param, NULL, X265_LOG_INFO, buffer);
+        g_x265_log(m_param, NULL, false, X265_LOG_INFO, buffer);
     }
     else
-        general_log(m_param, NULL, X265_LOG_INFO, "\nencoded 0 frames\n");
+        g_x265_log(m_param, NULL, false, X265_LOG_INFO, "\nencoded 0 frames\n");
 
 #if DETAILED_CU_STATS
     /* Summarize stats from all frame encoders */
diff -r ff02513b92c0 -r 248f862033e9 source/output/reconplay.cpp
--- a/source/output/reconplay.cpp	Fri Dec 22 18:23:24 2017 +0530
+++ b/source/output/reconplay.cpp	Mon Jan 01 15:34:41 2018 +0300
@@ -43,7 +43,7 @@
 static void sigpipe_handler(int)
 {
     if (ReconPlay::pipeValid)
-        general_log(NULL, "exec", X265_LOG_ERROR, "pipe closed\n");
+        g_x265_log(NULL, "exec", false, X265_LOG_ERROR, "pipe closed\n");
     ReconPlay::pipeValid = false;
 }
 #endif
@@ -52,7 +52,7 @@
 {
 #ifndef _WIN32
     if (signal(SIGPIPE, sigpipe_handler) == SIG_ERR)
-        general_log(&param, "exec", X265_LOG_ERROR, "Unable to register SIGPIPE handler: %s\n", strerror(errno));
+        g_x265_log(&param, "exec", false, X265_LOG_ERROR, "Unable to register SIGPIPE handler: %s\n", strerror(errno));
 #endif
 
     width = param.sourceWidth;
@@ -83,7 +83,7 @@
         return;
     }
     else
-        general_log(&param, "exec", X265_LOG_ERROR, "popen(%s) failed\n", commandLine);
+        g_x265_log(&param, "exec", false, X265_LOG_ERROR, "popen(%s) failed\n", commandLine);
 
 fail:
     threadActive = false;
diff -r ff02513b92c0 -r 248f862033e9 source/x265.cpp
--- a/source/x265.cpp	Fri Dec 22 18:23:24 2017 +0530
+++ b/source/x265.cpp	Mon Jan 01 15:34:41 2018 +0300
@@ -416,7 +416,7 @@
         else
             sprintf(buf + p, " frames %u - %d of %d", this->seek, this->seek + this->framesToBeEncoded - 1, info.frameCount);
 
-        general_log(param, input->getName(), X265_LOG_INFO, "%s\n", buf);
+        general_log(param, input->getName(), false, X265_LOG_INFO, "%s\n", buf);
     }
 
     this->input->startReader();
@@ -434,7 +434,7 @@
             this->recon = 0;
         }
         else
-            general_log(param, this->recon->getName(), X265_LOG_INFO,
+            general_log(param, this->recon->getName(), false, X265_LOG_INFO,
                     "reconstructed images %dx%d fps %d/%d %s\n",
                     param->sourceWidth, param->sourceHeight, param->fpsNum, param->fpsDenom,
                     x265_source_csp_names[param->internalCsp]);
@@ -446,7 +446,7 @@
         x265_log_file(param, X265_LOG_ERROR, "failed to open output file <%s> for writing\n", outputfn);
         return true;
     }
-    general_log_file(param, this->output->getName(), X265_LOG_INFO, "output file: %s\n", outputfn);
+    general_log(param, this->output->getName(), true, X265_LOG_INFO, "output file: %s\n", outputfn);
     return false;
 }
 
@@ -740,7 +740,7 @@
     cliopt.output->closeFile(largest_pts, second_largest_pts);
 
     if (b_ctrl_c)
-        general_log(param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",
+        general_log(param, NULL, false, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",
                     cliopt.seek + inFrameCount, stats.encodedPictureCount);
 
     api->cleanup(); /* Free library singletons */
diff -r ff02513b92c0 -r 248f862033e9 source/x265.h
--- a/source/x265.h	Fri Dec 22 18:23:24 2017 +0530
+++ b/source/x265.h	Mon Jan 01 15:34:41 2018 +0300
@@ -1787,6 +1787,20 @@
  * the residual bits to dither each row. */
 void x265_dither_image(x265_picture *, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth);
 
+/* Logging function. The function is called whenever a log message is emitted.
+ * The default function prints the message to stderr.
+ * @param param Parameters of the encoder that emitted the message
+ * @param caller A string identifying the log message originator
+ * @param national If not 0, the message may contain national characters
+ * @param level Log verbosity level, one of X265_LOG_*
+ * @param fmt printf-style format string of the message; any subsequent arguments
+ *            are to be formatted into the message according to this string */
+typedef void (*x265_log_t)(const x265_param* param, const char* caller, int national, int level, const char* fmt, ...);
+
+/* x265_set_log:
+ *       Sets a custom logger function */
+void x265_set_log(x265_log_t log);
+
 #define X265_MAJOR_VERSION 1
 
 /* === Multi-lib API ===
@@ -1840,6 +1854,8 @@
     void          (*dither_image)(x265_picture*, int, int, int16_t*, int);
     int           (*set_analysis_data)(x265_encoder *encoder, x265_analysis_data *analysis_data, int poc, uint32_t cuBytes);
     /* add new pointers to the end, or increment X265_MAJOR_VERSION */
+
+    void          (*set_log)(x265_log_t log);
 } x265_api;
 
 /* Force a link error in the case of linking against an incompatible API version.


More information about the x265-devel mailing list