FFmpeg的封装专有的log日志系统,支持设置日志等级log level,也支持日志回调log callback,方便开发者调试与排查问题。

1、日志等级

log日志位于libavutil模块,log level的声明位于log.h:

// 静默模式,不打印日志
#define AV_LOG_QUIET    -8// 立即崩溃,退出程序
#define AV_LOG_PANIC     0// 严重出错,无法修复
#define AV_LOG_FATAL     8// 程序出错
#define AV_LOG_ERROR    16// 警告
#define AV_LOG_WARNING  24// 信息
#define AV_LOG_INFO     32// 详细信息
#define AV_LOG_VERBOSE  40// 调试日志
#define AV_LOG_DEBUG    48// 跟踪日志
#define AV_LOG_TRACE    56

可以看到,每个日志等级间隔为8,等级越高数值越小。 设置日志等级的方法set_log_level()位于log.c,其中av_log_level是个静态全局变量,具体如下:

static int av_log_level = AV_LOG_INFO;void av_log_set_level(int level)
{av_log_level = level;
}

2、日志打印

常用的打印日志方法av_log(),声明位于log.h:

/** * 发送特定消息到小于等于当前等级的日志,默认全部发送到stderr** @param avcl  指向任意结构体的指针,结构体第一个变量为AVClass或NULL* @param level 日志等级* @param fmt   字符串格式*/
void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4);

av_log()方法的实现如下,打印前调用va_start开始,然后打印日志,最后调用va_end结束:

void av_log(void* avcl, int level, const char *fmt, ...)
{va_list vl;va_start(vl, fmt);av_vlog(avcl, level, fmt, vl);va_end(vl);
}

av_log()内部调用av_vlog()方法,把参数avc1强转为AVClass指针,av_log_callback赋值到函数指针log_callback,计算日志等级,最后如果log_callback不为空则回调日志:

void av_vlog(void* avcl, int level, const char *fmt, va_list vl)
{AVClass* avc = avcl ? *(AVClass **) avcl : NULL;void (*log_callback)(void*, int, const char*, va_list) = av_log_callback;if (avc && avc->version >= (50 << 16 | 15 << 8 | 2) &&avc->log_level_offset_offset && level >= AV_LOG_FATAL)level += *(int *) (((uint8_t *) avcl) + avc->log_level_offset_offset);if (log_callback)log_callback(avcl, level, fmt, vl);
}

3、日志回调

设置日志回调的方法为set_log_level(),代码如下:

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

av_log_callback有个默认回调函数:

