音视频系列三:ffmpeg之日志打印

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 在上一篇 Visual Studio2019集成ffmpeg之hello world中,我们已经配置好visual studio的开发环境,接下来继续根据上一篇的环境来学习ffmpeg的日志打印;

在上一篇 Visual Studio2019集成ffmpeg之hello world中,我们已经配置好visual studio的开发环境,接下来继续根据上一篇的环境来学习ffmpeg的日志打印;


日志打印对于定位问题或者寻找bug都起到决定性的作用。


一、FFmpeg 打印日志输出介绍


FFmpeg 日志输出的核心函数方法为: av_log() 。为什么说av_log()是FFmpeg中输出日志的核心函数函数?


因为我们随便打开一个FFmpeg的源代码文件(源代码文件需要去官网下载带源代码的版本),就会发现其中遍布着av_log()函数。一般情况下FFmpeg类库的源代码不允许使用printf()这种函数,所以打印的所有输出一律使用的av_log()。


二、av_log() 函数说明


av_log()的声明位于libavutil\log.h,具体的声明代码如下:


/**
 * 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, ...) av_printf_format(3, 4);


其中第一个参数指定该log所属的结构体,例如AVFormatContext、AVCodecContext等等。第二个参数指定log的级别,第三个参数为要输出的内容,源代码中定义了如下几个级别:


/**
 * 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
#define AV_LOG_MAX_OFFSET (AV_LOG_TRACE - AV_LOG_QUIET)


从定义中可以看出来,av_log()的日志级别分别是:


AV_LOG_PANIC,AV_LOG_FATAL,AV_LOG_ERROR,AV_LOG_WARNING,AV_LOG_INFO,AV_LOG_VERBOSE,AV_LOG_DEBUG,AV_LOG_TRACE。


每个级别定义的数值代表了严重程度,数值越小代表越严重。


默认av_log()输出的级别是AV_LOG_INFO。


三、设置/获取日志输出等级


在上面,我们讲到av_log()函数是可以设置日志的内容的等级的。而对于输出的日志内容,我们也是可以设置等级的。FFmpeg提供了av_log_set_level()用于设置当前Log的级别,av_log_get_level用于获取当前Log的级别。


av_log_set_level函数声明如下:


/**
 * Set the log level
 *
 * @see lavu_log_constants
 *
 * @param level Logging level
 */
void av_log_set_level(int level);
av_log_set_level函数声明如下:
/**
 * Get the current log level
 *
 * @see lavu_log_constants
 *
 * @return Current log level
 */
int av_log_get_level(void);


四、日志输出实战


通过下面的代码,我们就可以理解上面讲的日志输出及设置日志输出等级的逻辑了。


#include <iostream>
extern "C"{
#include "libavutil/log.h"
}
int main(int argc, char* argv[]) {
    av_log_set_level(AV_LOG_DEBUG); //设置日志级别
    av_log(NULL, AV_LOG_DEBUG, "hello world log"); //打印日志
    printf("av_log_get_level: %d\n",av_log_get_level());
    system("pause"); //窗口等待
    return 0;
}


五、自定义FFmpeg日志输出


查看ffmpeg日志的实现源码可以发现,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 my_log_printf(void* ptr, int level, const char* fmt,va_list vl){
    省略...
}


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


av_log_set_callback(my_log_printf);


下面是自定义日志输出的实例源码:


#include<iostream>
using namespace std;
extern "C" {//包含C头文件
#include "libavutil/log.h" 
};
void my_log_printf(void* ptr, int level, const char* fmt, va_list vl) {
    printf("my_log_printf enter! Content : %s\nlog level : %d\n", fmt, level);
}
int main(int argc, char* argv[]) {
    av_log_set_level(AV_LOG_DEBUG); //设置日志级别
    av_log_set_callback(my_log_printf);  // 设置自定义的日志输出方法
    av_log(NULL, AV_LOG_DEBUG, "hello world log"); //打印日志
    system("pause"); //窗口等待
    return 0;
}


1.png


如果你觉得文章还不错,可以给个"三连"


