Libavutil详解:理论与实战


前言

在这里插入图片描述
libavutil 是一个实用库,用于辅助多媒体编程,本文记录 libavutil 库学习及 demo 例程展示。


一、Libavutil 简介

libavutil 是一个实用库,用于辅助多媒体编程。此库包含安全的可移植字符串函数、随机数生成器、数据结构、附加数学函数、加密和多媒体相关功能(如像素和样本格式的枚举)。

libavcodec 和 libavformat 并不依赖此库

从 FFmpeg 官网的文档 -libavutil 来看, avutil 主要有以下几种功能:

  • 数学函数
  • 字符串操作
  • 内存管理相关
  • 数据结构相关
  • 错误码及错误处理
  • 日志输出
  • 其他辅助信息,比如密钥、哈希值、宏、库版本、常量等

FFmpeg 中 libavutil 的示例,目前包含:

  • AVLog
  • AVOption (AVClass)
  • AVDictionary
  • ParseUtil

二、AVLog 测试

AVLog 是 FFmpeg(音视频处理库)中的一个日志系统,用于记录和输出日志信息。它提供了一种可配置的方式,使开发者能够根据自己的需求控制日志输出的详细程度和目标。

AVLog 的设计目标是提供一个灵活和可扩展的日志系统,以便在音视频处理过程中记录各种事件、错误和调试信息。它可以用于调试和分析应用程序或库的运行时行为,特别是在处理音视频数据时。

AVLog 提供了多个日志级别,包括:

  • QUIET(静默):最低日志级别,不输出任何日志信息。
  • PANIC(紧急):当发生严重错误时触发,可能导致程序崩溃或不可恢复的错误。
  • FATAL(致命):当发生严重错误时触发,但程序可能还能继续执行。
  • ERROR(错误):记录错误信息,表示发生了一些操作失败或异常情况,但程序仍然可以继续执行。
  • WARNING(警告):记录警告信息,表示发生了一些潜在问题或不符合预期的情况。
  • INFO(信息):记录一般的信息,用于追踪应用程序的运行状态。
  • VERBOSE(详细):记录更详细的信息,用于调试和排查问题。
  • DEBUG(调试):记录详细的调试信息,包括函数调用、变量值等。

1、示例源码

#include <stdio.h>

extern "C" {
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/opt.h"
    #include "libavutil/parseutils.h"
    #include "libavutil/avutil.h"
};

void test_log(){
    / av_register_all();
    AVFormatContext *pAVFmtCtx = NULL;
    pAVFmtCtx = avformat_alloc_context();

	printf("====================================\n");
    av_log(pAVFmtCtx,AV_LOG_PANIC, "Panic: Something went really wrong and we will crash now.\n");
    av_log(pAVFmtCtx,AV_LOG_FATAL, "Fatal: Something went wrong and recovery is not possible.\n");
    av_log(pAVFmtCtx,AV_LOG_ERROR, "Error: Something went wrong and cannot losslessly be recovered.\n");
    av_log(pAVFmtCtx,AV_LOG_WARNING, "Warning: This may or may not lead to problems.\n");
    av_log(pAVFmtCtx,AV_LOG_INFO, "Info: Standard information.\n");
    av_log(pAVFmtCtx,AV_LOG_VERBOSE, "Verbose: Detailed information.\n");
    av_log(pAVFmtCtx,AV_LOG_DEBUG, "Debug: Stuff which is only useful for libav* developers.\n");
	printf("====================================\n");

    avformat_free_context(pAVFmtCtx);
}

int main(int argc, char* argv[])
{
    av_log_set_level(AV_LOG_DEBUG);
    test_log();

	return 0;
}
  • avformat_alloc_context():分配一个 AVFormatContext;
  • avformat_free_context():可用于释放上下文以及其中由框架分配的所有内容;
  • av_log():如果 level 小于或等于当前 av_log_level,则将指定的消息发送到日志。默认情况下,所有日志消息都发送到 stderr。可以通过设置不同的日志回调函数来更改此行为。

2、运行结果

====================================
====================================
[NULL @ 01e0fc40] Panic: Something went really wrong and we will crash now.
[NULL @ 01e0fc40] Fatal: Something went wrong and recovery is not possible.
[NULL @ 01e0fc40] Error: Something went wrong and cannot losslessly be recovered.
[NULL @ 01e0fc40] Warning: This may or may not lead to problems.
[NULL @ 01e0fc40] Info: Standard information.
[NULL @ 01e0fc40] Verbose: Detailed information.
[NULL @ 01e0fc40] Debug: Stuff which is only useful for libav* developers.

三、AVDictionary 测试

AVDictionary 是 FFmpeg(音视频处理库)中的一个字典结构,用于存储键值对的元数据信息。它提供了一种通用的方式来管理和操作多种类型的元数据,例如音视频流的元数据、编解码器的参数、封装格式的选项等。

AVDictionary 的设计目标是提供一种灵活和可扩展的数据结构,用于表示和传递各种元数据信息。它可以用于读取和写入多种音视频文件格式,并且支持动态添加、修改和查询字典中的元素。

AVDictionary 提供了一系列的函数来对字典进行操作,包括:

  • av_dict_set():向字典中添加或修改键值对。
  • av_dict_get():根据键查询字典中的值。
  • av_dict_count():获取字典中键值对的数量。
  • av_dict_copy():复制一个字典。
  • av_dict_free():释放字典及其内部分配的内存。

除了基本的操作函数外,AVDictionary 还支持迭代器遍历字典中的键值对,以及支持将字典转换为字符串格式进行打印或保存。

1、示例源码

#include <stdio.h>

extern "C" {
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/opt.h"
    #include "libavutil/parseutils.h"
    #include "libavutil/avutil.h"
};

