[x265] [PATCH] Add support for customizing logging
Pradeep Ramachandran
pradeep at multicorewareinc.com
Wed Jan 10 09:52:07 CET 2018
On Mon, Jan 1, 2018 at 6:05 PM, Andrey Semashev <andrey.semashev at gmail.com>
wrote:
> # 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).
>
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.
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 :-).
We will regress it and update the repo.
>
> 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(¶m, "exec", X265_LOG_ERROR, "Unable to register
> SIGPIPE handler: %s\n", strerror(errno));
> + g_x265_log(¶m, "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(¶m, "exec", X265_LOG_ERROR, "popen(%s) failed\n",
> commandLine);
> + g_x265_log(¶m, "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.
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20180110/b468af46/attachment-0001.html>
More information about the x265-devel
mailing list