Visual Studio 开发(二):VS 2017配置FFmpeg开发环境一文中,我们配置好了FFmpeg的开发环境,下面我们开始边实战,边学习FFmpeg。

首先,我们要学习的就是FFmpeg的日志输出系统 。

一、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.
* @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(, );

其中第一个参数指定该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

从定义中可以看出来,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()输出的级别是AV_LOG_INFO。

三、设置日志输出等级

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

函数声明如下:

/**
* 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的级别。

四、日志输出实战

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

#include "pch.h"
#include <iostream> extern "C"{
#include "libavutil/log.h"
} int main(int argc, char* argv[]) {
av_log_set_level(AV_LOG_ERROR);
av_log(NULL, AV_LOG_INFO, "Hello World\n");
return ;
}

五、自定义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_logoutput(void* ptr, int level, const char* fmt,va_list vl){
****(省略....)
}

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

av_log_set_callback(my_logoutput);

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

#include "pch.h"
#include <iostream> extern "C"{
#include "libavutil/log.h"
} void my_logoutput(void* ptr, int level, const char* fmt, va_list vl) {
printf("Hello Log Output! Content = %s", fmt);
} int main(int argc, char* argv[]) {
av_log_set_callback(my_logoutput); // 设置自定义的日志输出方法
av_log(NULL, AV_LOG_INFO, "Hello World\n");
return ;
}

输出如下:

附:本文涉及C语言知识点 --> 函数指针。

FFmpeg开发实战(一):FFmpeg 打印日志的更多相关文章

  1. FFmpeg开发实战(三):FFmpeg 打印音视频Meta信息

    在之前使用FFmpeg命令行的时候,我们经常看到FFmpeg命令行在输出音视频文件的会打印一下文件的Meta信息,类似如图: 那么我们如何通过代码的方式输出这些Meta信息呢? FFmpeg提供了一个 ...

  2. FFmpeg开发实战(四):FFmpeg 抽取音视频的音频数据

    如何使用FFmpeg抽取音视频的音频数据,代码如下: void adts_header(char *szAdtsHeader, int dataLen); // 使用FFmpeg从视频中抽取音频 vo ...

  3. FFmpeg开发实战(五):FFmpeg 抽取音视频的视频数据

    如何使用FFmpeg抽取音视频的视频数据,代码如下: // FFmpegTest.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并结束. // #include ...

  4. FFmpeg开发实战(二):FFmpeg 文件操作

    FFmpeg 提供了丰富的API供我们使用,下面我们来讲述一下文件操作相关的API: FFmpeg 删除文件:avpriv_io_delete() FFmpeg 重命名文件:avpriv_io_mov ...

  5. FFmpeg开发实战(六):使用 FFmpeg 将YUV数据编码为视频文件

    本文中实现的一个小功能是把一个YUV原始视频数据(时间序列图像)经过h264编码为视频码流,然后在使用mp4封装格式封装. 编码&封装的流程图如下: 使用ffmpeg编码流程: 1.首先使用a ...

  6. Android开发之封装log打印日志的工具类,实用logutils详细代码

    public final class LogUtil { /** all Log print on-off */ private final static boolean all = true; /* ...

  7. FFmpeg调用c语言SDK实现日志的打印

    日志文件的三大步 // 导入头文件 #include <libavutil/log.h> // 设置日志级别 av_log_set_level(AV_LOG_DEBUG); //DEBUG ...

  8. windows环境下搭建ffmpeg开发环境

           ffmpeg是一个开源.跨平台的程序库,能够使用在windows.linux等平台下,本文将简单解说windows环境下ffmpeg开发环境搭建过程,本人使用的操作系统为windows ...

  9. FFmpeg开发笔记(四):ffmpeg解码的基本流程详解

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

随机推荐

  1. 切面编程AOP之Castle.Core

    1.Nuget中搜索Castle.Core并install 2.创建一个普通的类(注意类中只有标记virtual才能实现拦截 ) public class TestInterceptor { publ ...

  2. Python2和3版本对str和bytes类型的处理

    python2中字符串分为2种类型: 字节类型:str,字节类型,通过decode()转化为unicode类型 unicode类型:unicode ,通过encode转化为str字节类型 字节类型 和 ...

  3. springmvc webservlet 异步请求总结

    1:每次请求会启动一个新线程 上边在debug状态下, 每次请求一次,生成一个新的 thread  在此已经是245了 出现一个现象在debug模式下, 每次请求生成的线程,自动在红框那个位置停了下来 ...

  4. 为nginx创建windows服务自启动

    1.下载最新版的 Windows Service Wrapper 程序,比如我下载的名称是 "winsw-1.9-bin.exe",然后,把它命名成你想要的名字(比如: " ...

  5. 关于微信小程序切换获取不到元素的问题

    1.由于公司要实现微信小程序的自动化,所以开始学习python + appium 实现微信小程序自动化.在学习过程中遇到在切换webview后获取不到页面元素的问题,导致无法继续.今天在网上看到一篇关 ...

  6. 【Linux】vim的使用

    使用vi和vim的原因:linux很多软件默认调用vi进行编辑,因此有必要熟悉它的使用规则 vi: 打开文件: vi 文件名 [一般模式]打开文件时进入一般模式,这个模式下的操作: 上下左右移动光标 ...

  7. ContentType与SpiringMvc

    转载https://blog.csdn.net/mingtianhaiyouwo/article/details/51459764

  8. OO第9-11作业总结

    一. 规格化设计   规格化抽象,即将执行的细节抽象为用户所需求的行为(模块做什么). 主要作用在于提高工程设计中的可维护性,可读性,明确功能,使整个编程任务变得清晰有序以减少程序BUG. 说其发展历 ...

  9. 实验十四 第九组 张燕~杨蓉庆~杨玲 Swing图形界面组件

    实验十四  Swing图形界面组件 8-11-29 理论知识 Swing和MVC设计模式 (1)设计模式(Design pattern)是设计者一种流行的 思考设计问题的方法,是一套被反复使用,多数人 ...

  10. windows10系统安装Oralce11g时遇到INS-13001环境不满足最低要求

    升级win10系统之后,需要重新安装Oracle,因为在安装Oralce11g时,使用64位的会出现各种不兼容问题,我每次安装都是使用32位的数据库. 在安装时点击setup.exe之后,出现了:[I ...