[x265] [PATCH 1 of 2] Add support for customizing logging

Andrey Semashev andrey.semashev at gmail.com
Fri Mar 16 16:28:40 CET 2018


# HG changeset patch
# User Andrey Semashev <andrey.semashev at gmail.com>
# Date 1515596947 -10800
#      Wed Jan 10 18:09:07 2018 +0300
# Branch add_custom_logging_v3
# Node ID 3ebefb64a1eb1487389db4ff7a808490b3005c39
# Parent  d7c26df32fae052b7e895fee9bda1c22b24cc44b
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).

The commit also increments API version.

diff -r d7c26df32fae -r 3ebefb64a1eb source/CMakeLists.txt
--- a/source/CMakeLists.txt	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/CMakeLists.txt	Wed Jan 10 18:09:07 2018 +0300
@@ -29,7 +29,7 @@
 option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)
 mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
 # X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 156)
+set(X265_BUILD 157)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r d7c26df32fae -r 3ebefb64a1eb source/common/common.cpp
--- a/source/common/common.cpp	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/common/common.cpp	Wed Jan 10 18:09:07 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 d7c26df32fae -r 3ebefb64a1eb source/common/common.h
--- a/source/common/common.h	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/common/common.h	Wed Jan 10 18:09:07 2018 +0300
@@ -409,16 +409,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 d7c26df32fae -r 3ebefb64a1eb source/encoder/api.cpp
--- a/source/encoder/api.cpp	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/encoder/api.cpp	Wed Jan 10 18:09:07 2018 +0300
@@ -415,6 +415,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,
@@ -457,7 +462,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 d7c26df32fae -r 3ebefb64a1eb source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/encoder/encoder.cpp	Wed Jan 10 18:09:07 2018 +0300
@@ -1798,10 +1798,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 d7c26df32fae -r 3ebefb64a1eb source/output/reconplay.cpp
--- a/source/output/reconplay.cpp	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/output/reconplay.cpp	Wed Jan 10 18:09:07 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 d7c26df32fae -r 3ebefb64a1eb source/x265.cpp
--- a/source/x265.cpp	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/x265.cpp	Wed Jan 10 18:09:07 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 d7c26df32fae -r 3ebefb64a1eb source/x265.h
--- a/source/x265.h	Tue Mar 13 13:40:13 2018 +0530
+++ b/source/x265.h	Wed Jan 10 18:09:07 2018 +0300
@@ -1807,6 +1807,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 ===
@@ -1859,6 +1873,8 @@
     void          (*csvlog_encode)(const x265_param*, const x265_stats *, int, int, int, char**);
     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);
+    void          (*set_log)(x265_log_t log);
+
     /* add new pointers to the end, or increment X265_MAJOR_VERSION */
 } x265_api;
 


More information about the x265-devel mailing list