今天学习日志相关内容,记录下来,以免忘记,在FFmpeg中使用av_log()来打印日志信息,首先函数定义在libavutil/log.c中
void av_log(void* avcl, int level, const char *fmt, ...)
{
AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
va_list vl;
va_start(vl, fmt);
if (avc && avc->version >= (50 << 16 | 15 << 8 | 2) &&
avc->log_level_offset_offset && level >= AV_LOG_FATAL)
level += *(int *) (((uint8_t *) avcl) + avc->log_level_offset_offset);
av_vlog(avcl, level, fmt, vl);
va_end(vl);
}
1、可以看到这个函数传入的参数是可变参“、、、”,也就是传入参数的个数不确定,简要介绍传入参数的含义
avcl:指定一个包含AVClass的结构体。
level:log的级别
fmt:和printf()一样。
avcl是指定log属于哪个结构体,例如AVFormatContext、AVCodecContext等,
level指定了log的级别,FFmpeg中定义了以下几种level:
#define AV_LOG_QUIET -8
#define AV_LOG_PANIC 0
#define AV_LOG_FATAL 8
#define AV_LOG_ERROR 16
#define AV_LOG_WARNING 24
#define AV_LOG_INFO 32
#define AV_LOG_VERBOSE 40
#define AV_LOG_DEBUG 48
#define AV_LOG_TRACE 56
#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET)
级别对应的数值越小级别越高,可以通过av_log_set_level来设置log的级别,数值大于设定的level等级的log都不会被打印出来,通过av_log_get_level()可以获得当前Log的级别。
2、
下面再来看函数的源码,其中
(1)va_list
(2)va_start()
(3)va_arg()
(4)va_end()
这是c语言中的东西,C语言中执行程序时入栈的顺序是从右向左,例如void fun(int a,int b,int c),
0x1ffc–>a (4字节)
0x2000–>b (4字节)
0x2004–>c (4字节)
因此,函数的所有参数是存储在线性连续的栈空间中的,基于这种存储结构,这样就可以从可变参数函数中必须有的第一个普通参数来寻址后续的所有可变参数的类型及其值。而对于可变参也就是通过地址偏移来定位到传入的参数,使用可变参数应该有以下步骤:
1)首先在函数里定义一个va_list型的变量,这里是vl,这个变量是指向参数的指针.
2)然后用va_start宏初始化变量vl,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数.
3)然后用va_arg返回可变的参数,如果函数有多个可变参数的,依次调用va_arg获取各个参数.
4)最后用va_end宏结束可变参数的获取.
3、在va_start和va_end之间调用了av_vlog,
void av_vlog(void* avcl, int level, const char *fmt, va_list vl)
{
void (*log_callback)(void*, int, const char*, va_list) = av_log_callback;
if (log_callback)
log_callback(avcl, level, fmt, vl);
}
从定义中可以看出,av_vlog()简单调用了一个函数指针av_log_callback。av_log_callback是一个全局静态变量,定义如下所示。
static void (*av_log_callback)(void*, int, const char*, va_list) =
av_log_default_callback;
av_log_default_callback是FFmpeg中默认的log函数,我们可以构造一个参数为(void*, int, const char*, va_list),返回值为void的函数作为Log函数,通过av_log_set_callback函数来设置。
av_log_default_callback 代码很多,主要是因为他还包含了很多的功能,比如说根据Log级别的不同将输出的文本设置成不同的颜色等等。不再详细分析。
下面借图一张: