ffmpeg.c学习-1-框架分析及命令行解析
目录
- 掌握ffmpeg.c的意义
- ffmpeg框架分析
- ffmpeg对应的⽂件
- ffmpeg程序框架流程
- 命令行解析
1. 掌握ffmpeg.c的意义
- ffmpeg.c本质是是基于FFmpeg库开发的多媒体⽂件转换器(multimedia converter)。
- ffmpeg.c的作⽤
- 转码:⽐如转成MP3/AAC/H264/H265等等;
- 压缩:⽐如将PCM进⾏⾳频编码,YUV进⾏视频编码;
- 提取:⽐如提前⾳频⽂件为AAC,提前视频⽂件为H264;
- 截取:⽐如从第5秒开始截取10秒的视频;
- 拼接:⽐如将多个⽂件拼接⻓⼀个⽂件;
- 合并:⽐如实现九宫格输出;
- 录屏:ffmpeg可以⽤来录屏,但效率不⾼。
- 市⾯是的格式⼯⼚⼯具,⼤部分都是基于ffmpeg.c⼆次开发,⽐如:
- 迅捷视频转换器
- 爱剪辑等等
- 掌握ffmpeg.c对于我们深⼊掌握FFmpeg⾮常有必要。
2. ffmpeg框架分析
1. ffmpeg对应的⽂件
- ffmpeg程序涉及的主要⽂件:
- cmdutils.c:解析命令相关的⼯具函数,不⽤太关注先;
- ffmpeg_opt.c:负责解析命令⾏输⼊的参数,以-vcodec copy的处理为例,对应了opt_video_codec函数(key-value的结构,-接下来的字符是代表key的开始,key后⾯紧跟着value)
- 我们重点关注的是解析出来的信息存储在 OptionsContext, ⽐如opt_video_codec函数
- 然后在处理的时候 open_output_file -> choose_encoder -> new_video_stream ->new_output_stream -> choose_encoder的时候可以获取到对应的编码器到底应该使⽤什么。
- ffmpeg.c:多媒体⽂件转换器的主体;
- ffmpeg_cuvid.c:CUDA硬件相关的加速;
- ffmpeg_filter.c:filter相关;
- ffmpeg_hw.c:硬件加速相关
2. ffmpeg程序框架流程
- 先忽略含有filter的情况。
- 解析命令⾏
- ffmpeg_parse_options 解析命令⾏的函数
- 对应的命令 const OptionDef options,例如
{ "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT,
{ .func_arg = opt_video_codec }, "force video codec ('copy' to copy stream)", "codec" },
{ "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT,
{ .func_arg = opt_data_codec }, "force data codec ('copy' to copy stream)", "codec" },
- 打开输⼊⽂件 open_input_file
- avformat_open_input
- 分析码流 avformat_find_stream_info
- 查找对应的编码器
- 打开输出⽂件 open_output_file
- avformat_alloc_output_context2 先建⼀个输出⽂件
- avformat_new_stream 新建⼀个steam
- 读取输⼊⽂件
- av_read_frame 读取输⼊⽂件
- 解码编码
- 解码:avcodec_send_packet和avcodec_receive_frame
- 编码:avcodec_send_frame和avcodec_receive_packet
- 写⼊输出⽂件
- avformat_write_header写⼊头部
- av_interleaved_write_frame 交替写⼊packet
- av_write_trailer 写⼊尾部
3. 命令行解析
1. FFmpeg 命令⾏基础语法:
ffmpeg [global_options] {[input_file_options] -i input_file}...{[output_file_options] output_file}...
- global_options:全局参数
- input_file_options:输⼊⽂件相关参数
- output_file_options:输出⽂件相关参数
- 如下为⼀个简单的 FFmpeg 命令,将 input.avi 视频⽂件转换为 640kbps 码率的 output.avi
ffmpeg -i 3.flv -acodec copy -vcodec libx264 -g 30 -b 500kb 3.mp4 -y -loglevel 56
- 当我们使⽤命令⾏来调⽤ FFmpeg 时,当命令⾏传⼊ FFmpeg 时,FFmpeg内部是如何识别这些命令并进⾏解析和赋值的呢?
- 总结起来,解析命令⾏的⼤致流程就是:
- 跳过 “–xx xxx” 参数
- “-xx xxx” 格式的默认参数存⼊全局参数数组或临时参数数组
- “-noxx xxx”格式的参数,即默认值为“0”,将值存⼊全局参数数组或临时参数数组
- 解析专属参数,并存⼊专属数组结构体(AVDictionary)
- “-i xxx” 格式的输⼊⽂件路径参数,将临时参数数组的值、输⼊⽂件路径以及专属参数存⼊输⼊相关参数结构体,并清空临时参数数组
- “xxx” 格式的输出⽂件路径参数,将临时参数数组的值、输出⽂件路径以及专属参数存⼊输出相关参数结构体,并清空临时参数数组
- 有关全局参数、输⼊参数、输出参数都存储到 OptionParseContext *octx 中
typedef struct OptionParseContext {
OptionGroup global_opts;
OptionGroupList *groups;
int nb_groups;
OptionGroup cur_group;
} OptionParseContext;
- 专属参数会先存储到 AVDictionary
AVDictionary *codec_opts;
AVDictionary *format_opts;
AVDictionary *resample_opts;
AVDictionary *sws_dict;
AVDictionary *swr_opts;
- 具体 split_commandline()函数⻅源码