void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
{static int print_prefix = 1;static int count;static char prev[LINE_SZ];AVBPrint part[4];char line[LINE_SZ];static int is_atty;int type[2];unsigned tint = 0;if (level >= 0) {tint = level & 0xff00;level &= 0xff;}if (level > av_log_level)return;ff_mutex_lock(&mutex);format_line(ptr, level, fmt, vl, part, &print_prefix, type);snprintf(line, sizeof(line), "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);#if HAVE_ISATTYif (!is_atty)is_atty = isatty(2) ? 1 : -1;
#endifif (print_prefix && (flags & AV_LOG_SKIP_REPEATED) && !strcmp(line, prev) &&*line && line[strlen(line) - 1] != '\r'){count++;if (is_atty == 1)fprintf(stderr, "    Last message repeated %d times\r", count);goto end;}if (count > 0) {fprintf(stderr, "    Last message repeated %d times\n", count);count = 0;}strcpy(prev, line);sanitize(part[0].str);colored_fputs(type[0], 0, part[0].str);sanitize(part[1].str);colored_fputs(type[1], 0, part[1].str);sanitize(part[2].str);colored_fputs(av_clip(level >> 3, 0, NB_LEVELS - 1), tint >> 8, part[2].str);sanitize(part[3].str);colored_fputs(av_clip(level >> 3, 0, NB_LEVELS - 1), tint >> 8, part[3].str);#if CONFIG_VALGRIND_BACKTRACEif (level <= BACKTRACE_LOGLEVEL)VALGRIND_PRINTF_BACKTRACE("%s", "");
#endif
end:av_bprint_finalize(part+3, NULL);ff_mutex_unlock(&mutex);
}static void (*av_log_callback)(void*, int, const char*, va_list) =av_log_default_callback;

看看Android平台设置的level与callback:

void ffmpeg_init() {av_log_set_level(AV_LOG_INFO);av_log_set_callback(log_callback);
}

log_callback()收到回调消息后,可以根据level等级打印对应msg:

void log_callback(void *ptr, int level, const char *format, va_list args) {switch (level) {case AV_LOG_DEBUG:ALOGD(FFMPEG_TAG, format, args);break;case AV_LOG_INFO:ALOGI(FFMPEG_TAG, format, args);break;case AV_LOG_ERROR:ALOGE(FFMPEG_TAG, format, args);break;default:break;}
}

FFmpeg源码分析:log日志系统相关推荐

  1. 云客Drupal源码分析之日志系统与监控

    系统日志让你了解系统内部发生了什么,当出现故障时首先想到的就是日志,drupal日志系统可以按信息类别分别记录日志,并且按照RFC 5424和PSR-3将各类信息按紧迫程度划分为8个级别,这样方便筛选 ...

  2. FFMPEG源码分析(一)

    FFMPEG源码分析(一) ffmpeg之前公司项目中就使用过,但是多停留于应用层面,实现某个功能时,需要哪些结构体以及调用哪些函数.最近想系统的学习一下ffmpeg,于是开始看雷霄骅https:// ...

  3. FFMPEG源码分析(二)

    ffmpeg源码分析之数据流 本文主要介绍ffmpeg的数据流,在ffmpeg中主要分有三个主要用途用于媒体流的解码播放,媒体流的转换(解码之后再编码)和媒体流录制. 媒体流的解码播放 在ffmpeg ...

  4. FFMPEG 源码分析

    FFMPEG基本概念: ffmpeg是一个开源的编解码框架,它提供了一个音视频录制,解码和编码库.FFMPEG是在linux下开发的,但也有windows下的编译版本. ffmpeg项目由以下几部分组 ...

  5. FFmpeg源码分析-直播延迟-内存泄漏

    FFmpeg源码分析-直播延迟-内存泄漏|FFmpeg源码分析方法|ffmpeg播放为什么容易产生延迟|解复用.解码内存泄漏分析 专注后台服务器开发,包括C/C++,Linux,Nginx,ZeroM ...

  6. ffmpeg源码分析-parse_optgroup

    本系列 以 ffmpeg4.2 源码为准,下载地址:链接:百度网盘 提取码:g3k8 ffmpeg 源码分析系列以一条简单的命令开始,ffmpeg -i a.mp4 b.flv,分析其内部逻辑. a. ...

  7. ffmpeg源码分析-ffmpeg_parse_options

    本系列 以 ffmpeg4.2 源码为准,下载地址:链接:百度网盘 提取码:g3k8 ffmpeg 源码分析系列以一条简单的命令开始,ffmpeg -i a.mp4 b.flv,分析其内部逻辑. a. ...

  8. ffmpeg源码分析-transcode_step

    本系列 以 ffmpeg4.2 源码为准,下载地址:链接:百度网盘 提取码:g3k8 ffmpeg 源码分析系列以一条简单的命令开始,ffmpeg -i a.mp4 b.flv,分析其内部逻辑. a. ...

  9. [Abp vNext 源码分析] - 2. 模块系统的变化

    一.简要说明 本篇文章主要分析 Abp vNext 当中的模块系统,从类型构造层面上来看,Abp vNext 当中不再只是单纯的通过 AbpModuleManager 来管理其他的模块,它现在则是 I ...

最新文章

  1. office移动端_微软手机端三合一Office APP开启公测,大家可以下载试试
  2. nanopi磁盘烧写
  3. 《JavaScript高级程序设计》笔记:JavaScript简介(一)
  4. 银行加息前存的定期会随着加息吗?
  5. [html] HTML5拖拽事件的顺序是什么?
  6. 在线安装php,CentOS在线安装PHP|dayblog-天天博客|PHP交流,PHP技术,PHP博客,博客交流,dayblog,blog,天天博客...
  7. LOJ3119 CTS2019 随机立方体 概率、容斥、二项式反演
  8. 循环、选择要注意的复合语句
  9. C++中继承的父类与子类的关系
  10. tcpserver检测断开qt_QTcpServer或QTcpClient(在服务器端)知道,已连接的客户端现已断开连接...
  11. 02年计算机学院成立,教育部关于成立2002年-2006年教育部高等学校外语专业等科类教学指导委员会的通知...
  12. pycharm 输入法光标跟随
  13. 给马云、马化腾订制旅行,这家公司想做旅游行业的“得到”
  14. 总账科目往来批量导入程序
  15. Excel库存表通过吉度PDA盘点机形成盘点差异表
  16. Vector人工智能机器人SDK使用笔记
  17. [POI2007]ZAP-Queries 莫比乌斯反演(模板)
  18. 北大核心2020_清华和北大,可以同时上了
  19. Java中List集合去除重复数据的六种方法
  20. 为什么一边裁员,一边招人。。

热门文章

  1. 代理服务器设置全局环境
  2. 精尽 JDK 源码解析 —— 集合(二)链表 LinkedList
  3. 二进制除法移位相减_在汇编除法中:移位相减是怎么样的原理啊,程序看了几天了还是看不懂,哪位兄弟告诉我,本人感激涕零...
  4. Mac: 搜狗云输入法的问题
  5. 计算机网络-第一章 计算机网络体系结构(详细知识点总结)
  6. 零基础无实物一步一步学PLCS7-1200仿真(六)-两个电动机顺启逆停
  7. Android Wifi开发——WiFi连接(八)
  8. 数据库应用系统的需求分析
  9. 全渠道和元宇宙【零售的未来】
  10. 基于 iris 数据集采用感知器 Perceptron 实现线性二分类