[FFmpeg-devel] [PATCH v4 3/4] fftools: Provide a an fftools-specific logging callback function
softworkz
ffmpegagent at gmail.com
Sun Mar 9 01:02:43 EET 2025
From: softworkz <softworkz at hotmail.com>
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
- 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
---
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 ++++
7 files changed, 537 insertions(+), 2 deletions(-)
create mode 100644 fftools/fftools_log.c
create mode 100644 fftools/fftools_log.h
diff --git a/fftools/Makefile b/fftools/Makefile
index 4499799818..5ae3e7af10 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -19,10 +19,15 @@ 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 \
-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)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index dc321fb4a2..dc73d38f1f 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -81,6 +81,7 @@
#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;
@@ -955,6 +956,7 @@ 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
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index cd8a4abc52..57a83f6e3a 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1,5 +1,5 @@
/*
- * ffmpeg filter configuration
+ * Copyright (c) The FFmpeg developers
*
* This file is part of FFmpeg.
*
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index 2a572fc3aa..e4e90187f5 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -57,6 +57,7 @@
#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;
@@ -3762,6 +3763,7 @@ 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 */
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 7341731d2f..2e4d6d0f3e 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -68,6 +68,7 @@
#include "libavfilter/version.h"
#include "cmdutils.h"
#include "opt_common.h"
+#include "fftools_log.h"
#include "libavutil/thread.h"
@@ -4652,6 +4653,7 @@ 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);
diff --git a/fftools/fftools_log.c b/fftools/fftools_log.c
new file mode 100644
index 0000000000..206dffe56f
--- /dev/null
+++ b/fftools/fftools_log.c
@@ -0,0 +1,480 @@
+/*
+ * 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
+static struct class_ids {
+ void *avcl;
+ uint64_t class_hash;
+ unsigned id;
+} class_ids[NB_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 < NB_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 < NB_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 NB_CLASS_IDS entries in class_ids[]
+ return 0;
+}
+
+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 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)
+ 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)
+{
+ 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 init_logging(void)
+{
+ av_log_set_callback(&fftools_log_callback);
+}
diff --git a/fftools/fftools_log.h b/fftools/fftools_log.h
new file mode 100644
index 0000000000..da24866045
--- /dev/null
+++ b/fftools/fftools_log.h
@@ -0,0 +1,44 @@
+/*
+ * 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"
+
+
+/**
+ * Custom logging callback for fftools.
+ */
+void fftools_log_callback(void* ptr, int level, const char* fmt, va_list vl);
+
+/**
+ * Sets the logging callback function.
+ */
+void init_logging(void);
+
+
+#endif /* FFTOOLS_FFTOOLS_LOG_H */
--
ffmpeg-codebot
More information about the ffmpeg-devel
mailing list