<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jan 1, 2018 at 6:05 PM, Andrey Semashev <span dir="ltr"><<a href="mailto:andrey.semashev@gmail.com" target="_blank">andrey.semashev@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"># HG changeset patch<br>
# User Andrey Semashev <<a href="mailto:andrey.semashev@gmail.com">andrey.semashev@gmail.com</a>><br>
# Date 1514810081 -10800<br>
#      Mon Jan 01 15:34:41 2018 +0300<br>
# Branch add_custom_logging<br>
# Node ID 248f862033e9fb01ee54d3e466dc28<wbr>4eeeb30365<br>
# Parent  ff02513b92c000c3bb3dcc51deb79a<wbr>f57f5358d5<br>
Add support for customizing logging.<br>
<br>
This commit adds support for customizing logging behavior. This can be used<br>
by the application using libx265 to override the default behavior of printing<br>
messages to the console with the application-specific logging system. This is<br>
especially important if the console is not available or monitored for the<br>
application (e.g. if it runs as a service or daemon).<br></blockquote><div><br></div><div>I like this patch - it is a good feature to have to support better logging for application that includes libx265. We have to increase BUILD_NUMBER as there is a change to the API but that is a trivial change.</div><div>Having the g_x265_log as a global may result in some issues when the application instantiates multiple instances of x265 but I think we can live with it for now; a follow-up patch to clean this up would be great :-).</div><div><br></div><div>We will regress it and update the repo.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
diff -r ff02513b92c0 -r 248f862033e9 source/common/common.cpp<br>
--- a/source/common/common.cpp  Fri Dec 22 18:23:24 2017 +0530<br>
+++ b/source/common/common.cpp  Mon Jan 01 15:34:41 2018 +0300<br>
@@ -102,49 +102,9 @@<br>
     return (x265_exp2_lut[i & 63] + 256) << (i >> 6) >> 8;<br>
 }<br>
<br>
-void general_log(const x265_param* param, const char* caller, int level, const char* fmt, ...)<br>
-{<br>
-    if (param && level > param->logLevel)<br>
-        return;<br>
-    const int bufferSize = 4096;<br>
-    char buffer[bufferSize];<br>
-    int p = 0;<br>
-    const char* log_level;<br>
-    switch (level)<br>
-    {<br>
-    case X265_LOG_ERROR:<br>
-        log_level = "error";<br>
-        break;<br>
-    case X265_LOG_WARNING:<br>
-        log_level = "warning";<br>
-        break;<br>
-    case X265_LOG_INFO:<br>
-        log_level = "info";<br>
-        break;<br>
-    case X265_LOG_DEBUG:<br>
-        log_level = "debug";<br>
-        break;<br>
-    case X265_LOG_FULL:<br>
-        log_level = "full";<br>
-        break;<br>
-    default:<br>
-        log_level = "unknown";<br>
-        break;<br>
-    }<br>
+x265_log_t g_x265_log = &general_log;<br>
<br>
-    if (caller)<br>
-        p += sprintf(buffer, "%-4s [%s]: ", caller, log_level);<br>
-    va_list arg;<br>
-    va_start(arg, fmt);<br>
-    vsnprintf(buffer + p, bufferSize - p, fmt, arg);<br>
-    va_end(arg);<br>
-    fputs(buffer, stderr);<br>
-}<br>
-<br>
-#if _WIN32<br>
-/* For Unicode filenames in Windows we convert UTF-8 strings to UTF-16 and we use _w functions.<br>
- * For other OS we do not make any changes. */<br>
-void general_log_file(const x265_param* param, const char* caller, int level, const char* fmt, ...)<br>
+void general_log(const x265_param* param, const char* caller, int national, int level, const char* fmt, ...)<br>
 {<br>
     if (param && level > param->logLevel)<br>
         return;<br>
@@ -181,19 +141,31 @@<br>
     vsnprintf(buffer + p, bufferSize - p, fmt, arg);<br>
     va_end(arg);<br>
<br>
-    HANDLE console = GetStdHandle(STD_ERROR_HANDLE)<wbr>;<br>
-    DWORD mode;<br>
-    if (GetConsoleMode(console, &mode))<br>
+#if _WIN32<br>
+    if (national)<br>
     {<br>
-        wchar_t buf_utf16[bufferSize];<br>
-        int length_utf16 = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, buf_utf16, sizeof(buf_utf16)/sizeof(<wbr>wchar_t)) - 1;<br>
-        if (length_utf16 > 0)<br>
-            WriteConsoleW(console, buf_utf16, length_utf16, &mode, NULL);<br>
+        HANDLE console = GetStdHandle(STD_ERROR_HANDLE)<wbr>;<br>
+        DWORD mode;<br>
+        if (GetConsoleMode(console, &mode))<br>
+        {<br>
+            wchar_t buf_utf16[bufferSize];<br>
+            int length_utf16 = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, buf_utf16, sizeof(buf_utf16)/sizeof(<wbr>wchar_t)) - 1;<br>
+            if (length_utf16 > 0)<br>
+                WriteConsoleW(console, buf_utf16, length_utf16, &mode, NULL);<br>
+            return;<br>
+        }<br>
     }<br>
