ffmpeg-日志输出av_log()

本文分析一下FFmpeg的日志(Log)输出系统的源代码。日志输出部分的核心函数只有一个:av_log()
函数调用结构图
FFmpeg日志输出系统的函数调用结构图。
在这里插入图片描述
av_log()
av_log()是FFmpeg中输出日志的函数。随便打开一个FFmpeg的源代码文件,就会发现其中遍布着av_log()函数。一般情况下FFmpeg类库的源代码中是不允许使用printf()这种的函数的,所有的输出一律使用av_log()。
av_log()的头文件:libavutil\log.h

void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4);  

这个函数的声明有两个地方比较特殊:
(1)函数最后一个参数是“…”。
在C语言中,在函数参数数量不确定的情况下使用“…”来代表参数。printf()的原型定义如下:

int printf (const char*, ...);

(2)声明后面有一个av_printf_format(3, 4)。网上资料说它的作用是按照printf()的格式检查av_log()的格式。
av_log()每个字段的含义如下:
avcl:指定一个包含AVClass的结构体。
level:log的级别
fmt:和printf()一样。
由此可见,av_log()和printf()的不同主要在于前面多了两个参数。其中第一个参数指定该log所属的结构体,例如AVFormatContext、AVCodecContext等等。第二个参数指定log的级别,源代码中定义了如下几个级别。

#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 

从定义中可知,随着严重程度逐渐下降,一共包含如下级别:AV_LOG_PANIC,AV_LOG_FATAL,AV_LOG_ERROR,AV_LOG_WARNING,AV_LOG_INFO,AV_LOG_VERBOSE,AV_LOG_DEBUG。每个级别定义的数值代表了严重程度,数值越小代表越严重。默认的级别是AV_LOG_INFO。此外,还有一个级别不输出任何信息,即AV_LOG_QUIET

当前系统存在着一个“Log级别”。所有严重程度高于该级别的Log信息都会输出出来。例如当前的Log级别是AV_LOG_WARNING,则会输出AV_LOG_PANIC,AV_LOG_FATAL,AV_LOG_ERROR,AV_LOG_WARNING级别的信息,而不会输出AV_LOG_INFO级别的信息。可以通过av_log_get_level()获得当前Log的级别,通过另一个函数av_log_set_level()设置当前的Log级别。
av_log_get_level(), av_log_set_level()定义如下:
通过av_log_set_level()设置当前Log的级别,通过av_log_get_level()获取当前Log的级别

void av_log_set_level(int level)  
{  
    av_log_level = level;  
}
int av_log_get_level(void)  
{  
    return av_log_level;  
}

以上两个函数主要操作了一个静态全局变量av_log_level。该变量用于存储当前系统Log的级别。

static int av_log_level = AV_LOG_INFO;

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);  
}

首先来提一下C语言函数中“…”参数的含义。与它相关还涉及到以下4个部分:
(1)va_list变量
(2)va_start()
(3)va_arg()
(4)va_end()
va_list是一个指向函数的参数的指针。va_start()用于初始化va_list变量。va_arg()用于返回可变参数。va_start()用于结束可变参数的获取。有关它们的用法可以参考一个小demo:

#include <stdio.h>  
#include<stdarg.h>  
void fun(int a,...){  
    va_list pp;  
    va_start(pp,a);  
    do{  
        printf("param =%d\n",a);  
        a=va_arg(pp,int);//使 pp 指向下一个参数,将下一个参数的值赋给变量 a  
    }  
    while (a!=0);//直到参数为 0 时停止循环  
}  
void main(){  
    fun(20,40,60,80,0);  
} 

av_log()的源代码中,在va_start()和va_end()之间,调用了另一个函数av_vlog()。
av_vlog()是一个FFmpeg的API函数。它的声明位于libavutil\log.h中

void av_vlog(void *avcl, int level, const char *fmt, va_list vl);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值