一般使用Error, Warning, Debug3个级别即可(见下面的颜色)。AV_LOG_QUIET

核心函数只有一个:av_log()。使用av_log()在控制台输出日志的效果如下图所示。

av_log()

av_log()是FFmpeg中输出日志的函数。随便打开一个FFmpeg的源代码文件,就会发现其中遍布着av_log()函数。一般情况下FFmpeg类库的源代码中是不允许使用printf()这种的函数的,所有的输出一律使用av_log()。
av_log()的声明位于libavutil\log.h,如下所示。

  1. * Send the specified message to the log if the level is less than or equal
  2. * to the current av_log_level. By default, all logging messages are sent to
  3. * stderr. This behavior can be altered by setting a different logging callback
  4. * function.
  5. * @see av_log_set_callback
  6. *
  7. * @param avcl A pointer to an arbitrary struct of which the first field is a
  8. *        pointer to an AVClass struct.
  9. * @param level The importance level of the message expressed using a @ref
  10. *        lavu_log_constants "Logging Constant".
  11. * @param fmt The format string (printf-compatible) that specifies how
  12. *        subsequent arguments are converted to output.
  13. */
  14. void av_log(void *avcl, int level, constchar *fmt, ...) av_printf_format(3, 4);
 av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
 av_log(avctx, AV_LOG_ERROR, "Dimensions %dx%d not supported.\n", width, avctx->height);

这个函数的声明有两个地方比较特殊:

(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的级别:

有一个级别不输出任何信息,即AV_LOG_QUIET。

可以通过av_log_get_level()获得当前Log的级别,通过另一个函数av_log_set_level()设置当前的Log级别。

我们看一下H.264编码的时候libx264的Log输出的示例:

下面回到av_log()函数的源代码。它的源代码位于libavutil\log.c,如下所示。

  1. void av_log(void* avcl, int level, constchar *fmt, ...)
  2. {
  3. AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
  4. va_list vl;
  5. va_start(vl, fmt);
  6. if (avc && avc->version >= (50 << 16 | 15 << 8 | 2) &&
  7. avc->log_level_offset_offset && level >= AV_LOG_FATAL)
  8. level += *(int *) (((uint8_t *) avcl) + avc->log_level_offset_offset);
  9. av_vlog(avcl, level, fmt, vl);
  10. va_end(vl);
  11. }

首先来提一下C语言函数中“…”参数的含义。与它相关还涉及到以下4个部分:

(1)va_list变量
(2)va_start()
(3)va_arg()
(4)va_end()

va_list是一个指向函数的参数的指针。va_start()用于初始化va_list变量。va_arg()用于返回可变参数。va_end()用于结束可变参数的获取。有关它们的用法可以参考一个小demo,如下所示。

  1. [0m"

(3)颜色对应关系如下所示:
\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"    白色

具体到编程中,printf() 颜色设置示例代码如下所示。

  1. int main()
  2. {
  3. printf("\e[31m Hello World. \e[0m \n"); // 红色字体
  4. return 0;
  5. }

Windows下控制台文字上色的方法

Windows下控制台颜色是通过SetConsoleTextAttribute()函数完成的。SetConsoleTextAttribute()函数的原型如下所示。

  1. BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);

其中2个参数的含义如下所示:

hConsoleOutput:指向控制台的句柄。
wAttributes:文本属性。

hConsoleOutput可以选择以下3种句柄:

STD_INPUT_HANDLE:标准输入的句柄
STD_OUTPUT_HANDLE:标准输出的句柄
STD_ERROR_HANDLE:标准错误的句柄

wAttributes可以控制前景色和背景色:

FOREGROUND_BLUE:字体颜色:蓝
FOREGROUND_GREEN:字体颜色:绿
FOREGROUND_RED:字体颜色:红
FOREGROUND_INTENSITY:前景色高亮显示
BACKGROUND_BLUE:背景颜色:蓝
BACKGROUND_GREEN:背景颜色:绿
BACKGROUND_RED:背景颜色:红
BACKGROUND_INTENSITY背景色高亮显示

控制台文本上色demo代码如下所示。

  1. #include
  2. #include
  3. int main()
  4. {
  5. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
  6. printf("red\n");
  7. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
  8. printf("green\n");
  9. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE);
  10. printf("blue\n");
  11. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED|FOREGROUND_GREEN);
  12. printf("red+green=yellow\n");
  13. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED|FOREGROUND_BLUE);
  14. printf("red+blue=purple\n");
  15. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN|FOREGROUND_BLUE);
  16. printf("green+blue=cyan\n");
  17. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED|BACKGROUND_GREEN);
  18. printf("Add background\n");
  19. return 0;
  20. }

程序的运行结果如下图所示。

colored_fputs()源代码

从colored_fputs()的源代码中可以看出如下流程:
首先根据宏定义判定系统的类型,如果系统类型是Windows,那么就调用SetConsoleTextAttribute()方法设定控制台文本的颜色,然后调用fputs()将Log记录输出到stderr(注意不是stdout);

如果系统类型是Linux,则通过添加特定字符串的方式设定控制台文本的颜色,然后将Log记录输出到stderr。
至此FFmpeg的日志输出系统的源代码就分析完毕了。