-    else<br>
-        fputs(buffer, stderr);<br>
+#else<br>
+    // Suppress warnings about unused argument<br>
+    (void)national;<br>
+#endif<br>
+<br>
+    fputs(buffer, stderr);<br>
 }<br>
<br>
+#if _WIN32<br>
+/* For Unicode filenames in Windows we convert UTF-8 strings to UTF-16 and we use _w functions.<br>
+ * For other OS we do not make any changes. */<br>
 FILE* x265_fopen(const char* fileName, const char* mode)<br>
 {<br>
     wchar_t buf_utf16[MAX_PATH * 2], mode_utf16[16];<br>
diff -r ff02513b92c0 -r 248f862033e9 source/common/common.h<br>
--- a/source/common/common.h    Fri Dec 22 18:23:24 2017 +0530<br>
+++ b/source/common/common.h    Mon Jan 01 15:34:41 2018 +0300<br>
@@ -411,16 +411,15 @@<br>
<br>
 /* located in common.cpp */<br>
 int64_t  x265_mdate(void);<br>
-#define  x265_log(param, ...) general_log(param, "x265", __VA_ARGS__)<br>
-#define  x265_log_file(param, ...) general_log_file(param, "x265", __VA_ARGS__)<br>
-void     general_log(const x265_param* param, const char* caller, int level, const char* fmt, ...);<br>
+extern x265_log_t g_x265_log;<br>
+#define  x265_log(param, ...) X265_NS::g_x265_log(param, "x265", 0, __VA_ARGS__)<br>
+#define  x265_log_file(param, ...) X265_NS::g_x265_log(param, "x265", 1, __VA_ARGS__)<br>
+void     general_log(const x265_param* param, const char* caller, int national, int level, const char* fmt, ...);<br>
 #if _WIN32<br>
-void     general_log_file(const x265_param* param, const char* caller, int level, const char* fmt, ...);<br>
 FILE*    x265_fopen(const char* fileName, const char* mode);<br>
 int      x265_unlink(const char* fileName);<br>
 int      x265_rename(const char* oldName, const char* newName);<br>
 #else<br>
-#define  general_log_file(param, caller, level, fmt, ...) general_log(param, caller, level, fmt, __VA_ARGS__)<br>
 #define  x265_fopen(fileName, mode) fopen(fileName, mode)<br>
 #define  x265_unlink(fileName) unlink(fileName)<br>
 #define  x265_rename(oldName, newName) rename(oldName, newName)<br>
diff -r ff02513b92c0 -r 248f862033e9 source/encoder/api.cpp<br>
--- a/source/encoder/api.cpp    Fri Dec 22 18:23:24 2017 +0530<br>
+++ b/source/encoder/api.cpp    Mon Jan 01 15:34:41 2018 +0300<br>
@@ -414,6 +414,11 @@<br>
     return x265_free(p);<br>
 }<br>
