工具(7): ffmpeg
本文记录对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 libavcodec
lavc_encdec
lavc_core
lavc_decoding
lavc_encoding
lavc_codec
lavc_codec_native
lavc_codec_wrapers
lavc_codec_hwaccel
lavc_internal
lavc_encdec
组定义了一组编解码的发送和接收API,每组API围绕一个特定的数据结构:
lavc_encdec
(AVCodecContext
)- 发送
AVFrame
给编码器,并且循环调用recv方法获得AVPacket
,一直到返回AVERROR
或EAGAIN
avcodec_send_frame
avcodec_receive_packet
- 发送
AVPacket
给解码器,并且循环调用recv方法获得AVFrame
,一直到返回AVERROR
或EAGAIN
avcodec_send_packet
avcodec_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给