FFMPEG 日志输出控制

原文:https://blog.csdn.net/tea1896/article/details/48310579

1. FFMPEG 编码速度很慢,发现其中打印很多。因为打印是一个执行比较慢的动作,有些还是阻塞的。所以必须控制打印等级。

    用到的函数及头文件

    #include "libavutil/log.h"

    av_log_set_level(AV_LOG_QUIET);

1).  FFMPEG 打印日志的函数


FFMPEG 有一套自己的日志系统,它使用 av_log() 函数来打印日志,其声明位于:<libavutil/log.h>


它的函数原型如下:


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


参数含义:


avcl:指定一个包含 AVClass 的结构体,指定该 log 所属的结构体,如 AVFormatContext、AVCodecContext 等等,可以设置为 NULL

level:log 的级别,下面给出可选的值

fmt:跟 c 语言的 printf() 定义一样


2).  FFMPEG 日志级别


LOG 的级别是一个 int 类型,其可选的数值及其含义如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
  * Print no output.
  */
#define AV_LOG_QUIET    -8
 
/**
  * Something went really wrong and we will crash now.
  */
#define AV_LOG_PANIC     0
 
/**
  * Something went wrong and recovery is not possible.
  * For example, no header was found for a format which depends
  * on headers or an illegal combination of parameters is used.
  */
#define AV_LOG_FATAL     8
 
/**
  * Something went wrong and cannot losslessly be recovered.
  * However, not all future data is affected.
  */
#define AV_LOG_ERROR    16
 
/**
  * Something somehow does not look correct. This may or may not
  * lead to problems. An example would be the use of '-vstrict -2'.
  */
#define AV_LOG_WARNING  24
 
/**
  * Standard information.
  */
#define AV_LOG_INFO     32
 
/**
  * Detailed information.
  */
#define AV_LOG_VERBOSE  40
 
/**
  * Stuff which is only useful for libav* developers.
  */
#define AV_LOG_DEBUG    48


3).  FFMPEG 设置和获取当前日志级别


由一个全局的变量来控制哪个级别及以上的日志会打印输出,设置和获取这个全局变量的函数如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
  * Get the current log level
  *
  * @see lavu_log_constants
  *
  * @return Current log level
  */
int  av_log_get_level( void );
 
/**
  * Set the log level
  *
  * @see lavu_log_constants
  *
  * @param level Logging level
  */
void  av_log_set_level( int  level);


例如,当全局的日志级别设置为 `AV_LOG_ERROR`,那么凡是日志级别高于 `AV_LOG_ERROR` 的日志,都不会被打印出来。


4).  FFMPEG 日志打印函数的使用示例


假设要打印 DEBUG 和 ERROR 级别的日志,用法示例如下:


1
2
av_log(NULL, AV_LOG_DEBUG,  "Hello World ! \n" );
av_log(NULL, AV_LOG_ERROR,  "Error:%d ! \n" , errorCode);


5).  FFMPEG 日志打印函数的封装


当然,如果你觉得 av_log 用起来不是很顺手,你可以定义个宏封装下,例如:


1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _SYS_LOG_
#define _SYS_LOG_
 
#include <libavutil/log.h>
 
#define LOGD(format, ...) av_log(NULL, AV_LOG_DEBUG, format, ##__VA_ARGS__);
#define LOGV(format, ...) av_log(NULL, AV_LOG_VERBOSE, format, ##__VA_ARGS__);
#define LOGI(format, ...) av_log(NULL, AV_LOG_INFO, format, ##__VA_ARGS__);
#define LOGW(format, ...) av_log(NULL, AV_LOG_WARNING, format, ##__VA_ARGS__);
#define LOGE(format, ...) av_log(NULL, AV_LOG_ERROR, format, ##__VA_ARGS__);
 
#endif


6).  Android 中打印 FFMPEG 的日志


由于 FFMPEG 默认使用的是 printf 来打印日志,而 Android 系统有着一套自己的 LOG 系统,因此,需要让 FFMPEG 的日志重定向使用 Android 的日志系统,具体方法描述如下:


