FFmpeg学习笔记(2):FFmpeg 打印日志

FFmpeg 日志输出系统介绍

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

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);

FFmpeg 日志输出的核心函数方法为: 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(3, 4);

 

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

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

/**
 * 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_INFO。

日志输出实例:

#include "stdafx.h"
#include 

extern "C"{
#include "libavutil/log.h"
}

int main(int argc, char* argv[]) {
    av_log_set_level(AV_LOG_DEBUG);
    av_log(NULL, AV_LOG_INFO, "Hello World\n");
    return 0;
}

 

自定义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 "stdafx.h"
#include 

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 0;
}

输出这些Meta信息

FFmpeg提供了一个API专门用来打印多媒体文件的格式 —— av_dump_format()

// 使用FFmpeg打印多媒体文件的Meta信息
void ffmpegVideoMeta() {
    av_log_set_level(AV_LOG_INFO);
    AVFormatContext *fmt_ctx = NULL;
    av_register_all();

    int ret;
    // 参数为 AVFormatContext上下文、文件名、指定的输入格式(一般为NULL,由ffmpeg自行解析)、附加参数(一般为NULL)
    ret = avformat_open_input(&fmt_ctx, "111.mp4", NULL, NULL);
    if (ret < 0) {
        printf("Cant open File: %s\n", av_err2str(ret));
    }
    // 参数为AVFormatContext上下文、流索引值(一般不用关心,直接写0)、文件名、是否是输入出文件(1:是  0:不是)    
    av_dump_format(fmt_ctx, 0, "111.mp4", 0);
    // 关闭打开的多媒体文件
    avformat_close_input(&fmt_ctx);
}

 

你可能感兴趣的:(ffmpeg,ffmpeg)