void test_avdictionary(){

    AVDictionary *d = NULL;
    AVDictionaryEntry *t = NULL;

    av_dict_set(&d, "name", "zhangsan", 0);
    av_dict_set(&d, "age", "22", 0);
    av_dict_set(&d, "gender", "man", 0);
    av_dict_set(&d, "email", "www@www.com", 0);
    //av_strdup()
    char *k = av_strdup("location");
    char *v = av_strdup("Beijing-China");
    av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);

    printf("====================================\n");
    int dict_cnt = av_dict_count(d);
    printf("dict_count:%d\n",dict_cnt);

    printf("dict_element:\n");
    while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
        printf("key:%10s  |  value:%s\n",t->key,t->value);
    }

    t = av_dict_get(d, "email", t, AV_DICT_IGNORE_SUFFIX);
    printf("email is %s\n",t->value);
    printf("====================================\n");
    av_dict_free(&d);
}

int main(int argc, char* argv[])
{
    test_avdictionary();

	return 0;
}

2、运行结果

====================================
dict_count:5
dict_element:
key:      name  |  value:zhangsan
key:       age  |  value:22
key:    gender  |  value:man
key:     email  |  value:www@www.com
key:  location  |  value:Beijing-China
email is www@www.com
====================================

四、ParseUtil 测试

ParseUtil 提供了一些实用的函数和方法,用于解析和转换编解码器参数字符串,以及处理编解码器参数的操作。它主要用于解析编解码器的选项和参数,并将它们转换为适当的数据结构供 FFmpeg 使用。

一些常见的功能和用途包括:

  • 解析编解码器参数:ParseUtil 可以解析编解码器参数字符串,将其拆分为键值对或特定格式的数据。
  • 转换参数数据类型:它可以将参数字符串中的数值或其他特定格式的数据转换为适当的数据类型,如整数、浮点数等。
  • 构建编解码器参数结构:ParseUtil 可以根据解析的结果构建编解码器参数的数据结构,以便在 FFmpeg 中使用。
  • 错误处理:它提供了一些错误处理机制,用于检测和处理无效的参数字符串或错误的参数格式。

1、示例源码

#include <stdio.h>

extern "C" {
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/opt.h"
    #include "libavutil/parseutils.h"
    #include "libavutil/avutil.h"
};

void test_parseutil(){
    char input_str[100] = {0};
    printf("========= Parse Video Size =========\n");
    int output_w = 0;
    int output_h = 0;
    strcpy(input_str, "1920x1080");
    av_parse_video_size(&output_w,&output_h,input_str);
    printf("w:%4d | h:%4d\n",output_w,output_h);

    //strcpy(input_str,"vga");//640x480(4:3)
    //strcpy(input_str,"hd1080");//high definition
    strcpy(input_str,"pal");//ntsc(N制720x480), pal(啪制720x576)
    av_parse_video_size(&output_w, &output_h, input_str);
    printf("w:%4d | h:%4d\n",output_w,output_h);


    printf("========= Parse Frame Rate =========\n");
    AVRational output_rational = {0,0};
    strcpy(input_str,"15/1");
    av_parse_video_rate(&output_rational,input_str);
    printf("framerate:%d/%d\n",output_rational.num,output_rational.den);

    strcpy(input_str,"pal");//fps:25/1
    av_parse_video_rate(&output_rational,input_str);
    printf("framerate:%d/%d\n",output_rational.num,output_rational.den);


    printf("=========== Parse Time =============\n");
    int64_t output_timeval;//单位:微妙, 1S=1000MilliSeconds, 1MilliS=1000MacroSeconds
    strcpy(input_str,"00:01:01");
    av_parse_time(&output_timeval,input_str,1);
    printf("microseconds:%lld\n",output_timeval);
    printf("====================================\n");
}

int main(int argc, char* argv[])
{
    test_parseutil();

	return 0;
}
  • av_parse_video_size():用于解析视频大小字符串并将其转换为对应的宽度和高度;
  • av_parse_video_rate():用于解析视频帧率字符串并将其转换为对应的帧率值;
  • av_parse_time():用于解析时间字符串并将其转换为对应的时间值(以微秒为单位)

2、运行结果

========= Parse Video Size =========
w:1920 | h:1080
w: 720 | h: 576
========= Parse Frame Rate =========
framerate:15/1
framerate:25/1
=========== Parse Time =============
microseconds:61000000
====================================

我的qq:2442391036,欢迎交流!


  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这个错误提示是说在编译过程中找不到libavutil/time.h文件。根据引用,这个错误是由于缺少linux/perf_event.h文件导致的。可以根据引用中的方法,在libavutil目录下创建一个avconfig.h文件,然后在avconfig.h文件中添加以下内容: ``` /* Generated by ffconf */ #ifndef AVUTIL_AVCONFIG_H #define AVUTIL_AVCONFIG_H #define AV_HAVE_BIGENDIAN 0 #define AV_HAVE_FAST_UNALIGNED 0 #endif /* AVUTIL_AVCONFIG_H */ ``` 如果问题仍然存在,可以尝试根据引用中的方法进行操作。具体步骤是进入/ijkplayer-master/config目录,查看module-default.sh文件的最后一行是否包含以下内容: ``` export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-linux-perf" ``` 如果没有的话,可以手动添加这一行。然后执行以下命令: ``` cd config rm module.sh ln -s module-lite.sh module.sh ``` 这样应该能解决缺少libavutil/time.h文件的错误。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [/libavutil/timer.h:38:31: fatal error: linux/perf_event.h: No such file or directory](https://blog.csdn.net/wusejiege6/article/details/108310915)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [fatal error: libavutil/avconfig.h: No such file...](https://blog.csdn.net/athrunsunny/article/details/122369052)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

须尽欢~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值