通过 FFMPEG 的 av_log_set_callback() 注册一个 LOG callback function,FFMPEG 就会把 LOG 打印功能重定向到 callback function 中,代码示例如下(你也可以到我的 Github 查看封装好的源代码:  https://github.com/Jhuster/clib):


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifdef __ANDROID_API__
#include <android/log.h>
 
#define ALOG(level, TAG, ...)    ((void)__android_log_vprint(level, TAG, __VA_ARGS__))
 
#define SYS_LOG_TAG "nmplayer"
 
static  void  syslog_print( void  *ptr,  int  level,  const  char  *fmt,  va_list  vl)
{
     switch (level) {
     case  AV_LOG_DEBUG:
         ALOG(ANDROID_LOG_VERBOSE, SYS_LOG_TAG, fmt, vl);
         break ;
     case  AV_LOG_VERBOSE:
         ALOG(ANDROID_LOG_DEBUG, SYS_LOG_TAG, fmt, vl);
         break ;
     case  AV_LOG_INFO:
         ALOG(ANDROID_LOG_INFO, SYS_LOG_TAG, fmt, vl);
         break ;
     case  AV_LOG_WARNING:
         ALOG(ANDROID_LOG_WARN, SYS_LOG_TAG, fmt, vl);
         break ;
     case  AV_LOG_ERROR:
         ALOG(ANDROID_LOG_ERROR, SYS_LOG_TAG, fmt, vl);
         break ;
     }
}
 
static  void  syslog_init()
{
     av_log_set_callback(syslog_print);
}
 
#endif // __ANDROID_API__


在代码初始化的地方调用一下 syslog_init() 后,就可以使用 av_log() 在 Android 平台输出调试日志了。


7).  FFPlay 设置日志级别


平时自己写的播放器播放某些流播放有问题的话,也可以使用 ffplay 来对比调试一下,看看使用 ffplay 是否可以播放,报错信息是什么,ffplay 打开 DEBUG 日志输出的方法示例如下:


1
$ ffplay -v debug $URL


-v 参数是用于配制 ffplay 的日志级别,其定义如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-loglevel [repeat+]loglevel | -v [repeat+]loglevel
 
Set the logging level used by the library. Adding  "repeat+"  indicates that repeated  log  output should not be compressed to the first line and the  "Last message repeated n times"  line will be omitted.  "repeat"  can also be used alone. If  "repeat"  is used alone, and with no prior loglevel set, the  default  loglevel will be used. If multiple loglevel parameters are given,  using  ’repeat’ will not change the loglevel. loglevel is a string or a number containing one of the following values:
 
‘quiet, -8’
Show nothing at all; be silent.
 
‘panic, 0’
Only show fatal errors which could lead the process to crash, such as an assertion failure. This is not currently used  for  anything.
 
‘fatal, 8’
Only show fatal errors. These are errors after which the process absolutely cannot  continue .
 
‘error, 16’
Show all errors, including ones which can be recovered from.
 
‘warning, 24’
Show all warnings and errors. Any message related to possibly incorrect or unexpected events will be shown.
 
‘info, 32’
Show informative messages during processing. This is in addition to warnings and errors. This is the  default  value.
 
‘verbose, 40’
Same as info, except more verbose.
 
‘debug, 48’
Show everything, including debugging information.
 
‘trace, 56’
By  default  the program logs to stderr. If coloring is supported by the terminal, colors are used to mark errors and warnings. Log coloring can be disabled setting the environment variable AV_LOG_FORCE_NOCOLOR or NO_COLOR, or can be forced setting the environment variable AV_LOG_FORCE_COLOR. The use of the environment variable NO_COLOR is  deprecated  and will be dropped in a future FFmpeg version.


8).  小结


关于如何使用 FFMPEG 如何打印日志就介绍到这儿了,文章中有不清楚的地方欢迎留言或者来信 lujun.hust@gmail.com 交流,关注我的新浪微博 @卢_俊 或者 微信公众号 @Jhuster 获取最新的文章和资讯。



2. 如果是用命令行的形式,则可以用以下类似语句

  ./test.sh > log 2>&1

  即利用linux 的重定向功能


3.如果需要自定义ffmpeg的日志输出,使用以下函数:

av_log_set_callback(av_log_selfcallback); 

ps:注意源码说明,这个回调函数需要是一个线程安全函数。

如果需要设置回默认的,按如下使用
av_log_set_callback(av_log_default_callback);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值