<br>
+void x265_set_log(x265_log_t log)<br>
+{<br>
+    X265_NS::g_x265_log = log;<br>
+}<br>
+<br>
 static const x265_api libapi =<br>
 {<br>
     X265_MAJOR_VERSION,<br>
@@ -456,7 +461,9 @@<br>
     &x265_csvlog_frame,<br>
     &x265_csvlog_encode,<br>
     &x265_dither_image,<br>
-    &x265_set_analysis_data<br>
+    &x265_set_analysis_data,<br>
+<br>
+    &x265_set_log<br>
 };<br>
<br>
 typedef const x265_api* (*api_get_func)(int bitDepth);<br>
diff -r ff02513b92c0 -r 248f862033e9 source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp        Fri Dec 22 18:23:24 2017 +0530<br>
+++ b/source/encoder/encoder.cpp        Mon Jan 01 15:34:41 2018 +0300<br>
@@ -1774,10 +1774,10 @@<br>
             p += sprintf(buffer + p, ", SSIM Mean Y: %.7f (%6.3f dB)", m_analyzeAll.m_globalSsim / m_analyzeAll.m_numPics, x265_ssim2dB(m_analyzeAll.m_<wbr>globalSsim / m_analyzeAll.m_numPics));<br>
<br>
         sprintf(buffer + p, "\n");<br>
-        general_log(m_param, NULL, X265_LOG_INFO, buffer);<br>
+        g_x265_log(m_param, NULL, false, X265_LOG_INFO, buffer);<br>
     }<br>
     else<br>
-        general_log(m_param, NULL, X265_LOG_INFO, "\nencoded 0 frames\n");<br>
+        g_x265_log(m_param, NULL, false, X265_LOG_INFO, "\nencoded 0 frames\n");<br>
<br>
 #if DETAILED_CU_STATS<br>
     /* Summarize stats from all frame encoders */<br>
diff -r ff02513b92c0 -r 248f862033e9 source/output/reconplay.cpp<br>
--- a/source/output/reconplay.cpp       Fri Dec 22 18:23:24 2017 +0530<br>
+++ b/source/output/reconplay.cpp       Mon Jan 01 15:34:41 2018 +0300<br>
@@ -43,7 +43,7 @@<br>
 static void sigpipe_handler(int)<br>
 {<br>
     if (ReconPlay::pipeValid)<br>
-        general_log(NULL, "exec", X265_LOG_ERROR, "pipe closed\n");<br>
+        g_x265_log(NULL, "exec", false, X265_LOG_ERROR, "pipe closed\n");<br>
     ReconPlay::pipeValid = false;<br>
 }<br>
 #endif<br>
@@ -52,7 +52,7 @@<br>
 {<br>
 #ifndef _WIN32<br>
     if (signal(SIGPIPE, sigpipe_handler) == SIG_ERR)<br>
-        general_log(&param, "exec", X265_LOG_ERROR, "Unable to register SIGPIPE handler: %s\n", strerror(errno));<br>
+        g_x265_log(&param, "exec", false, X265_LOG_ERROR, "Unable to register SIGPIPE handler: %s\n", strerror(errno));<br>
 #endif<br>
<br>
     width = param.sourceWidth;<br>
@@ -83,7 +83,7 @@<br>
         return;<br>
     }<br>
     else<br>
-        general_log(&param, "exec", X265_LOG_ERROR, "popen(%s) failed\n", commandLine);<br>
+        g_x265_log(&param, "exec", false, X265_LOG_ERROR, "popen(%s) failed\n", commandLine);<br>
<br>
 fail:<br>
     threadActive = false;<br>