av_log() 函数
avcl:指定一个包含 AVClass 的结构体,指定该 log 所属的结构体,如 AVFormatContext、AVCodecContext 等等,可以设置为 NULL
av_log(NULL, AV_LOG_DEBUG, "Hello World ! \n");

ffmpeg 日志系统av_log()的更多相关文章

  1. C++ 高性能无锁日志系统

    服务器编程中,日志系统需要满足几个条件 .高效,日志系统不应占用太多资源 .简洁,为了一个简单的日志功能引入大量第三方代码未必值得 .线程安全,服务器中各个线程都能同时写出日志 .轮替,服务器不出故障 ...

  2. Atitit.日志系统slf4j的使用

    Atitit.日志系统slf4j的使用 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar ...

  3. Android源码——Logger日志系统

    Android的Logger日志系统是基于内核中的Logger日志驱动程序实现的. 日志保存在内核空间中 缓冲区保存日志   分类方法:日志的类型  +   日志的输出量   日志类型:   main ...

  4. 使用Slf4j集成Log4j2构建项目日志系统的完美解决方案

    一.背景 最近因为公司项目性能需要,我们考虑把以前基于的log4j的日志系统重构成基于Slf4j和log4j2的日志系统,因为,使用slf4j可以很好的保证我们的日志系统具有良好的兼容性,兼容当前常见 ...

  5. 日志系统实战(三)-分布式跟踪的Net实现

    介绍 在大型系统开发调试中,跨系统之间联调开始变得不好使了.莫名其妙一个错误爆出来了,日志虽然有记录,但到底是哪里出问题了呢? 是Ios端参数传的不对?还是A系统或B系统提供的接口导致?相信有不少人遇 ...

  6. 日志系统实战(一)—AOP静态注入

    背景 近期在写日志系统,需要在运行时在函数内注入日志记录,并附带函数信息,这时就想到用Aop注入的方式. AOP分动态注入和静态注入两种注入的方式. 动态注入方式 利用Remoting的Context ...

  7. Android性能优化之UncaughtExceptionHandler定制自己的错误日志系统

    前言: 每当我们app测试的时候,测试人员总是对我们说这里崩溃了,那里挂掉了!我们只能默默接受,然后尝试着重现bug,更可悲的是有时候bug很难复现,为了解决这种现状所以我们要尝试这建立一个自己的bu ...

  8. [Asp.net 5] Logging-其他日志系统的实现

    Microsoft.Framework.Logging.NLog 使用Nlog扩展日志系统:按照我们上节说的,对于扩展的日志系统都要实现俩个接口ILogger.ILoggerProvider.所以在当 ...

  9. 【转载】scribe、chukwa、kafka、flume日志系统对比

    原文地址:http://www.ttlsa.com/log-system/scribe-chukwa-kafka-flume-log-system-contrast/ 1. 背景介绍许多公司的平台每天 ...

随机推荐

  1. 使用git-svn迁移SVN至GitLab

    使用git-svn迁移SVN至GitLab 1.安装git和git-svn 后面的步骤中对git版本有一定要求,通过yum安装的git版本较低,这里进行编译安装 [root@DevTest ~]# y ...

  2. 利用SmtpClient发送邮件

    1  163邮箱 HOST:smtp.163.com public static string CreateTimeoutTestMessage(string server) { string Suc ...

  3. Swift教程之运算符

    import Foundation //4.复合赋值操作符 var a = 1 a += 2 //一元减运算符(一个数值前加了符号-,叫作一元减运算符) let three = 3 let minus ...

  4. XP系统如何把桌面图标变大

    右击桌面,属性,外观,高级,在项目里面找到图标,大小改为你喜欢的样式.   我测试的结果是:图标大小改为42,字体大小改为8,图标垂直间距改为100,水平间距改为54效果不错.

  5. 内网渗透技巧:判断机器真实外网IP的5种方法总结

    在内网渗透中有时需要在某台WEB服务器中留下后门,该机器可以通过内网IP建立IPC连接,但还需要获知外网IP或域名才能访问Wbshell,在无网关权限的情况下,我总结了有如下方法: 1.通过nsloo ...

  6. 关于org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor的队列

    今天查看源码发现spring的线程池是支持队列的: 并且队列支持的上限相当大: 当线程池的达到最大线程时,默认会把任务放在队列(内存)中,所以我们可以放心用这个东西来写日志了

  7. Android Touch事件传递机制引发的血案

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38942135 关于Android Touch事件传递机制我之前也写过两篇文章,自觉得对Tou ...

  8. oracle 查询 函数练习

    /*--以下代码是对emp表进行显示宽度设置col empno for 9999;col ename for a10;col job for a10;col mgr for 9999; col hir ...

  9. post请求方式的翻页爬取内容及思考

    1 #coding=utf-8 import urllib2 import urllib import json output = open('huizho.json', 'w') for page ...

  10. atitti.atiNav 手机导航组件的设计

    atitti.atiNav 手机导航组件的设计 1.1. 三大按键导航功能,back,menu ,home1 1.2. header页头组件,为移动页面顶部的导航条设计.1 1.3. 页头主题设计1 ...