音视频应用场景:
- 直播类:音视频会议、教育直播、娱乐/游戏直播等
- 短时频:抖音、快手、小咖秀
- 网络视频:优酷、腾讯视频、爱奇艺
- 音视频通话:微信、QQ、Skype等
- 视频监控
- 人工智能:人脸识别、智能音箱等,更关注算法。
一. FFmpeg日志
3个步骤:
- 包含include <libavutil/log.h>
- 设置打印级别:av_log_set_level(AV_LOG_DEBUG)
- 打印函数:av_log(NULL, AV_LOG_INFO, "...%s\n", p)
常用日志级别由高到低:
- AV_LOG_ERROR
- AV_LOG_WARNING
- AV_LOG_INFO
- AV_LOG_DEBUG
实例展示,建一个ffmpeg_log.c文件
#include<stdio.h>
#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: %s!\n", "shenfeng");
return 0;
}
编译该c文件:
clang -g -o ffmpeg_log ffmpeg_log.c -lavutil
运行:
./ffmpeg_log
PKG_CONFIG_PATH环境变量的设置
pkg-config
命令可以到 PKG_CONFIG_PATH 指定的路径下找指定库的 .pc 文件,然后从.pc 文件中拿到需要的库路径,名称以及头文件。比如执行:
clang -g -o test test.c `pkg-config --cflags --libs libavformat`
相当于执行:
clang -g -o ffmpeg_del ffmpeg_file.c -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -lavformat
可以通过 pkg-config 找到需要的库路径和头文件,也可以单独执行查看是否有该 pkg-config 的配置,没有的话找不到相应头文件:
pkg-config --libs libavutil
Package libavutil was not found in the pkg-config search path.
Perhaps you should add the directory containing `libavutil.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libavutil' found
需要配置PKG_CONFIG_PATH环境变量:
#ffmpeg
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/ffmpeg/lib/pkgconfig
#libssl
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/opt/openssl/lib/pkgconfig
保存退出再执行以下命令让设置立即生效:
source ~/.bash_profile
二. 文件的删除与重命名
1. 删除
avpriv_io_delete()
编译语句:
clang -g -o ffmpeg_del ffmpeg_file.c `pkg-config --libs libavformat`
ffmpeg_file.c文件代码如下:
2. 重命名
avpriv_io_move()
编译语句:
clang -g -o ffmpeg_del ffmpeg_file.c `pkg-config --libs libavformat`
ffmpeg_file.c文件代码如下:
三. 操作目录的函数
核心函数:
avio_open_dir()
avio_read_dir()
avio_close_dir()
相关类:
- AVIODirContext:操作目录的上下文
- AVIODirEntry:目录项,用于存放文件名、文件大小等信息
实战:实现一个ls命令。
1. 新建一个ffmpeg_list.c文件
#include <libavutil/log.h>
#include <libavformat/avformat.h>
int main (int argc, char* argv[]) {
int res;
AVIODirContext *ctx = NULL;
AVIODirEntry *entry = NULL;
av_log_set_level(AV_LOG_INFO);
res = avio_open_dir(&ctx, "./", NULL);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "Can't open dir:%s\n", av_err2str(res));
goto __fail;
}
while (1) {
res = avio_read_dir(ctx, &entry);
if (res < 0) {
av_log(NULL, AV_LOG_ERROR, "Can't read dir: %s\n", av_err2str(res));
goto __fail;
}
if (!entry) {
break;
}
av_log(NULL, AV_LOG_INFO, "%12"PRId64" %s \n", entry -> size, entry -> name);
avio_free_directory_entry(&entry);
}
__fail:
avio_close_dir(&ctx);
return 0;
}
其中,PRld:是一种跨平台的书写方式,主要是为了通知支持32位和64位操作系统。PRld64表示64位整数,在32位系统中表示long long int,在64位系统中表示long int:
printf("%" "ld" "\n", value);
printf("%" "lld" "\n", value);
2. 编译
clang -g -o list ffmpeg_list.c `pkg-config --libs libavformat libavutil`
四. 处理数据流的基本概念
1. 多媒体文件的基本概念
- 多媒体文件其实是个容器。
- 在容器里有很多流(Stream/Track)。
- 每种流是由不同的编码器编码的,比如音频mp3,视频H264、H265等等。
- 从流中读出的数据称为包。
- 在一个包中包含着一个或多个帧。
2. 几个重要的结构体
- AVFormatContext:格式上下文,连接api间的桥梁,多媒体文件的信息会存在这个结构体中,用来在调用不同api时辨别是哪个多媒体文件。
- AVStream:通过此结构体可以读取流。
- AVPacket:通过它获取数据包。
3. FFmpeg 操作流数据的基本步骤
总结:多媒体文件是个容器,里面包含了许多流,如音频、视频、字幕等等,通过解复用获取流,流中读取出数据包,数据包中存着一个或多个被压缩的数据帧。