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

Andrey Semashev andrey.semashev at gmail.com
Wed Jan 10 16:20:17 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
# Node ID a5ad2f32cd45697897fdf6b643c69291861520c7
# Parent  2f3c4158cf3553030920708271bc43cdc79932a3
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 2f3c4158cf35 -r a5ad2f32cd45 source/CMakeLists.txt
--- a/source/CMakeLists.txt	Thu Jan 04 12:37:01 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 151)
+set(X265_BUILD 152)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 2f3c4158cf35 -r a5ad2f32cd45 source/common/common.cpp
--- a/source/common/common.cpp	Thu Jan 04 12:37:01 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 2f3c4158cf35 -r a5ad2f32cd45 source/common/common.h
--- a/source/common/common.h	Thu Jan 04 12:37:01 2018 +0530
+++ b/source/common/common.h	Wed Jan 10 18:09:07 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 2f3c4158cf35 -r a5ad2f32cd45 source/encoder/api.cpp
--- a/source/encoder/api.cpp	Thu Jan 04 12:37:01 2018 +0530
+++ b/source/encoder/api.cpp	Wed Jan 10 18:09:07 2018 +0300
@@ -417,6 +417,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,
@@ -459,7 +464,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 2f3c4158cf35 -r a5ad2f32cd45 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Thu Jan 04 12:37:01 2018 +0530
+++ b/source/encoder/encoder.cpp	Wed Jan 10 18:09:07 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 2f3c4158cf35 -r a5ad2f32cd45 source/output/reconplay.cpp
--- a/source/output/reconplay.cpp	Thu Jan 04 12:37:01 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 2f3c4158cf35 -r a5ad2f32cd45 source/x265.cpp
--- a/source/x265.cpp	Thu Jan 04 12:37:01 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 2f3c4158cf35 -r a5ad2f32cd45 source/x265.h
--- a/source/x265.h	Thu Jan 04 12:37:01 2018 +0530
+++ b/source/x265.h	Wed Jan 10 18:09:07 2018 +0300
@@ -1788,6 +1788,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          (*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