概述
一、ffmpeg的日志系统,个人感觉主要好在以下几个方面:
1.有颜色输出
2.标志输出的日志信息属于哪一个模块
3.输出信息的日志等级可控。也就是说通过控制,输出的日志信息内容会不同
二、 简单分析ffmpeg日志系统的处理机制:
2.1、 例如,当命令是-loglevel trace时,ffmpeg内部是怎样处理的?
av_log(avctx, AV_LOG_VERBOSE, “Codec not supportedn”);执行这一行代码,内部发生什么?
int main(int argc, char **argv)
{
.....
/*与重复信息的处理有关*/
av_log_set_flags(AV_LOG_SKIP_REPEATED);
/*解析设置loglevel的命令*/
parse_loglevel(argc, argv, options);
.....
}
void parse_loglevel(int argc, char **argv, const OptionDef *options)
{
/*查找匹配命令
*命令会在数组const OptionDef options[] 查找----ffmpeg_opt.c
*/
int idx = locate_option(argc, argv, options, "loglevel");
const char *env;
check_options(options);
if (!idx)
idx = locate_option(argc, argv, options, "v");
/*设置loglevel命令*/
if (idx && argv[idx + 1])
opt_loglevel(NULL, "loglevel", argv[idx + 1]);
/*这里涉及到report和hide_banner的处理*/
idx = locate_option(argc, argv, options, "report");
if ((env = getenv("FFREPORT")) || idx) {
init_report(env);
if (report_file) {
int i;
fprintf(report_file, "Command line:n");
for (i = 0; i < argc; i++) {
dump_argument(argv[i]);
fputc(i < argc - 1 ? ' ' : 'n', report_file);
}
fflush(report_file);
}
}
idx = locate_option(argc, argv, options, "hide_banner");
if (idx)
hide_banner = 1;
}
为了阅读,省略部分代码
int opt_loglevel(void *optctx, const char *opt, const char *arg)
{
/*日志等级,从上往下看,等级越靠前,代表输出信息等级高
*输出信息可控的意思就是,如果设置AV_LOG_FATAL等级,那么
*AV_LOG_DEBUG等级的日志信息不会输出;
*如果设置日志等级AV_LOG_DEBUG,
*AV_LOG_DEBUG前面等级的日志信息都会输出
*/
const struct { const char *name; int level; } log_levels[] = {
{ "quiet" , AV_LOG_QUIET },
{ "panic" , AV_LOG_PANIC },
{ "fatal" , AV_LOG_FATAL },
{ "error" , AV_LOG_ERROR },
{ "warning", AV_LOG_WARNING },
{ "info" , AV_LOG_INFO },
{ "verbose", AV_LOG_VERBOSE },
{ "debug" , AV_LOG_DEBUG },
{ "trace" , AV_LOG_TRACE },
};
........
/*匹配,调用设置av_log_set_level*/
for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) {
if (!strcmp(log_levels[i].name, arg)) {
av_log_set_level(log_levels[i].level);
return 0;
}
}
.......
}
这样就把日志等级给设置上了,-loglevel trace这个命令的最终结果就是执行
av_log_set_level(AV_LOG_TRACE)
从这里开始就开始进入libavutil/log.c这个文件,日志系统的处理集中在这个文件
void av_log_set_level(int level)
{
av_log_level = level;
}
av_log_level是一个全局变量
2.2、讲完了日志等级的设置,简单分析 执行 av_log(avctx, AV_LOG_VERBOSE, “Codec not supportedn”),内部发生了什么?
由于涉及的源码较多,简单的梳理调用流程,细节稍后看下面的链接 。
调用流程。从上往下依次调用
av_log
av_vlog
av_log_default_callback ---主要是对AVBPrint结构体的处理
format_line --------------格式控制
av_bprintf(part+1, "[%s @ %p"----模块信息
av_vbprintf(part+3, fmt, vl); ---主要信息
colored_fputs ----------给数据上色,颜色输出
整一个调用的关键部分大概就是上述那样,下面拆解分析:
av_log_default_callback—-这是一个回调函数,支持用户自定义,一般情况下都是使用源码默认的。
这个函数有一个声明AVBPrint part[4];
也就是说输出的日志信息是由四个部分组成,通常情况下,主要使用到第一部分和第四部分,也就是part[1]和part[3]
这个函数主要是调用format_line,对AVBPrint结构体的处理。
format_line ———关键函数
对AVBPrint结构体的处理,处理AVBPrint part[4],规定日志信息的输出格式。
colored_fputs ———-给数据上色,颜色输出
/一般的颜色关系
e[30m – e[37m 设置前景色(字体颜色)
echo -e “e[30m” 灰色
echo -e “e[31m” 红色
echo -e “e[32m” 绿色
echo -e “e[33m” 黄色
echo -e “e[34m” 蓝色
echo -e “e[35m” 紫色
echo -e “e[36m” 淡蓝色
echo -e “e[37m” 白色
e[40m – e[47m 设置背景色
echo -e “e[40m” 灰色
echo -e “e[41m” 红色
echo -e “e[42m” 绿色
echo -e “e[43m” 黄色
echo -e “e[44m” 蓝色
echo -e “e[45m” 紫色
echo -e “e[46m” 淡蓝色
echo -e “e[47m” 白色
总结整一个日志系统的处理思路:
1. 将要打印的信息分为四部分,第四部分就是用户想要打印的信息,其他三部分就是源码为了查阅方便,自我添加额外的输出信息
2.之后就是把传进来的打印信息用stdarg这个库的接口处理好
3.给打印信息上色
4.优化,控制打印的输出内容
if (level > av_log_level)
return;
http://blog.csdn.net/leixiaohua1020/article/details/44243155 —–日志输入系统详细介绍
常用stdarg这个库接口简单说明
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址
#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
总结:读取可变参数的过程其实就是堆栈中,使用指针,遍历堆栈段中的参数列表
最后
以上就是外向西牛为你收集整理的ffmpeg-日志系统的全部内容,希望文章能够帮你解决ffmpeg-日志系统所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复