diff -r ff02513b92c0 -r 248f862033e9 source/x265.cpp<br>
--- a/source/x265.cpp   Fri Dec 22 18:23:24 2017 +0530<br>
+++ b/source/x265.cpp   Mon Jan 01 15:34:41 2018 +0300<br>
@@ -416,7 +416,7 @@<br>
         else<br>
             sprintf(buf + p, " frames %u - %d of %d", this->seek, this->seek + this->framesToBeEncoded - 1, info.frameCount);<br>
<br>
-        general_log(param, input->getName(), X265_LOG_INFO, "%s\n", buf);<br>
+        general_log(param, input->getName(), false, X265_LOG_INFO, "%s\n", buf);<br>
     }<br>
<br>
     this->input->startReader();<br>
@@ -434,7 +434,7 @@<br>
             this->recon = 0;<br>
         }<br>
         else<br>
-            general_log(param, this->recon->getName(), X265_LOG_INFO,<br>
+            general_log(param, this->recon->getName(), false, X265_LOG_INFO,<br>
                     "reconstructed images %dx%d fps %d/%d %s\n",<br>
                     param->sourceWidth, param->sourceHeight, param->fpsNum, param->fpsDenom,<br>
                     x265_source_csp_names[param-><wbr>internalCsp]);<br>
@@ -446,7 +446,7 @@<br>
         x265_log_file(param, X265_LOG_ERROR, "failed to open output file <%s> for writing\n", outputfn);<br>
         return true;<br>
     }<br>
-    general_log_file(param, this->output->getName(), X265_LOG_INFO, "output file: %s\n", outputfn);<br>
+    general_log(param, this->output->getName(), true, X265_LOG_INFO, "output file: %s\n", outputfn);<br>
     return false;<br>
 }<br>
<br>
@@ -740,7 +740,7 @@<br>
     cliopt.output->closeFile(<wbr>largest_pts, second_largest_pts);<br>
<br>
     if (b_ctrl_c)<br>
-        general_log(param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",<br>
+        general_log(param, NULL, false, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",<br>
                     cliopt.seek + inFrameCount, stats.encodedPictureCount);<br>
<br>
     api->cleanup(); /* Free library singletons */<br>
diff -r ff02513b92c0 -r 248f862033e9 source/x265.h<br>
--- a/source/x265.h     Fri Dec 22 18:23:24 2017 +0530<br>
+++ b/source/x265.h     Mon Jan 01 15:34:41 2018 +0300<br>
@@ -1787,6 +1787,20 @@<br>
  * the residual bits to dither each row. */<br>
 void x265_dither_image(x265_picture *, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth);<br>
<br>
+/* Logging function. The function is called whenever a log message is emitted.<br>
+ * The default function prints the message to stderr.<br>
+ * @param param Parameters of the encoder that emitted the message<br>
+ * @param caller A string identifying the log message originator<br>
+ * @param national If not 0, the message may contain national characters<br>
+ * @param level Log verbosity level, one of X265_LOG_*<br>
+ * @param fmt printf-style format string of the message; any subsequent arguments<br>
+ *            are to be formatted into the message according to this string */<br>
+typedef void (*x265_log_t)(const x265_param* param, const char* caller, int national, int level, const char* fmt, ...);<br>
+<br>
+/* x265_set_log:<br>
+ *       Sets a custom logger function */<br>
+void x265_set_log(x265_log_t log);<br>
+<br>
 #define X265_MAJOR_VERSION 1<br>
<br>
 /* === Multi-lib API ===<br>
@@ -1840,6 +1854,8 @@<br>
     void          (*dither_image)(x265_picture*, int, int, int16_t*, int);<br>
     int           (*set_analysis_data)(x265_<wbr>encoder *encoder, x265_analysis_data *analysis_data, int poc, uint32_t cuBytes);<br>
     /* add new pointers to the end, or increment X265_MAJOR_VERSION */<br>
+<br>
+    void          (*set_log)(x265_log_t log);<br>
 } x265_api;<br>
<br>
 /* Force a link error in the case of linking against an incompatible API version.<br>
______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/<wbr>listinfo/x265-devel</a><br>
</blockquote></div><br></div></div>