本文记录对ffmpeg这个工具的理解和掌握,随时添加。
源代码获取
获取 ffmpeg 源代码快照:git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
多次尝试下载失败,减少了深度也一样:git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg --depth=1
放弃直接从git拉取代码,下载官网提供的快照代码:https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
编译
配置Makefile:./configure
执行编译,要等挺久的,可以去干掉别的事情:make
编译完成后,在根目录下生成了ffmpeg等可执行程序,在doc目录下生成了文档,清理下中间文件make clean
类库结构
-
libavcodec一组编解码实现 -
libavformat实现流协议,容器格式和基础IO访问 -
libavutil包含哈希、解压等辅助库 -
libavfilter提供解码管道中使用的过滤器 -
libavdevice提供访问、捕获、播放设备的抽象 -
libswresample实现音频混淆和重采样 -
libswscale实现颜色转换和缩放
可以看到,ffmpeg的代码结构组织清晰直接。
源码分析(libavcodec)
入口文件:/libavcodec/avcodec.h
ffmpeg在每个类库里面定义了一些group,每个group完成一类功能,并且可以有子group。libavcodec的分组如下:
-
libavc libavcodeclavc_encdeclavc_core
lavc_decodinglavc_encodinglavc_codeclavc_codec_nativelavc_codec_wraperslavc_codec_hwaccellavc_internal
lavc_encdec组定义了一组编解码的发送和接收API,每组API围绕一个特定的数据结构:
-
lavc_encdec(AVCodecContext)- 发送
AVFrame给编码器,并且循环调用recv方法获得AVPacket,一直到返回AVERROR或EAGAINavcodec_send_frameavcodec_receive_packet
- 发送
AVPacket给解码器,并且循环调用recv方法获得AVFrame,一直到返回AVERROR或EAGAINavcodec_send_packetavcodec_receive_frame
- 发送
编解码内部有不同的阶段:
- 开始阶段,
codec可能接受很多frams/packets输入,一直到内部缓存被填满才会返回frame - 中间阶段,发送输入数据后可能返回
ENGAIN,仅当并非所有的数据都被接收时发生,例如你可以在每个迭代中发送新数据,同时在返回ENGAIN时接收数据 - 结束阶段,需要刷新(
flushing/draining)- 对于编码,发送NULL给
avcodec_send_frame,循环调用avcodec_receive_packet一直到AVERROR_EOF - 对于解码,发送NULL给
avcodec_send_packet,循环调用avcodec_receive_frame一直到AVERROR_EOF
- 对于编码,发送NULL给