ffmpeg日志系统

日志系统

PS:

在当前的计算机系统中, I/O操作相比其它环节是最耗费资源浪费时间的,所以大家要慎重, 尽量减少不必要的I/O操作。

使用一般步骤:

  1. 头文件: #include <libavutil/log.h>
  2. 设置log级别: av_log_set_level(AV_LOG_DEBUG);
  3. 输出log: av_log(nullptr, AV_LOG_INFO, “this is log output”);

设置日志级别

设置日志级别的意义:作者可以预设标识了级别的输出日志, 然后通过设置日志级别来控制那些日志信息需要输出, 方便进行调试。而不需要到处去修改,和设置DEBUG宏异曲同工之妙。

/**
 * Set the log level
 *
 * @see lavu_log_constants
 *
 * @param level Logging level
 */
void av_log_set_level(int level);

函数代码实现:

static int av_log_level = AV_LOG_INFO;

显然,设置日志输出等级就是操作静态全局变量av_log_level。该变量用于存储当前系统Log的级别。
设置了日志输出级别之后, 比此级别严重的日志都会输出
exp:

int main()
{
    av_log_set_level(AV_LOG_INFO);
    av_log(nullptr, AV_LOG_INFO, "AV_LOG_INFO = %d\n", AV_LOG_INFO);
    av_log(nullptr, AV_LOG_ERROR, "AV_LOG_ERROR = %d\n", AV_LOG_ERROR);
    av_log(nullptr, AV_LOG_TRACE, "AV_LOG_TRACE = %d\n", AV_LOG_TRACE);
    return 0;
}

out put

int main()
{
    av_log_set_level(AV_LOG_ERROR);
    av_log(nullptr, AV_LOG_INFO, "AV_LOG_INFO = %d\n", AV_LOG_INFO);
    av_log(nullptr, AV_LOG_ERROR, "AV_LOG_ERROR = %d\n", AV_LOG_ERROR);
    av_log(nullptr, AV_LOG_TRACE, "AV_LOG_TRACE = %d\n", AV_LOG_TRACE);
    return 0;
}

在这里插入图片描述

常用的日志级别

 // 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

// Extremely verbose debugging, useful for libav* development.
#define AV_LOG_TRACE    56

每个级别定义的数值代表了严重程度,数值越小代表越严重
默认av_log()输出的级别是AV_LOG_INFO。

获取当前日志级别

/**
 * Get the current log level
 *
 * @see lavu_log_constants
 *
 * @return Current log level
 */
int av_log_get_level(void);

日志输出函数

/**
 * 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 or NULL if general log.
 * @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, ...)

第一个参数指定该log所属的结构体,例如AVFormatContext、AVCodecContext等等。
第二个参数指定log的级别,第三个参数为要输出的内容。

PS: 结合之前的内容,所谓的输出log, 其实是设定了具有一定log级别的输出, 系统会根据作者设置的日志阈值, 来自动筛选那些日志是需要输出的, 那些是不需要输出的。

自定义log输出函数

av_log()调用了av_vlog(),av_log()调用了一个函数指针av_log_callback。av_log_callback是一个全局静态变量,定义如下所示:

static void (*av_log_callback)(void*, int, const char*, va_list) = av_log_default_callback;

从代码中可以看出,av_log_callback指针默认指向一个函数av_log_default_callback()。av_log_default_callback()即FFmpeg默认的Log函数。
需要注意的是,这个Log函数是可以自定义的。按照指定的参数定义一个自定义的函数后,可以通过FFmpeg的另一个API函数av_log_set_callback()设定为Log函数。
查看源码,可以看到 av_log_set_callback() 的声明如下:

/**
 * Set the logging callback
 *
 * @note The callback must be thread safe, even if the application does not use
 *       threads itself as some codecs are multithreaded.
 *
 * @see av_log_default_callback
 *
 * @param callback A logging function with a compatible signature.
 */
void av_log_set_callback(void (*callback)(void*, int, const char*, va_list));

从声明中可以看出,需要指定一个参数为(void*, int, const char*, va_list),返回值为void的函数作为Log函数。

查看av_log_set_callback() 源码,可以看到此方法只是做了一个函数指针赋值的工作,代码如下:

void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)) {
    av_log_callback = callback;
}

这样我们可以自定义一个my_logoutput()函数作为Log的输出函数:

void selfDefineLogOutPut(void* ptr, int level, const char* fmt,va_list vl){
    *******(omit....}

编辑好函数之后,使用av_log_set_callback()函数设置该函数为Log输出函数即可。

av_log_set_callback(selfDefineLogOutPut);

For Example:

void selfDefineLogOutPut(void* ptr, int level, const char* fmt,va_list vl){
    cout << fmt;
    return;
}

int main()
{
    av_log_set_level(AV_LOG_INFO);
    av_log_set_callback(selfDefineLogOutPut);
    av_log(nullptr, AV_LOG_ERROR, "My self out put\n");
    av_log_get_level();
    return 0;
}

输出结果:
在这里插入图片描述
ps: 如果有需要, 还得恢复默认的log输出行为, 不要拍拍屁股就走人了:

av_log_set_callback(av_log_default_callback);

把日志输出到日志文件:

大家务必注意,上文的所有骚操作, 一顿操作猛如虎,一看结果250,所有的log都输出在屏幕上,也即是标准输出或者标准出错。怎么把日志输出到log文件里呢??
这里就需要结合上一条的操作, 既然能够自定义log输出函数, 那就好办了:

void selfDefineLogOutPut(void* ptr, int level, const char* fmt, va_list vl){
    char buff[1024] = "";
    sprintf(buff, fmt, vl[0]);
    FILE *file = fopen("D:\\ZLJ\\stuff\\a.txt", "wb+");
    fwrite(buff, 1, strlen(buff), file);
    fclose(file);
    return;
}

int main()
{
    av_log_set_level(AV_LOG_INFO);
    av_log_set_callback(selfDefineLogOutPut);
    av_log(nullptr, AV_LOG_ERROR, "My self out put abc = %d \n", 123);
    av_log_get_level();
    return 0;
}

上面的方法完全可以实现把log输出到日志里。但是,因为va_list 实在是一个愚蠢到顶的数据结构,不知道那个白痴想出来的可变参数。用起来还是有些不方便。但是有总比没有要强的多吧,哈哈哈哈

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值