From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 018BE4E153 for ; Sat, 8 Mar 2025 23:03:04 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7AD4B68E764; Sun, 9 Mar 2025 01:02:59 +0200 (EET) Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A257968DFA8 for ; Sun, 9 Mar 2025 01:02:52 +0200 (EET) Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2255003f4c6so7108045ad.0 for ; Sat, 08 Mar 2025 15:02:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741474971; x=1742079771; darn=ffmpeg.org; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=GjQNpScLU8oLKXQui3/KfiIk72g2zEl3JbbBNZL/DIg=; b=DK0UpOL5utXtN0Dq291ppYfMc9IvklfgOtXR9vDdqe7gIHWP//fDQNAdjqEiml7iSN CbJkEXoJYQTsTsaFB0nAbgb/TtGl8erjmUm/LaKfM1/YeWEkZD2rkFnp0YQmu02Sf0AT 6XV1TcuN+za6S2rIOnfCEii4wnrP3D7bHiyAZiaAvwCBOuS0OFHTqz8LBQRQ3ssXbNaQ QWrFkuQvIN6fdloZI4QoXK8aHNq10SN/bD00KZZkp8iYc/jos9EXsxZ+kNUND8LBkX6+ He4xZXU+IKcUCEXj6yEJ7pBVrG3YutgzEIbRXxrOil4k3A8I+h9b7puTn2TZty0WKJyJ R5nQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741474971; x=1742079771; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GjQNpScLU8oLKXQui3/KfiIk72g2zEl3JbbBNZL/DIg=; b=bkdVBJmBzT5KphgpobWVO2GywPAtHKgO9sDpuo0FSDjJJkTShDPPq1s+uifJ7Y66cP 3BjuEuXnqyfnCaeIWcKDfcH5VNnbFXIZY/GXK+0iyxOQid47HF0SeaTJyxvS49n4GV8N qexMv/cVvY5K7LeEk+AKuGNziWLs/9zf9pskQpPeJNh+k3YcrOBLekbYQmXQDH/Ci1t1 KNzApZnqmTgQw0lDSNWeXB5USghCmyAvkYk0No+8zF4eX3TAWKASFCZzhMxkyq/qTJXg 5Fg7KiTxeWR+cmVC2H6Xn3jAwLhQ1ii4VXEio0UYvXWXi6yyFWepwf1rQvQHzVNgiD55 Xg7g== X-Gm-Message-State: AOJu0YwKcYV9O6+DPICqekpLhJGA5u1Q6Qhubkot99WSwJJ9S5MJ5xod +/pPROaT9hMj1j8NiBiIgnAnBnnzyPzsXOItNWFpYFT5av6zVo23hby+K4Vm X-Gm-Gg: ASbGncsD36qav3+yqpUsIjZuLD1oXz3pWlpuFpIUXhWifOrE9gFkmYhuvLLAz67XcXX n7+KjuoghCbrMD4GIEMFUvfJtnxmc8D/Qj8AJmb04vXK6uz86aNLooprSjyjHDW3PJAonxcz2QU NnaB0bx1pyWVVmw6pAiMW+0AVdpHzwJqf2YCJhS/ZbrXdbQWsactOzOMvjY/OtPZQdp3LxL9XJp Pf8UsvgRL+46/52kPcRn2XAay9g0VhfJJg02h/9AAxVbRuH2CUKT3nGzPILOGp6JqpKpBgJVjz9 mRDCO+qfTdyrgH3gYAevCpuxSkpfZXXXtjBjR5ANMK4YzvvKA+x1OIZN6mDdg4nBuIPldVMu+A= = X-Google-Smtp-Source: AGHT+IFWWYtzygQS0eLf1o04zp8UaO33L0Otxyfrov091WO1V88964S9wBSbdWnW5xIUXTwIseM3qg== X-Received: by 2002:a17:902:d2c7:b0:223:6657:5004 with SMTP id d9443c01a7336-22428a9e371mr143932515ad.28.1741474970491; Sat, 08 Mar 2025 15:02:50 -0800 (PST) Received: from [127.0.0.1] (master.gitmailbox.com. [34.83.118.50]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-22410a7f717sm51571775ad.111.2025.03.08.15.02.49 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 08 Mar 2025 15:02:49 -0800 (PST) Message-Id: In-Reply-To: References: From: ffmpegagent Date: Sat, 08 Mar 2025 23:02:40 +0000 Fcc: Sent MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH v4 0/4] avutil/log: Replace addresses in log output with simple ids X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: softworkz Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: ..and individual numbering. The benefits are: * Smaller log file sizes * The disambiguation is much easier to recognize and to follow * It eventually allows comparing and viewing log file diffs without almost every line being different due to those addresses Before ====== [hevc @ 0000018e72a89cc0] nal_unit_type: [hevc @ 0000018e72a89cc0] Decoding PPS [hevc @ 0000018e72a89cc0] nal_unit_type: 39(SEI_P.. [hevc @ 0000018e72a89cc0] Decoding SEI [mp4 @ 0000018e72a8e240] All [mp4 @ 0000018e72a8e240] Afte [hevc @ 0000018e742f6b40] Decoded frame with POC .. detected 16 logical cores [Parsed_scale_0 @ 0000018e74382f40] Setting 'w' t.. [Parsed_scale_0 @ 0000018e74382f40] Setting 'h' t.. [Parsed_scale_1 @ 0000018e74382440] Setting 'w' t.. [mjpeg @ 0000018e743210c0] Forcing thread count t.. [mjpeg @ 0000018e743210c0] intra_quant_bias = 96 After ===== [hevc #0] nal_unit_type: [hevc #0] Decoding PPS [hevc #0] nal_unit_type: 39(SEI_P.. [hevc #0] Decoding SEI [mp4 #0] All info found [mp4 #0] After avformat_find_ [hevc #1] Decoded frame with POC 2. [Parsed_scale_0 #0] Setting 'w' t.. [Parsed_scale_0 #0] Setting 'h' t.. [Parsed_scale_1 #1] Setting 'w' t.. [mjpeg #2] Forcing thread count t.. [mjpeg #2] intra_quant_bias = 96 Versions ======== V2 == * Added log flag for optionally restoring the previous behavior (as requested by Gyan) V3 == * Externalize the prefix formatting with a prefix_format callback V4 == * Implement a custom logging callback function for fftools instead of the prefix formatting callback (as suggested by Hendrik Leppkes) softworkz (4): avutil/log: Add AV_LOG_PRINT_MEMADDRESSES logging flag fftools/opt_common: add memaddresses log flag fftools: Provide a an fftools-specific logging callback function doc/fftools-common-opts: document memaddresses log flag doc/APIchanges | 3 + doc/fftools-common-opts.texi | 2 + fftools/Makefile | 7 +- fftools/ffmpeg.c | 2 + fftools/ffmpeg_filter.c | 2 +- fftools/ffplay.c | 2 + fftools/ffprobe.c | 2 + fftools/fftools_log.c | 480 +++++++++++++++++++++++++++++++++++ fftools/fftools_log.h | 44 ++++ fftools/opt_common.c | 6 + libavutil/log.h | 5 + libavutil/version.h | 2 +- 12 files changed, 554 insertions(+), 3 deletions(-) create mode 100644 fftools/fftools_log.c create mode 100644 fftools/fftools_log.h base-commit: 1bce40cb73fffd9d1fb6e118d71ac8999cded808 Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-59%2Fsoftworkz%2Fsubmit_logaddresses-v4 Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-59/softworkz/submit_logaddresses-v4 Pull-Request: https://github.com/ffstaging/FFmpeg/pull/59 Range-diff vs v3: 1: b8702de13b ! 1: 4be966796c avutil/log: Add callback for context prefix formatting @@ Metadata Author: softworkz ## Commit message ## - avutil/log: Add callback for context prefix formatting + avutil/log: Add AV_LOG_PRINT_MEMADDRESSES logging flag - also adds a log flag AV_LOG_PRINT_MEMADDRESSES, which is meant to - control prefix formatting. The actual formatting has to be performed - by the consuming application which needs to provide a formatting - callback via av_log_set_formatprefix_callback. + which is meant to control prefix formatting. The actual formatting + has to be performed by the consuming application which needs to provide + a custom logging callback via av_log_set_callback(). Signed-off-by: softworkz @@ doc/APIchanges The last version increases of all libraries were on 2024-03-07 +2025-03-xx - xxxxxxxxxx - lavu 59.59.100 - log.h -+ Add flag AV_LOG_PRINT_MEMADDRESSES, av_log_set_formatprefix_callback, -+ av_log_formatprefix_default_callback ++ Add flag AV_LOG_PRINT_MEMADDRESSES + API changes, most recent first: 2025-03-01 - xxxxxxxxxx - lavu 59.58.100 - pixfmt.h - ## libavutil/log.c ## -@@ libavutil/log.c: static void format_date_now(AVBPrint* bp_time, int include_date) - } - } - -+void av_log_formatprefix_default_callback(AVBPrint* buffer, AVClass** avcl, int log_flags) -+{ -+ av_bprintf(buffer+0, "[%s @ %p] ", item_name(avcl, *avcl), avcl); -+} -+ -+static void (*av_log_formatprefix_callback)(AVBPrint* part, AVClass** avcl, int log_flags) = -+ av_log_formatprefix_default_callback; -+ - static void format_line(void *avcl, int level, const char *fmt, va_list vl, - AVBPrint part[5], int *print_prefix, int type[2]) - { -@@ libavutil/log.c: static void format_line(void *avcl, int level, const char *fmt, va_list vl, - - if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16; - if (*print_prefix && avc) { -+ - if (avc->parent_log_context_offset) { -- AVClass** parent = *(AVClass ***) (((uint8_t *) avcl) + -- avc->parent_log_context_offset); -+ AVClass** parent = *(AVClass ***) ((uint8_t *)avcl + avc->parent_log_context_offset); - if (parent && *parent) { -- av_bprintf(part+0, "[%s @ %p] ", -- item_name(parent, *parent), parent); -+ av_log_formatprefix_callback(part, parent, flags); - if(type) type[0] = get_category(parent); - } - } -- av_bprintf(part+1, "[%s @ %p] ", -- item_name(avcl, avc), avcl); -+ av_log_formatprefix_callback(part, avcl, flags); -+ - if(type) type[1] = get_category(avcl); - } - -@@ libavutil/log.c: int av_log_get_flags(void) - return flags; - } - -+void av_log_set_formatprefix_callback(void (*callback)(AVBPrint* buffer, AVClass** avcl, int log_flags)) -+{ -+ av_log_formatprefix_callback = callback; -+} -+ - void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)) - { - av_log_callback = callback; - ## libavutil/log.h ## -@@ - #include - #include "attributes.h" - #include "version.h" -+#include "bprint.h" - - typedef enum { - AV_CLASS_CATEGORY_NA = 0, -@@ libavutil/log.h: int av_log_get_level(void); - */ - void av_log_set_level(int level); - -+/** -+ * Set the prefix formatting callback -+ * -+ * @note The callback must be thread safe, even if the application does not use -+ * threads itself as some codecs are multithreaded. -+ * -+ * @see av_log_formatprefix_default_callback -+ * -+ * @param callback A formatting function with a compatible signature. -+ */ -+void av_log_set_formatprefix_callback(void (*callback)(AVBPrint* buffer, AVClass** avcl, int log_flags)); -+ -+/** -+ * Default prefix formatting callback -+ * -+ * It prints the message to stderr, optionally colorizing it. -+ * -+ * @param buffer A pointer to the print buffer. -+ * @param avcl The AVClass reference for which to format the prefix. -+ * @param log_flags The enabled logging flags -+ */ -+void av_log_formatprefix_default_callback(AVBPrint* buffer, AVClass** avcl, int log_flags); -+ - /** - * Set the logging callback - * @@ libavutil/log.h: int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl, */ #define AV_LOG_PRINT_DATETIME 8 2: 84c0848afc = 2: e4f8213c24 fftools/opt_common: add memaddresses log flag 3: 105adac4ba ! 3: fa1ae9231a fftools: Provide a log formatting callback for context prefixes @@ Metadata Author: softworkz ## Commit message ## - fftools: Provide a log formatting callback for context prefixes + fftools: Provide a an fftools-specific logging callback function - This allows to print logical ids instead of memory addresses. + This goes together with a change to logging of context prefixes, which + is printing logical ids instead of memory addresses. The benefits are: - Smaller log file sizes @@ Commit message - It eventually allows comparing and viewing log file diffs without almost every line being different due to those addresses - ## fftools/cmdutils.c ## -@@ fftools/cmdutils.c: AVDictionary *format_opts, *codec_opts; + ## fftools/Makefile ## +@@ fftools/Makefile: OBJS-ffmpeg += \ + fftools/ffmpeg_mux_init.o \ + fftools/ffmpeg_opt.o \ + fftools/ffmpeg_sched.o \ ++ fftools/fftools_log.o \ + fftools/sync_queue.o \ + fftools/thread_queue.o \ - int hide_banner = 0; +-OBJS-ffplay += fftools/ffplay_renderer.o ++OBJS-ffprobe += \ ++ fftools/fftools_log.o \ ++ ++OBJS-ffplay += fftools/ffplay_renderer.o \ ++ fftools/fftools_log.o \ + + define DOFFTOOL + OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes) + + ## fftools/ffmpeg.c ## +@@ + #include "ffmpeg.h" + #include "ffmpeg_sched.h" + #include "ffmpeg_utils.h" ++#include "fftools_log.h" + + const char program_name[] = "ffmpeg"; + const int program_birth_year = 2000; +@@ fftools/ffmpeg.c: int main(int argc, char **argv) + setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */ + + av_log_set_flags(AV_LOG_SKIP_REPEATED); ++ init_logging(); + parse_loglevel(argc, argv, options); + + #if CONFIG_AVDEVICE + + ## fftools/ffmpeg_filter.c ## +@@ + /* +- * ffmpeg filter configuration ++ * Copyright (c) The FFmpeg developers + * + * This file is part of FFmpeg. + * + + ## fftools/ffplay.c ## +@@ + #include "cmdutils.h" + #include "ffplay_renderer.h" + #include "opt_common.h" ++#include "fftools_log.h" + + const char program_name[] = "ffplay"; + const int program_birth_year = 2003; +@@ fftools/ffplay.c: int main(int argc, char **argv) + init_dynload(); + + av_log_set_flags(AV_LOG_SKIP_REPEATED); ++ init_logging(); + parse_loglevel(argc, argv, options); + /* register all codecs, demux and protocols */ + + ## fftools/ffprobe.c ## +@@ + #include "libavfilter/version.h" + #include "cmdutils.h" + #include "opt_common.h" ++#include "fftools_log.h" + + #include "libavutil/thread.h" + +@@ fftools/ffprobe.c: int main(int argc, char **argv) + init_dynload(); + + av_log_set_flags(AV_LOG_SKIP_REPEATED); ++ init_logging(); + + options = real_options; + parse_loglevel(argc, argv, options); + + ## fftools/fftools_log.c (new) ## +@@ ++/* ++ * Copyright (c) The FFmpeg developers ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++ ++#include "config.h" ++ ++#if HAVE_UNISTD_H ++#include ++#endif ++#if HAVE_IO_H ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include "libavutil/bprint.h" ++#include "libavutil/common.h" ++//#include "libavutil/internal.h" ++#include "libavutil/log.h" ++#include "libavutil/thread.h" ++#include "libavutil/time.h" ++//#include "libavutil/time_internal.h" ++ ++#include "fftools_log.h" ++ ++ ++#if !HAVE_LOCALTIME_R && !defined(localtime_r) ++static inline struct tm *ff_localtime_r(const time_t* clock, struct tm *result) ++{ ++ struct tm *ptr = localtime(clock); ++ if (!ptr) ++ return NULL; ++ *result = *ptr; ++ return result; ++} ++#define localtime_r ff_localtime_r ++#endif ++ +static int nb_class_ids; + +#define NB_CLASS_IDS 1000 @@ fftools/cmdutils.c: AVDictionary *format_opts, *codec_opts; +static unsigned get_class_id(void* avcl) +{ + AVClass* avc = avcl ? *(AVClass **) avcl : NULL; -+ const char* class_name = avc->item_name(avcl); + unsigned i, nb_ids = 0; + uint64_t class_hash; + @@ fftools/cmdutils.c: AVDictionary *format_opts, *codec_opts; + return 0; +} + - void uninit_opts(void) - { - av_dict_free(&swr_opts); -@@ fftools/cmdutils.c: static void check_options(const OptionDef *po) - } - } - ++static AVMutex mutex = AV_MUTEX_INITIALIZER; ++ ++#define LINE_SZ 1024 ++ ++#if HAVE_VALGRIND_VALGRIND_H && CONFIG_VALGRIND_BACKTRACE ++#include ++/* this is the log level at which valgrind will output a full backtrace */ ++#define BACKTRACE_LOGLEVEL AV_LOG_ERROR ++#endif ++ ++#define NB_LEVELS 8 ++#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE ++#include ++static const uint8_t color[16 + AV_CLASS_CATEGORY_NB] = { ++ [AV_LOG_PANIC /8] = 12, ++ [AV_LOG_FATAL /8] = 12, ++ [AV_LOG_ERROR /8] = 12, ++ [AV_LOG_WARNING/8] = 14, ++ [AV_LOG_INFO /8] = 7, ++ [AV_LOG_VERBOSE/8] = 10, ++ [AV_LOG_DEBUG /8] = 10, ++ [AV_LOG_TRACE /8] = 8, ++ [16+AV_CLASS_CATEGORY_NA ] = 7, ++ [16+AV_CLASS_CATEGORY_INPUT ] = 13, ++ [16+AV_CLASS_CATEGORY_OUTPUT ] = 5, ++ [16+AV_CLASS_CATEGORY_MUXER ] = 13, ++ [16+AV_CLASS_CATEGORY_DEMUXER ] = 5, ++ [16+AV_CLASS_CATEGORY_ENCODER ] = 11, ++ [16+AV_CLASS_CATEGORY_DECODER ] = 3, ++ [16+AV_CLASS_CATEGORY_FILTER ] = 10, ++ [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 9, ++ [16+AV_CLASS_CATEGORY_SWSCALER ] = 7, ++ [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 7, ++ [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT ] = 13, ++ [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT ] = 5, ++ [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT ] = 13, ++ [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT ] = 5, ++ [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT ] = 13, ++ [16+AV_CLASS_CATEGORY_DEVICE_INPUT ] = 5, ++}; ++ ++static int16_t background, attr_orig; ++static HANDLE con; ++#else ++ ++static const uint32_t color[16 + AV_CLASS_CATEGORY_NB] = { ++ [AV_LOG_PANIC /8] = 52 << 16 | 196 << 8 | 0x41, ++ [AV_LOG_FATAL /8] = 208 << 8 | 0x41, ++ [AV_LOG_ERROR /8] = 196 << 8 | 0x11, ++ [AV_LOG_WARNING/8] = 226 << 8 | 0x03, ++ [AV_LOG_INFO /8] = 253 << 8 | 0x09, ++ [AV_LOG_VERBOSE/8] = 40 << 8 | 0x02, ++ [AV_LOG_DEBUG /8] = 34 << 8 | 0x02, ++ [AV_LOG_TRACE /8] = 34 << 8 | 0x07, ++ [16+AV_CLASS_CATEGORY_NA ] = 250 << 8 | 0x09, ++ [16+AV_CLASS_CATEGORY_INPUT ] = 219 << 8 | 0x15, ++ [16+AV_CLASS_CATEGORY_OUTPUT ] = 201 << 8 | 0x05, ++ [16+AV_CLASS_CATEGORY_MUXER ] = 213 << 8 | 0x15, ++ [16+AV_CLASS_CATEGORY_DEMUXER ] = 207 << 8 | 0x05, ++ [16+AV_CLASS_CATEGORY_ENCODER ] = 51 << 8 | 0x16, ++ [16+AV_CLASS_CATEGORY_DECODER ] = 39 << 8 | 0x06, ++ [16+AV_CLASS_CATEGORY_FILTER ] = 155 << 8 | 0x12, ++ [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 192 << 8 | 0x14, ++ [16+AV_CLASS_CATEGORY_SWSCALER ] = 153 << 8 | 0x14, ++ [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 147 << 8 | 0x14, ++ [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT ] = 213 << 8 | 0x15, ++ [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT ] = 207 << 8 | 0x05, ++ [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT ] = 213 << 8 | 0x15, ++ [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT ] = 207 << 8 | 0x05, ++ [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT ] = 213 << 8 | 0x15, ++ [16+AV_CLASS_CATEGORY_DEVICE_INPUT ] = 207 << 8 | 0x05, ++}; ++ ++#endif ++static int use_color = -1; ++ ++#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE ++static void win_console_puts(const char *str) ++{ ++ const uint8_t *q = str; ++ uint16_t line[LINE_SZ]; ++ ++ while (*q) { ++ uint16_t *buf = line; ++ DWORD nb_chars = 0; ++ DWORD written; ++ ++ while (*q && nb_chars < LINE_SZ - 1) { ++ uint32_t ch; ++ uint16_t tmp; ++ ++ GET_UTF8(ch, *q ? *q++ : 0, ch = 0xfffd; goto continue_on_invalid;) ++continue_on_invalid: ++ PUT_UTF16(ch, tmp, *buf++ = tmp; nb_chars++;) ++ } ++ ++ WriteConsoleW(con, line, nb_chars, &written, NULL); ++ } ++} ++#endif ++ ++static void check_color_terminal(void) ++{ ++ char *term = getenv("TERM"); ++ ++#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE ++ CONSOLE_SCREEN_BUFFER_INFO con_info; ++ DWORD dummy; ++ con = GetStdHandle(STD_ERROR_HANDLE); ++ if (con != INVALID_HANDLE_VALUE && !GetConsoleMode(con, &dummy)) ++ con = INVALID_HANDLE_VALUE; ++ if (con != INVALID_HANDLE_VALUE) { ++ GetConsoleScreenBufferInfo(con, &con_info); ++ attr_orig = con_info.wAttributes; ++ background = attr_orig & 0xF0; ++ } ++#endif ++ ++ if (getenv("AV_LOG_FORCE_NOCOLOR")) { ++ use_color = 0; ++ } else if (getenv("AV_LOG_FORCE_COLOR")) { ++ use_color = 1; ++ } else { ++#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE ++ use_color = (con != INVALID_HANDLE_VALUE); ++#elif HAVE_ISATTY ++ use_color = (term && isatty(2)); ++#else ++ use_color = 0; ++#endif ++ } ++ ++ if (getenv("AV_LOG_FORCE_256COLOR") || term && strstr(term, "256color")) ++ use_color *= 256; ++} ++ ++static void ansi_fputs(int level, int tint, const char *str, int local_use_color) ++{ ++ if (local_use_color == 1) { ++ fprintf(stderr, ++ "\033[%"PRIu32";3%"PRIu32"m%s\033[0m", ++ (color[level] >> 4) & 15, ++ color[level] & 15, ++ str); ++ } else if (tint && use_color == 256) { ++ fprintf(stderr, ++ "\033[48;5;%"PRIu32"m\033[38;5;%dm%s\033[0m", ++ (color[level] >> 16) & 0xff, ++ tint, ++ str); ++ } else if (local_use_color == 256) { ++ fprintf(stderr, ++ "\033[48;5;%"PRIu32"m\033[38;5;%"PRIu32"m%s\033[0m", ++ (color[level] >> 16) & 0xff, ++ (color[level] >> 8) & 0xff, ++ str); ++ } else ++ fputs(str, stderr); ++} ++ ++static void colored_fputs(int level, int tint, const char *str) ++{ ++ int local_use_color; ++ if (!*str) ++ return; ++ ++ if (use_color < 0) ++ check_color_terminal(); ++ ++ if (level == AV_LOG_INFO/8) local_use_color = 0; ++ else local_use_color = use_color; ++ ++#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE ++ if (con != INVALID_HANDLE_VALUE) { ++ if (local_use_color) ++ SetConsoleTextAttribute(con, background | color[level]); ++ win_console_puts(str); ++ if (local_use_color) ++ SetConsoleTextAttribute(con, attr_orig); ++ } else { ++ ansi_fputs(level, tint, str, local_use_color); ++ } ++#else ++ ansi_fputs(level, tint, str, local_use_color); ++#endif ++ ++} ++ ++static void sanitize(uint8_t *line){ ++ while(*line){ ++ if(*line < 0x08 || (*line > 0x0D && *line < 0x20)) ++ *line='?'; ++ line++; ++ } ++} ++ ++static int get_category(void *ptr){ ++ AVClass *avc = *(AVClass **) ptr; ++ if( !avc ++ || (avc->version&0xFF)<100 ++ || avc->version < (51 << 16 | 59 << 8) ++ || avc->category >= AV_CLASS_CATEGORY_NB) return AV_CLASS_CATEGORY_NA + 16; ++ ++ if(avc->get_category) ++ return avc->get_category(ptr) + 16; ++ ++ return avc->category + 16; ++} ++ ++static const char *get_level_str(int level) ++{ ++ switch (level) { ++ case AV_LOG_QUIET: ++ return "quiet"; ++ case AV_LOG_DEBUG: ++ return "debug"; ++ case AV_LOG_TRACE: ++ return "trace"; ++ case AV_LOG_VERBOSE: ++ return "verbose"; ++ case AV_LOG_INFO: ++ return "info"; ++ case AV_LOG_WARNING: ++ return "warning"; ++ case AV_LOG_ERROR: ++ return "error"; ++ case AV_LOG_FATAL: ++ return "fatal"; ++ case AV_LOG_PANIC: ++ return "panic"; ++ default: ++ return ""; ++ } ++} ++ +static const char *item_name(void *obj, const AVClass *cls) +{ + return (cls->item_name ? cls->item_name : av_default_item_name)(obj); +} + -+static void log_formatprefix_callback(AVBPrint* buffer, AVClass** avcl, int log_flags) ++static void format_date_now(AVBPrint* bp_time, int include_date) ++{ ++ struct tm *ptm, tmbuf; ++ const int64_t time_us = av_gettime(); ++ const int64_t time_ms = time_us / 1000; ++ const time_t time_s = time_ms / 1000; ++ const int millisec = time_ms - (time_s * 1000); ++ ptm = localtime_r(&time_s, &tmbuf); ++ if (ptm) { ++ if (include_date) ++ av_bprint_strftime(bp_time, "%Y-%m-%d ", ptm); ++ ++ av_bprint_strftime(bp_time, "%H:%M:%S", ptm); ++ av_bprintf(bp_time, ".%03d ", millisec); ++ } ++} ++ ++static void log_formatprefix(AVBPrint* buffer, AVClass** avcl, int log_flags) +{ + const int print_mem = log_flags & AV_LOG_PRINT_MEMADDRESSES; + if (print_mem) @@ fftools/cmdutils.c: static void check_options(const OptionDef *po) + av_bprintf(buffer+0, "[%s #%u] ", item_name(avcl, *avcl), get_class_id(avcl)); +} + -+void init_logformatting(void) ++static void format_line(void *avcl, int level, const char *fmt, va_list vl, ++ AVBPrint part[5], int *print_prefix, int type[2], int current_flags) +{ -+ av_log_set_formatprefix_callback(&log_formatprefix_callback); ++ AVClass* avc = avcl ? *(AVClass **) avcl : NULL; ++ av_bprint_init(part+0, 0, AV_BPRINT_SIZE_AUTOMATIC); ++ av_bprint_init(part+1, 0, AV_BPRINT_SIZE_AUTOMATIC); ++ av_bprint_init(part+2, 0, AV_BPRINT_SIZE_AUTOMATIC); ++ av_bprint_init(part+3, 0, 65536); ++ av_bprint_init(part+4, 0, AV_BPRINT_SIZE_AUTOMATIC); ++ ++ if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16; ++ if (*print_prefix && avc) { ++ ++ if (avc->parent_log_context_offset) { ++ AVClass** parent = *(AVClass ***) ((uint8_t *)avcl + avc->parent_log_context_offset); ++ if (parent && *parent) { ++ log_formatprefix(part, parent, current_flags); ++ if(type) type[0] = get_category(parent); ++ } ++ } ++ log_formatprefix(part, avcl, current_flags); ++ ++ if(type) type[1] = get_category(avcl); ++ } ++ ++ if (*print_prefix && (level > AV_LOG_QUIET) && (current_flags & (AV_LOG_PRINT_TIME | AV_LOG_PRINT_DATETIME))) ++ format_date_now(&part[4], current_flags & AV_LOG_PRINT_DATETIME); ++ ++ if (*print_prefix && (level > AV_LOG_QUIET) && (current_flags & AV_LOG_PRINT_LEVEL)) ++ av_bprintf(part+2, "[%s] ", get_level_str(level)); ++ ++ av_vbprintf(part+3, fmt, vl); ++ ++ if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) { ++ char lastc = part[3].len && part[3].len <= part[3].size ? part[3].str[part[3].len - 1] : 0; ++ *print_prefix = lastc == '\n' || lastc == '\r'; ++ } ++} ++ ++void fftools_log_callback(void* ptr, int level, const char* fmt, va_list vl) ++{ ++ static int print_prefix = 1; ++ static int count; ++ static char prev[LINE_SZ]; ++ AVBPrint part[5]; ++ char line[LINE_SZ]; ++ static int is_atty; ++ int type[2]; ++ unsigned tint = 0; ++ int current_flags = 0; ++ ++ if (level >= 0) { ++ tint = level & 0xff00; ++ level &= 0xff; ++ } ++ ++ if (level > av_log_get_level()) ++ return; ++ ++ current_flags = av_log_get_flags(); ++ ff_mutex_lock(&mutex); ++ ++ format_line(ptr, level, fmt, vl, part, &print_prefix, type, current_flags); ++ snprintf(line, sizeof(line), "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str); ++ ++#if HAVE_ISATTY ++ if (!is_atty) ++ is_atty = isatty(2) ? 1 : -1; ++#endif ++ ++ if (print_prefix && (current_flags & AV_LOG_SKIP_REPEATED) && !strcmp(line, prev) && ++ *line && line[strlen(line) - 1] != '\r'){ ++ count++; ++ if (is_atty == 1) ++ fprintf(stderr, " Last message repeated %d times\r", count); ++ goto end; ++ } ++ if (count > 0) { ++ fprintf(stderr, " Last message repeated %d times\n", count); ++ count = 0; ++ } ++ strcpy(prev, line); ++ ++ sanitize(part[4].str); ++ colored_fputs(7, 0, part[4].str); ++ sanitize(part[0].str); ++ colored_fputs(type[0], 0, part[0].str); ++ sanitize(part[1].str); ++ colored_fputs(type[1], 0, part[1].str); ++ sanitize(part[2].str); ++ colored_fputs(av_clip(level >> 3, 0, NB_LEVELS - 1), tint >> 8, part[2].str); ++ sanitize(part[3].str); ++ colored_fputs(av_clip(level >> 3, 0, NB_LEVELS - 1), tint >> 8, part[3].str); ++ ++#if CONFIG_VALGRIND_BACKTRACE ++ if (level <= BACKTRACE_LOGLEVEL) ++ VALGRIND_PRINTF_BACKTRACE("%s", ""); ++#endif ++end: ++ av_bprint_finalize(part+3, NULL); ++ ff_mutex_unlock(&mutex); +} + - void parse_loglevel(int argc, char **argv, const OptionDef *options) - { - int idx; ++ ++void init_logging(void) ++{ ++ av_log_set_callback(&fftools_log_callback); ++} - ## fftools/cmdutils.h ## -@@ fftools/cmdutils.h: int split_commandline(OptionParseContext *octx, int argc, char *argv[], - */ - void uninit_parse_context(OptionParseContext *octx); - + ## fftools/fftools_log.h (new) ## +@@ ++/* ++ * Copyright (c) The FFmpeg developers ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef FFTOOLS_FFTOOLS_LOG_H ++#define FFTOOLS_FFTOOLS_LOG_H ++ ++#include ++ ++#include "config.h" ++#include "libavcodec/avcodec.h" ++#include "libavfilter/avfilter.h" ++#include "libavformat/avformat.h" ++#include "libswscale/swscale.h" ++ ++ +/** -+ * Sets up formatting callbacks for logging ++ * Custom logging callback for fftools. + */ -+void init_logformatting(void); ++void fftools_log_callback(void* ptr, int level, const char* fmt, va_list vl); + - /** - * Find the '-loglevel' option in the command line args and apply it. - */ - - ## fftools/ffmpeg.c ## -@@ fftools/ffmpeg.c: int main(int argc, char **argv) - setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */ - - av_log_set_flags(AV_LOG_SKIP_REPEATED); -+ init_logformatting(); - parse_loglevel(argc, argv, options); - - #if CONFIG_AVDEVICE - - ## fftools/ffplay.c ## -@@ fftools/ffplay.c: int main(int argc, char **argv) - init_dynload(); - - av_log_set_flags(AV_LOG_SKIP_REPEATED); -+ init_logformatting(); - parse_loglevel(argc, argv, options); - - /* register all codecs, demux and protocols */ - - ## fftools/ffprobe.c ## -@@ fftools/ffprobe.c: int main(int argc, char **argv) - init_dynload(); - - av_log_set_flags(AV_LOG_SKIP_REPEATED); -+ init_logformatting(); - - options = real_options; - parse_loglevel(argc, argv, options); ++/** ++ * Sets the logging callback function. ++ */ ++void init_logging(void); ++ ++ ++#endif /* FFTOOLS_FFTOOLS_LOG_H */ 4: 9dc2cbe5ca = 4: 68a9ee6fbe doc/fftools-common-opts: document memaddresses log flag -- ffmpeg-codebot _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".