《FFMPEG使用、源码框架、架构解析》
Fabrice Bellard真是个人才!软件代码结构又简单又实用,QEMU也是他写的。
如果FFMPEG、QEMU、Linux kernel中的架构都学会了,可以当一个合格的架构师了(里面的细节没有那么多时间和精力学,但学习到里面的思想是可以的)。
作者 | 日期 |
---|---|
将狼才鲸 | 2021-08-14 |
CSDN阅读完整版
b站其它视频才鲸嵌入式
Gitee源码下载地址才鲸/音视频编解码
一、使用方法一(直接使用软件)
1.1 ffplay使用
- 功能:
- 播放文件
- 打印ffplay软件的各种信息
- 播放控制:
设置宽高、静音、禁用音频、跳转、播放固定时间、设置窗口标题、循环播放、显示音频波形、显示音频频带、切换模式、指定输入文件、指定解码器、匹配流、指定解复用格式、指定流过滤器、指定协议、指定输入输出设备、指定像素格式、指定采样格式、指定频道布局、自动监测输出设备、设置日志级别、日志另存、设置CPU类型、libavformat/libavdevice/libavcodec库直接提供的AVOptions、设置帧大小、禁用字幕、设置无边框、窗口置顶、设置音量、设置任意键退出、自动旋转、自动丢帧、缓存大小 - 播放时支持的快捷键:
退出、全屏、暂停、切换显示模式、单步跳到下一帧、快进快退10s、快进快退1min、跳转到前章后章、跳转到鼠标点击位置(以百分比算)
1.2 ffmpeg使用
- 功能:
- 转换(转码、压缩、合并、拼接、裁剪、播放速度、分辨率、宽高、去掉音频、去掉视频……)
- 录制(录像、添加字幕、截图……)
- 流化(网络推送……)
- 过滤器(旋转、翻转、填充、裁剪、缩放、覆盖、模糊、锐化、Logo、文本、图片、马赛克、颤抖、色彩平衡、彩色黑白转换……)
- 图片处理(JPEG、GIF、视频转图片、图片转视频、裁剪、填充、翻转、旋转、覆盖、缩放……)
- 打印ffmpeg软件的各种信息:
显示帮助、显示支持的输入输出格式、编解码、协议 - 操作参数:
指定格式、指定输入输出文件名、是否覆盖输出文件、指定持续时间、指定开始时间点、设置标题/作者/版权/评论、音视频质量、时间偏移,比特率、帧数、宽高比、像素补齐、码率误差、缓冲区大小、指定编解码格式、流直接拷贝、处理遍数、图像组大小、视频量化标度、编码的初始复杂度、qp因子偏差、dct算法、idct算法、宏块决策、运动矢量、数据划分、与标准的严格性、高级帧内编码、无限运动矢量、是否交织编码、压缩帧psnr、标准比特率、最大Q值差距,音频码率、采样率、通道数、字幕codec、禁止字幕、多输出源、一个输入映射一个输出、视频同步方法、音频同步方法、解封装解码延时、过滤图、
1.3 ffprobe使用
- 功能:
- 打印音视频文件信息
封装格式、编码格式、流数量、码率、帧信息、版本信息、以JSON输出、以XML输出、以INI输出,指定输入文件格式、指定解码器、指定解复用器、指定过滤器、指定协议、指定像素格式、指定CPU、显示有效载荷、每个数据包、每个帧、章节、流、时间码
- 其中是基于libavXXX库来实现的
二、使用方法二(使用库)
2.1 可以使用的库
libavutil libswscale libswresample libavcodec libavformat libavdevice libavfilter
2.2 API调用示例:
- 打开音视频文件、打印音视频信息
avio_reading.c - 解码音频、输出PCM文件
decode_audio.c - 解码视频、每帧保存一张PGM图片
decode_video.c - 解封装、解码、输出YUV视频流和PCM音频流
demuxing_decoding.c - 声音编码、保存为MP2文件
encode_audio.c - 视频编码、保存为你指定格式的文件
encode_video.c - 计算hash校验值
ffhash.c - 音频过滤器、生成一个正弦波音频、进行采样格式/采样率/音量过滤后输出
filter_audio.c - 视频过滤器、变换宽高旋转后输出
filtering_video.c - 多播组播,输入一个文件,多个客户端可以连接并接收相同的文件
http_multiclient.c - 硬件解码
hw_decode.c - 使用元数据(键值对、字典)功能
metadata.c - 复用(封装)为MP4等容器
muxing.c - 使用Intel GPU视频surfaces中的输出帧进行QSV加速的H.264解码
qsvdec.c - 转复用(转封装)从MP4等容器中提取视频流和音频流封装成别的格式
remuxing.c - 音频重采样
resampling_audio.c - 视频缩放转换
scaling_video.c - 将MP4中音频转码为AAC
transcode_aac.c - 转码
transcoding.c - Intel VAAPI加速规范编码,YUV到H264
vaapi_encode.c - Intel VAAPI加速规范转码
vaapi_transcode.c - 通过麦克风录音
ffmpeg实现录屏+录音 - 通过摄像头录像
最简单的基于FFmpeg的AVDevice例子(读取摄像头) - 录屏
最简单的基于FFmpeg的AVDevice例子(屏幕录制)
2.2.1 libavdevice API详解
设备输入输出
16个API,4个结构体,2个枚举
-
整体:
libavdevice说明 -
结构体:
AVDeviceRect: 图像窗口的起始xy,窗口宽高大小
AVDeviceCapabilitiesQuery: 一个封装的类可继承,包含了封装类,指定编解码、音频采样深度、音频采样率、音频通道数、图像位宽、窗口宽高、帧宽高、帧率
AVDeviceInfo: 设备名字符串,设备描述字符串
AVDeviceInfoList: 设备名、设备总数、默认设备 -
API:
avdevice_version 获取版本号
avdevice_configuration 获取库编译时的配置
avdevice_license 获取许可证
avdevice_register_all 注册所有输入输出设备
av_input_audio_device_next 迭代获取一项音频输入设备
av_input_video_device_next 迭代获取一项视频输入设备
av_output_audio_device_next 迭代获取一项音频输出设备
av_output_video_device_next 迭代获取一项视频输出设备
avdevice_app_to_dev_control_message 从应用程序向设备发送控制消息
avdevice_dev_to_app_control_message 从设备向应用发送控制消息
avdevice_capabilities_create 获取设备名对应的可用的设备参数信息(不同设备私有)
avdevice_capabilities_free 上一条API使用后进行释放用
avdevice_list_devices 获取可用的设备名和参数
avdevice_free_list_devices 和上一条配套使用
avdevice_list_input_sources 获取可用的输入设备名和参数
avdevice_list_output_sinks 获取可用的输出设备
2.2.2 libavformat API详解
封装与解封装(mp4等容器解析)
基础类函数: 15个API
解封装(解复用):19个API,1个结构体
封装(复用):11个API,1个结构体
工具类函数:24个API,
-
整体:
libavformat -
结构体:
AVOutputFormat: 一个类,容器名称、容器详细名称、音频编解码器、视频编解码器、字幕编解码器、写音视频流的头(方法/函数接口)、写包、写尾、容器是否允许当前流的编码格式、获取输出时间戳、发送控制消息到设备、写未解码帧、获取设备列表、初始化、检查比特流 -
API:
avformat_version 获取libavformat库版本号
avformat_configuration 获取库编译时的配置
avformat_license 获取库许可证
avformat_network_init 初始化网络库
avformat_network_deinit 与上一条配合使用
av_muxer_iterate 迭代所有封装器
av_demuxer_iterate 迭代所有解封装器
avformat_alloc_context 分配AVFormatContext
avformat_free_context 与上一条配合使用
avformat_get_class 调用父类元素时使用
avformat_new_stream 添加一个流到多媒体文件(如添加h264、aac等)
av_stream_add_side_data 将现有数据封装流side信息
av_stream_new_side_data 与上一条配合使用
av_stream_get_side_data 获取流side信息
av_new_program (文档里没说)av_find_input_format 找到特定的解封装器
av_probe_input_format 猜测文件封装格式(如MP4)
av_probe_input_format2 同上,参数不一样(同一方法的重载)
av_probe_input_format3 同上
av_probe_input_buffer 使用文件的一部分内容猜测封装格式
av_probe_input_buffer2 同上,参数不一样
avformat_open_input 打开流,读头信息
av_demuxer_open 打开解封装器
avformat_find_stream_info 读文件多媒体包以获取流信息
av_find_program_from_stream 找到用以处理这个流的程序
av_program_add_stream_index 加上流的序号
av_find_best_stream 找到文件中最好的流
av_read_frame 递归的读流中的一帧
av_seek_frame 按时间戳跳到关键帧
avformat_seek_file 跳到指定时间
avformat_flush 丢弃所有内部缓存数据
av_read_play 开始播放一个网络流
av_read_pause 暂停网络流
avformat_close_input 关闭文件avformat_write_header 写流的头信息到输出文件
avformat_init_output 初始化解码器但是不写流的头信息
av_write_frame 写一帧到输出文件
av_interleaved_write_frame 确保正确的交织将帧写到输出文件
av_write_uncoded_frame 写未解码的帧
av_interleaved_write_uncoded_frame 以交织写未解码的帧
av_write_uncoded_frame_query 测试封装器是否支持未解码的帧
av_write_trailer 写流的尾信息并释放资源
av_guess_format 使用参数猜测输出文件封装信息(如.mp4 .m4v等)
av_guess_codec 通过封装器和文件名猜测解码器
av_get_output_timestamp 获取时间信息av_hex_dump 调试打印文件十六进制信息
av_hex_dump_log 调试打印文件十六进制信息到日志文件
av_pkt_dump2 发送调试包到文件流
av_pkt_dump_log2 发送调试包到日志文件
av_codec_get_id 获取给定编解码器的id
av_codec_get_tag 获取编解码器标志
av_codec_get_tag2 同上,参数不同
av_find_default_stream_index 找到默认流索引
av_index_search_timestamp 按时间戳找索引
av_add_index_entry 加索引到已排序列表
av_url_split 分割网址
av_dump_format 打印音视频流的细节参数
av_get_frame_filename 获取文件名
av_get_frame_filename2 同上,参数不同
av_filename_number_test 检查文件名是否是一组带序列名字的其中一个
av_sdp_create 为RTP网络推流生成SDP
av_match_ext 判断文件名的扩展名(后缀)
avformat_query_codec 判断容器是否支持当前流的编码类型
av_guess_sample_aspect_ratio 猜测视频流的宽高比
av_guess_frame_rate 猜测帧率
avformat_match_stream_specifier 检查流的规范
avformat_queue_attached_pictures 附加图片
avformat_transfer_internal_stream_timing_info 从一个流转移时间信息到另一个流
av_stream_get_codec_timebase 获取流的解码时间戳
2.2.3 libavcodec API详解
编解码(h264 aac等流)
-
整体:
libavcodec -
API:
基础类: 35个API,11个结构体
详见Core functions/structures.
基础类-未解码包:29个API,2个结构体
详见AVPacket
基础类-图片:8个API,1个结构体
详见AVPicture
解码:15个API
详见Decoding
解码-帧:7个API,2个结构体
详见Frame parsing
编码:5个API
详见Encoding
工具类:50个API,3个结构体
详见Utility functions
工具栏-像素格式:7个API
详见Pixel formats
工具类-快速傅里叶变换:
详见FFT functions
2.2.4 libavfilter API详解
视频滤镜
-
整体:
libavfilter -
API:
滤镜: 34个API,5个结构体
详见libavfilter
滤镜-缓存:6个API,2个结构体
详见Buffer sink API
滤镜-缓存-访问:11个API
详见Buffer sink accessors
2.2.5 libswscale API详解
视频缩放
- API:
缩放:31个API,2个结构体
详见libavfilter
2.2.6 libswresample API详解
音频重采样(声音倍速)
- API:
重采样: 21个API
详见libswresample
2.2.7 libpostproc API详解
后期效果处理 网上搜过后我还是不知道这个库干什么用的
- API:
后期效果处理: 8个API
详见libpostproc
2.2.8 libavutil API详解
工具模块 (这一块是重点,有很多代码结构和思想可供借鉴)
-
整体:
libavutil -
API:
加解密和校验: 8个API
包含的模块有:AES Base64 Blowfish CAMELLIA CAST5 DES Hash HMAC LZO RC4 TEA TWOFISH XTEA
详见Crypto and Hashing
数学运算:12个API
详见Mathematics
数学运算-用整数实现小数(时间基):13个API,1个结构体
详见AVRational
字符串处理(功能和string.h类似):28个API
详见String Manipulation
内存管理-堆管理:19个API
详见Heap Management
内存管理-动态数组:3个API
详见Dynamic Array
内存管理-杂项功能(设置可分配大小、检查溢出):2个API
详见Miscellaneous Functions
数据结构-有引用计数的数据缓存区:11个API,1个结构体
详见AVBuffer
数据结构-有锁的线程安全的有引用计数的数据缓存区:4个API
详见AVBufferPool
数据结构-有引用计数的已解码帧:43个API,2个结构体
详见AVFrame
数据结构-操作符重载(C实现面向对象):23个API,3个结构体
详见AVOptions
数据结构-操作符重载-猜测数据类型:6个API
详见Evaluating option strings
数据结构-操作符重载-赋值:11个API
详见Option setting functions
数据结构-操作符重载-取值:10个API
详见Option getting functions
数据结构-键值对(字典、元数据):8个API,1个结构体
详见AVDictionary
数据结构-树状结构:5个API
详见AVTree
视频相关-显示坐标系矩阵变换:3个API
详见Display transformation matrix functions
视频相关-球面映射(可用来播放360°视频、VR视频、3D等):4个API,1个结构体
详见Spherical video mapping
视频相关-3D处理(3D、VR):4个API,1个结构体
详见Stereo3D types and functions
音频相关-先进先出缓存:11个API
详见Audio FIFO Buffer
音频相关-多声道:11个API
详见Audio channel layouts
音频相关-混音:1个API,1个结构体
详见Audio downmix metadata
音频相关-采样格式:9个API
详见Audio sample formats
音频相关-采样调制:5个API
详见Samples manipulation
错误处理:2个API
详见Error Codes
日志记录:12个API
详见Logging Facility
其它(获取字符串、判断指针空、计算长度、打开UTF-8文件、获取时间基、按4字节填充字符串):6个API
详见Other
其它-一些宏和一些const字符串:
其它-图片相关:16个API
详见Image related
三、使用方法三(修改、增删源码重新编译生成库)
如:
1、将.m4v的后缀文件解析由默认的苹果视频文件格式改为mpeg4的流
2、按只选中编译自己支持的特定容器封装解封装、音视频编解码,输出最小的libavXXX的动态库文件
四、使用方法四(学习、拷贝、修改自己需要的代码块在专用硬件上编译,实现自己需要的某几项音视频相关的功能)
4.1 AVClass(C实现面向对象,可继承)
资料:
FFmpeg源代码简单分析:结构体成员管理系统-AVClass
4.2 AVOption(C实现操作符重载)
资料:
FFmpeg源代码简单分析:结构体成员管理系统-AVOption