我是加班猿,我们下期见

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
FFmpeg【SDK01】日志和字典的使用
FFmpeg中日志功能的使用方法,包括日志级别的设置和AVDictionary的基本操作,同时展示了字符串解析函数如av_parse_video_size、av_parse_video_rate和av_parse_time的应用。
32 2
|
3月前
|
Web App开发 5G Linux
FFmpeg开发笔记(四十四)毕业设计可做的几个拉满颜值的音视频APP
一年一度的毕业季来临,计算机专业的毕业设计尤为重要,不仅关乎学业评价还积累实战经验。选择紧跟5G技术趋势的音视频APP作为课题极具吸引力。这里推荐三类应用:一是融合WebRTC技术实现视频通话的即时通信APP;二是具备在线直播功能的短视频分享平台,涉及RTMP/SRT等直播技术;三是具有自定义动画特效及卡拉OK歌词字幕功能的视频剪辑工具。这些项目不仅技术含量高,也符合市场需求,是毕业设计的理想选择。
81 6
FFmpeg开发笔记(四十四)毕业设计可做的几个拉满颜值的音视频APP
|
2月前
|
Android开发 计算机视觉 C++
FFmpeg开发笔记(五十一)适合学习研究的几个音视频开源框架
音视频编程对许多程序员来说是一片充满挑战的领域,但借助如OpenCV、LearnOpenGL、FFmpeg、OBS Studio及VLC media player等强大的开源工具,可以降低入门门槛。这些框架不仅覆盖了计算机视觉、图形渲染,还包括多媒体处理与直播技术,通过多种编程语言如Python、C++的应用,使得音视频开发更为便捷。例如,OpenCV支持跨平台的视觉应用开发,FFmpeg则擅长多媒体文件的处理与转换,而VLC media player则是验证音视频文件质量的有效工具。
95 0
FFmpeg开发笔记(五十一)适合学习研究的几个音视频开源框架
|
2月前
用ffmpeg提取合并音视频
用ffmpeg提取合并音视频
|
4月前
|
达摩院 语音技术 异构计算
语音识别-免费开源的语音转文本软件Whisper的本地搭建详细教程,python版本是3.805,ffmpeg是专门处理音视频的,ffmpeg的下载链接,现在要求安装python和ffmpeg
语音识别-免费开源的语音转文本软件Whisper的本地搭建详细教程,python版本是3.805,ffmpeg是专门处理音视频的,ffmpeg的下载链接,现在要求安装python和ffmpeg
|
5月前
|
存储 编解码 Linux
rodert教你学FFmpeg实战这一篇就够了 - 音视频处理入门篇
rodert教你学FFmpeg实战这一篇就够了 - 音视频处理入门篇
64 1
|
4月前
|
C#
C#进程调用FFmpeg操作音视频
因为公司需要对音视频做一些操作,比如说对系统用户的发音和背景视频进行合成,以及对多个音视频之间进行合成,还有就是在指定的源背景音频中按照对应的规则在视频的多少秒钟内插入一段客户发音等一些复杂的音视频操作。本篇文章主要讲解的是使用C#进程(Process)调用FFmpeg.exe进行视频合并、音频合并、音频与视频合并成视频这几个简单的音视频操作。
|
6月前
|
存储 缓存 调度
FFmpeg开发笔记(十九)FFmpeg开启两个线程分别解码音视频
《FFmpeg开发实战》第10章示例playsync.c在处理音频流和视频流交错的文件时能实现同步播放,但对于分开存储的格式,会出现先播放全部声音再快速播放视频的问题。为解决此问题,需改造程序,增加音频处理线程和队列,以及相关锁,先将音视频帧读入缓存,再按时间戳播放。改造包括声明新变量、初始化线程和锁、修改数据包处理方式等。代码修改后在playsync2.c中,编译运行成功,控制台显示日志,SDL窗口播放视频并同步音频,证明改造有效。
111 0
FFmpeg开发笔记(十九)FFmpeg开启两个线程分别解码音视频
|
6月前
|
编解码 安全 计算机视觉
FFMPEG常用命令 音视频合并
FFMPEG常用命令 音视频合并
143 2
|
6月前
|
Web App开发 编解码 vr&ar
使用FFmpeg从音视频处理到流媒体技术的探索和实战应用
使用FFmpeg从音视频处理到流媒体技术的探索和实战应用
288 2
下一篇
无影云桌面