[FFmpeg-devel] [PATCH v4 0/4] avutil/log: Replace addresses in log output with simple ids
ffmpegagent
ffmpegagent at gmail.com
Sun Mar 9 01:02:40 EET 2025
..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 <softworkz at hotmail.com>
## 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 <softworkz at hotmail.com>
@@ 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 <stdarg.h>
- #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 <softworkz at hotmail.com>
## 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 <unistd.h>
++#endif
++#if HAVE_IO_H
++#include <io.h>
++#endif
++#include <inttypes.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#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 <valgrind/valgrind.h>
++/* 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 <windows.h>
++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 <stdint.h>
++
++#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
More information about the ffmpeg-devel
mailing list