[FFmpeg-devel] [PATCH v6 0/3] avutil/log: Replace addresses in log output with simple ids
ffmpegagent
ffmpegagent at gmail.com
Thu Mar 13 11:30:38 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)
V5
==
* Remove unused var
* Add missing include to fix build error on PPC (thanks, Michael)
V6
==
* No more changes to avutil involved
* Let fftools have its own management of log level and flags (as figured to
be most likely what Nicolas George was alluding to)
softworkz (3):
fftools: Add a local logging callback function
fftools/opt_common: add memaddresses log flag
doc/fftools-common-opts: document memaddresses log flag
doc/fftools-common-opts.texi | 2 +
fftools/Makefile | 7 +-
fftools/cmdutils.c | 4 +-
fftools/ffmpeg.c | 10 +-
fftools/ffplay.c | 6 +-
fftools/ffprobe.c | 4 +-
fftools/fftools_log.c | 503 +++++++++++++++++++++++++++++++++++
fftools/fftools_log.h | 101 +++++++
fftools/opt_common.c | 47 ++--
9 files changed, 655 insertions(+), 29 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-v6
Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-59/softworkz/submit_logaddresses-v6
Pull-Request: https://github.com/ffstaging/FFmpeg/pull/59
Range-diff vs v5:
1: 4be966796c < -: ---------- avutil/log: Add AV_LOG_PRINT_MEMADDRESSES logging flag
2: e4f8213c24 < -: ---------- fftools/opt_common: add memaddresses log flag
3: ba20f5b116 ! 1: 8080f15800 fftools: Provide a an fftools-specific logging callback function
@@ Metadata
Author: softworkz <softworkz at hotmail.com>
## Commit message ##
- fftools: Provide a an fftools-specific logging callback function
+ fftools: Add a local logging callback function
- This goes together with a change to logging of context prefixes, which
- is printing logical ids instead of memory addresses.
- The benefits are:
+ This gets fftools its own management of log level and flags for and
+ provides an fftools-specific logging callback.
+ This makes it easier to implement specific logging behaviors which are
+ incompatible with direct use of the av libs and cannot be done in
+ libavutil.
- - 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
+ Signed-off-by: softworkz <softworkz at hotmail.com>
## fftools/Makefile ##
@@ fftools/Makefile: OBJS-ffmpeg += \
@@ fftools/Makefile: OBJS-ffmpeg += \
define DOFFTOOL
OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes)
+ ## fftools/cmdutils.c ##
+@@
+ #include "libavutil/dict.h"
+ #include "libavutil/opt.h"
+ #include "cmdutils.h"
++#include "fftools_log.h"
+ #include "fopen_utf8.h"
+ #include "opt_common.h"
+ #ifdef _WIN32
+@@ fftools/cmdutils.c: int opt_default(void *optctx, const char *opt, const char *arg)
+ #endif
+
+ if (!strcmp(opt, "debug") || !strcmp(opt, "fdebug"))
+- av_log_set_level(AV_LOG_DEBUG);
++ ff_log_set_level(AV_LOG_DEBUG);
+
+ if (!(p = strchr(opt, ':')))
+ p = opt + strlen(opt);
+
## fftools/ffmpeg.c ##
@@
#include "ffmpeg.h"
@@ fftools/ffmpeg.c
const char program_name[] = "ffmpeg";
const int program_birth_year = 2000;
+@@ fftools/ffmpeg.c: static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
+
+ if (print_stats || is_last_report) {
+ const char end = is_last_report ? '\n' : '\r';
+- if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) {
++ if (print_stats==1 && AV_LOG_INFO > ff_log_get_level()) {
+ fprintf(stderr, "%s %c", buf.str, end);
+ } else
+ av_log(NULL, AV_LOG_INFO, "%s %c", buf.str, end);
+@@ fftools/ffmpeg.c: static int check_keyboard_interaction(int64_t cur_time)
+ av_log(NULL, AV_LOG_INFO, "\n\n[q] command received. Exiting.\n\n");
+ return AVERROR_EXIT;
+ }
+- if (key == '+') av_log_set_level(av_log_get_level()+10);
+- if (key == '-') av_log_set_level(av_log_get_level()-10);
++ if (key == '+') ff_log_set_level(ff_log_get_level()+10);
++ if (key == '-') ff_log_set_level(ff_log_get_level()-10);
+ if (key == 'c' || key == 'C'){
+ char buf[4096], target[64], command[256], arg[256] = {0};
+ double time;
@@ 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);
+- av_log_set_flags(AV_LOG_SKIP_REPEATED);
++ ff_log_set_flags(FF_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"
@@ fftools/ffplay.c
const char program_name[] = "ffplay";
const int program_birth_year = 2003;
+@@ fftools/ffplay.c: display:
+ vqsize / 1024,
+ sqsize);
+
+- if (show_status == 1 && AV_LOG_INFO > av_log_get_level())
++ if (show_status == 1 && AV_LOG_INFO > ff_log_get_level())
+ fprintf(stderr, "%s", buf.str);
+ else
+ av_log(NULL, AV_LOG_INFO, "%s", buf.str);
@@ fftools/ffplay.c: int main(int argc, char **argv)
+
init_dynload();
- av_log_set_flags(AV_LOG_SKIP_REPEATED);
+- av_log_set_flags(AV_LOG_SKIP_REPEATED);
++ ff_log_set_flags(FF_LOG_SKIP_REPEATED);
+ init_logging();
parse_loglevel(argc, argv, options);
@@ fftools/ffprobe.c
#include "libavutil/thread.h"
@@ fftools/ffprobe.c: int main(int argc, char **argv)
+
init_dynload();
- av_log_set_flags(AV_LOG_SKIP_REPEATED);
+- av_log_set_flags(AV_LOG_SKIP_REPEATED);
++ ff_log_set_flags(FF_LOG_SKIP_REPEATED);
+ init_logging();
options = real_options;
@@ fftools/fftools_log.c (new)
+
+#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"
+
+
++static int ff_log_level = AV_LOG_INFO;
++static int ff_log_flags;
++
++
+#if !HAVE_LOCALTIME_R && !defined(localtime_r)
+static inline struct tm *ff_localtime_r(const time_t* clock, struct tm *result)
+{
@@ fftools/fftools_log.c (new)
+#define localtime_r ff_localtime_r
+#endif
+
-+#define MAX_CLASS_IDS 1000
-+static struct class_ids {
-+ void *avcl;
-+ uint64_t class_hash;
-+ unsigned id;
-+} class_ids[MAX_CLASS_IDS];
-+
-+static uint64_t fnv_hash(const char *str)
-+{
-+ // FNV-1a 64-bit hash algorithm
-+ uint64_t hash = 0xcbf29ce484222325ULL;
-+ while (*str) {
-+ hash ^= (unsigned char)*str++;
-+ hash *= 0x100000001b3ULL;
-+ }
-+ return hash;
-+}
-+
-+static unsigned get_class_id(void* avcl)
-+{
-+ AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
-+ unsigned i, nb_ids = 0;
-+ uint64_t class_hash;
-+
-+ for (i = 0; i < MAX_CLASS_IDS && class_ids[i].avcl; i++) {
-+ if (class_ids[i].avcl == avcl)
-+ return class_ids[i].id;
-+ }
-+
-+ class_hash = fnv_hash(avc->class_name);
-+
-+ for (i = 0; i < MAX_CLASS_IDS; i++) {
-+ if (class_ids[i].class_hash == class_hash)
-+ nb_ids++;
-+
-+ if (!class_ids[i].avcl) {
-+ class_ids[i].avcl = avcl;
-+ class_ids[i].class_hash = class_hash;
-+ class_ids[i].id = nb_ids;
-+ return class_ids[i].id;
-+ }
-+ }
-+
-+ // exceeded MAX_CLASS_IDS entries in class_ids[]
-+ return 0;
-+}
-+
+static AVMutex mutex = AV_MUTEX_INITIALIZER;
+
+#define LINE_SZ 1024
@@ fftools/fftools_log.c (new)
+ }
+}
+
-+static void log_formatprefix(AVBPrint* buffer, AVClass** avcl, int log_flags)
-+{
-+ const int print_mem = log_flags & AV_LOG_PRINT_MEMADDRESSES;
-+ if (print_mem)
-+ av_bprintf(buffer+0, "[%s @ %p] ", item_name(avcl, *avcl), avcl);
-+ else
-+ av_bprintf(buffer+0, "[%s #%u] ", item_name(avcl, *avcl), get_class_id(avcl));
-+}
-+
+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)
++ AVBPrint part[5], int *print_prefix, int type[2])
+{
+ AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
+ av_bprint_init(part+0, 0, AV_BPRINT_SIZE_AUTOMATIC);
@@ fftools/fftools_log.c (new)
+
+ 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) {
-+ log_formatprefix(part, parent, current_flags);
++ av_bprintf(part+0, "[%s @ %p] ",
++ item_name(parent, *parent), parent);
+ if(type) type[0] = get_category(parent);
+ }
+ }
-+ log_formatprefix(part, avcl, current_flags);
-+
++ av_bprintf(part+1, "[%s @ %p] ",
++ item_name(avcl, avc), avcl);
+ 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) && (ff_log_flags & (FF_LOG_PRINT_TIME | FF_LOG_PRINT_DATETIME)))
++ format_date_now(&part[4], ff_log_flags & FF_LOG_PRINT_DATETIME);
+
-+ if (*print_prefix && (level > AV_LOG_QUIET) && (current_flags & AV_LOG_PRINT_LEVEL))
++ if (*print_prefix && (level > AV_LOG_QUIET) && (ff_log_flags & FF_LOG_PRINT_LEVEL))
+ av_bprintf(part+2, "[%s] ", get_level_str(level));
+
+ av_vbprintf(part+3, fmt, vl);
@@ fftools/fftools_log.c (new)
+ 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())
++ if (level > ff_log_level)
+ return;
+
-+ current_flags = av_log_get_flags();
+ ff_mutex_lock(&mutex);
+
-+ format_line(ptr, level, fmt, vl, part, &print_prefix, type, current_flags);
++ format_line(ptr, level, fmt, vl, part, &print_prefix, type);
+ snprintf(line, sizeof(line), "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);
+
+#if HAVE_ISATTY
@@ fftools/fftools_log.c (new)
+ is_atty = isatty(2) ? 1 : -1;
+#endif
+
-+ if (print_prefix && (current_flags & AV_LOG_SKIP_REPEATED) && !strcmp(line, prev) &&
++ if (print_prefix && (ff_log_flags & FF_LOG_SKIP_REPEATED) && !strcmp(line, prev) &&
+ *line && line[strlen(line) - 1] != '\r'){
+ count++;
+ if (is_atty == 1)
@@ fftools/fftools_log.c (new)
+{
+ av_log_set_callback(&fftools_log_callback);
+}
++
++int ff_log_get_level(void)
++{
++ return ff_log_level;
++}
++
++void ff_log_set_level(int level)
++{
++ ff_log_level = level;
++
++ av_log_set_level(level);
++}
++
++void ff_log_set_flags(int arg)
++{
++ ff_log_flags = arg;
++}
++
++int ff_log_get_flags(void)
++{
++ return ff_log_flags;
++}
++
## fftools/fftools_log.h (new) ##
@@
@@ fftools/fftools_log.h (new)
+void init_logging(void);
+
+
++/**
++ * Get the current log level
++ *
++ * @see lavu_log_constants
++ *
++ * @return Current log level
++ */
++int ff_log_get_level(void);
++
++/**
++ * Set the log level
++ *
++ * @see lavu_log_constants
++ *
++ * @param level Logging level
++ */
++void ff_log_set_level(int level);
++
++void ff_log_set_flags(int arg);
++
++int ff_log_get_flags(void);
++
++
++/**
++ * Skip repeated messages, this requires the user app to use av_log() instead of
++ * (f)printf as the 2 would otherwise interfere and lead to
++ * "Last message repeated x times" messages below (f)printf messages with some
++ * bad luck.
++ * Also to receive the last, "last repeated" line if any, the user app must
++ * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end
++ */
++#define FF_LOG_SKIP_REPEATED 1
++
++/**
++ * Include the log severity in messages originating from codecs.
++ *
++ * Results in messages such as:
++ * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts
++ */
++#define FF_LOG_PRINT_LEVEL 2
++
++/**
++ * Include system time in log output.
++ */
++#define FF_LOG_PRINT_TIME 4
++
++/**
++ * Include system date and time in log output.
++ */
++#define FF_LOG_PRINT_DATETIME 8
++
++
+#endif /* FFTOOLS_FFTOOLS_LOG_H */
+
+ ## fftools/opt_common.c ##
+@@
+ #include "cmdutils.h"
+ #include "opt_common.h"
+
++#include "fftools_log.h"
+ #include "libavutil/avassert.h"
+ #include "libavutil/avstring.h"
+ #include "libavutil/bprint.h"
+@@ fftools/opt_common.c: int init_report(const char *env, FILE **file)
+ return AVERROR(ENOMEM);
+ }
+
+- prog_loglevel = av_log_get_level();
++ prog_loglevel = ff_log_get_level();
+ if (!envlevel)
+ report_file_level = FFMAX(report_file_level, prog_loglevel);
+
+@@ fftools/opt_common.c: int opt_loglevel(void *optctx, const char *opt, const char *arg)
+ };
+ const char *token;
+ char *tail;
+- int flags = av_log_get_flags();
+- int level = av_log_get_level();
++ int flags = ff_log_get_flags();
++ int level = ff_log_get_level();
+ int cmd, i = 0;
+
+ av_assert0(arg);
+@@ fftools/opt_common.c: int opt_loglevel(void *optctx, const char *opt, const char *arg)
+ }
+ if (av_strstart(token, "repeat", &arg)) {
+ if (cmd == '-') {
+- flags |= AV_LOG_SKIP_REPEATED;
++ flags |= FF_LOG_SKIP_REPEATED;
+ } else {
+- flags &= ~AV_LOG_SKIP_REPEATED;
++ flags &= ~FF_LOG_SKIP_REPEATED;
+ }
+ } else if (av_strstart(token, "level", &arg)) {
+ if (cmd == '-') {
+- flags &= ~AV_LOG_PRINT_LEVEL;
++ flags &= ~FF_LOG_PRINT_LEVEL;
+ } else {
+- flags |= AV_LOG_PRINT_LEVEL;
++ flags |= FF_LOG_PRINT_LEVEL;
+ }
+ } else if (av_strstart(token, "time", &arg)) {
+ if (cmd == '-') {
+- flags &= ~AV_LOG_PRINT_TIME;
++ flags &= ~FF_LOG_PRINT_TIME;
+ } else {
+- flags |= AV_LOG_PRINT_TIME;
++ flags |= FF_LOG_PRINT_TIME;
+ }
+ } else if (av_strstart(token, "datetime", &arg)) {
+ if (cmd == '-') {
+- flags &= ~AV_LOG_PRINT_DATETIME;
++ flags &= ~FF_LOG_PRINT_DATETIME;
+ } else {
+- flags |= AV_LOG_PRINT_DATETIME;
++ flags |= FF_LOG_PRINT_DATETIME;
+ }
+ } else {
+ break;
+@@ fftools/opt_common.c: int opt_loglevel(void *optctx, const char *opt, const char *arg)
+ } else if (*arg == '+') {
+ arg++;
+ } else if (!i) {
+- flags = av_log_get_flags(); /* level value without prefix, reset flags */
++ flags = ff_log_get_flags(); /* level value without prefix, reset flags */
+ }
+
+ for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) {
+@@ fftools/opt_common.c: int opt_loglevel(void *optctx, const char *opt, const char *arg)
+ }
+
+ end:
+- av_log_set_flags(flags);
+- av_log_set_level(level);
++ ff_log_set_flags(flags);
++ ff_log_set_level(level);
+ return 0;
+ }
+
+@@ fftools/opt_common.c: int show_sources(void *optctx, const char *opt, const char *arg)
+ char *dev = NULL;
+ AVDictionary *opts = NULL;
+ int ret = 0;
+- int error_level = av_log_get_level();
++ int error_level = ff_log_get_level();
+
+- av_log_set_level(AV_LOG_WARNING);
++ ff_log_set_level(AV_LOG_WARNING);
+
+ if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
+ goto fail;
+@@ fftools/opt_common.c: int show_sources(void *optctx, const char *opt, const char *arg)
+ fail:
+ av_dict_free(&opts);
+ av_free(dev);
+- av_log_set_level(error_level);
++ ff_log_set_level(error_level);
+ return ret;
+ }
+
+@@ fftools/opt_common.c: int show_sinks(void *optctx, const char *opt, const char *arg)
+ char *dev = NULL;
+ AVDictionary *opts = NULL;
+ int ret = 0;
+- int error_level = av_log_get_level();
++ int error_level = ff_log_get_level();
+
+- av_log_set_level(AV_LOG_WARNING);
++ ff_log_set_level(AV_LOG_WARNING);
+
+ if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0)
+ goto fail;
+@@ fftools/opt_common.c: int show_sinks(void *optctx, const char *opt, const char *arg)
+ fail:
+ av_dict_free(&opts);
+ av_free(dev);
+- av_log_set_level(error_level);
++ ff_log_set_level(error_level);
+ return ret;
+ }
+ #endif /* CONFIG_AVDEVICE */
-: ---------- > 2: bab6b91549 fftools/opt_common: add memaddresses log flag
4: f689a432df = 3: ea2a970d23 doc/fftools-common-opts: document memaddresses log flag
5: 9429d11516 < -: ---------- Remove commented lines
--
ffmpeg-codebot
More information about the ffmpeg-devel
mailing list