1.环境搭建和整体工程说明
命令行输入:-i 3.flv -vcodec copy 2_audio.mp4
![188b1032690124fc2629db9f42d9d2b0.png](https://i-blog.csdnimg.cn/blog_migrate/7ccfb72a2f6d1169d32f81737932bdb8.jpeg)
转码的CPU占有率。
![1d8a6ce24d12b0613f16632d9b2b7b72.png](https://i-blog.csdnimg.cn/blog_migrate/aa109cd5bc331c836009dcd6eb5b32dc.jpeg)
需要在这个目录下,拷贝正确的SDL2.dll
![6ac7e71af8285bd768a7b1db0d108754.png](https://i-blog.csdnimg.cn/blog_migrate/104c61c4387b100699f46b85ca4ce577.jpeg)
转码过程:
![e6e14365f5ac7b342cc2d58c9031be5e.png](https://i-blog.csdnimg.cn/blog_migrate/08ee14efc1943dcd942f05e985349316.jpeg)
转码成功后,MP4的大小要比3.flv的大一些。
![874e4e5271a8737c11fd8dbdf0c8d0b8.png](https://i-blog.csdnimg.cn/blog_migrate/018c0fc763d6093f4e19606cc06a657f.jpeg)
使用Mediainfo查看转码前后的对比。
![46bf5dd0577f5d6f1a7838747c609258.png](https://i-blog.csdnimg.cn/blog_migrate/01b7e147624d218051236e365b8c73b4.jpeg)
接下来,就详细聊聊ffmpeg.c。
ffmpeg.c本质是是基于FFmpeg库开发的多媒体⽂件转换器(multimedia converter)。
ffmpeg.c的作⽤如下:
(1)转码:⽐如转成MP3/AAC/H264/H265等等。
(2)压缩:⽐如将PCM进⾏⾳频编码,YUV进⾏视频编码。
(3)提取:⽐如提取⾳频⽂件,保存为AAC,提前视频⽂件,保存为H264。
(4)截取:⽐如从第5秒开始截取10秒的视频。
(5)拼接:⽐如将多个⽂件视频拼接⻓⼀个⽂件视频。
(6)合并:⽐如实现九宫格输出。
(7)录屏:ffmpeg可以⽤来录屏,但效率不⾼。
市⾯是的格式⼯⼚⼯具,⼤部分都是基于ffmpeg.c⼆次开发,⽐如:
迅捷视频转换器
爱剪辑
2.ffmpeg框架分析
ffmpeg对应的⽂件
ffmpeg程序涉及的主要⽂件:
(1)cmdutils.c:解析命令相关的⼯具函数。
(2)ffmpeg_opt.c:负责解析命令⾏输⼊的参数,以-vcodec copy的处理为例,对应了opt_video_codec函数(key-value的结构,- 接下来的字符是代表key的开始,key后⾯紧跟着value)。重点关注的是解析出来的信息存储在 OptionsContext, ⽐如opt_video_codec函数。如下图,是解析命令的函数调用栈。
![27912abcdc774d4fa35ecb0b8dc4d1f8.png](https://i-blog.csdnimg.cn/blog_migrate/7247a339d0bed36140e11c6eb54d059a.jpeg)
然后在处理的时候 open_output_file -> choose_encoder -> new_video_stream ->new_output_stream -> choose_encoder的时候可以获取到对应的编码器到底应该使⽤什么。
![b1633131c5065a0a532f1999d532a1f3.png](https://i-blog.csdnimg.cn/blog_migrate/cf0d1c77a65e3bd19989a5b03eb2081a.jpeg)
ffmpeg.c:多媒体⽂件转换器的主体。
ffmpeg_cuvid.c:CUDA硬件相关的加速。
ffmpeg_filter.c:filter相关。
ffmpeg_hw.c:硬件加速相关。
3.ffmpeg程序框架流程
(1)解析命令⾏
ffmpeg_parse_options 解析命令⾏的函数。对应的命令 const OptionDef options,例如:
{ "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg =opt_video_codec },
{ "codec", HAS_ARG | OPT_STRING | OPT_SPEC |OPT_INPUT | OPT_OUTPUT, { .off =OFFSET(codec_names) },"codec name", "codec" },
(2)打开输⼊⽂件 open_input_file
avformat_open_input。
分析码流 avformat_find_stream_info。
查找对应的编码器。
(3)打开输出⽂件 open_output_file
avformat_alloc_output_context2 先建⼀个输出⽂件。
avformat_new_stream 新建⼀个steam。
(4)读取输⼊⽂件
av_read_frame 读取输⼊⽂件。
(5)解码编码
解码:avcodec_send_packet和avcodec_receive_frame。
编码:avcodec_send_frame和avcodec_receive_packet。
(6)写⼊输出⽂件
avformat_write_header写⼊头部。
av_interleaved_write_frame 交替写⼊packet。
av_write_trailer 写⼊尾部。
4.框图分析
接下来主要分析transcode()。
![0db2f926c9b24bbacf1cca060769bc56.png](https://i-blog.csdnimg.cn/blog_migrate/26f68d1ecc258088e23e261337b8fb94.jpeg)
transcode_init():转码的初始化⼯作。
check_keyboard_interaction():检测键盘操作。⽐如转码的过程中按下“q”键之后,会退出转码,该函数内还有⼀些其他的按键处理,具体看函数实现也是挺简单的。
transcode_step():进⾏转码。
print_report():打印转码信息,输出到屏幕上,如下信息:
![a05e238cbe8ad26991d545ae6a26f71d.png](https://i-blog.csdnimg.cn/blog_migrate/f6dc435c5f101907bfea3bd94d581ec9.jpeg)
flush_encoder():输出编码器中剩余的帧。
当中check_keyboard_interaction(),transcode_step(),print_report()三个函数位于⼀个循环之中会不断地运⾏。
transcode_init()调⽤了以下⼏个重要的函数:
(1)init_input_stream():当中调⽤了avcodec_open2()打开编码器。
(2)init_output_stream()。
(3)av_dump_format()在屏幕上打印输出格式信息。注意是输出格式的信息。输⼊格式的信息的打印是在parse_options()函数运⾏过程中调⽤opt_input_file()的时候打印到屏幕上。
(4)avformat_write_header():写输出⽂件的⽂件头。
transcode_step()调⽤了例如以下函数:
(1)process_input():完成解码⼯作。
(2)transcode_from_filter():未分析。
(3)reap_filters():完成编码⼯作。
(4)process_input()流程图如下所示:
![0b9b3fcdc25e809f01ef1c51c79bd63c.png](https://i-blog.csdnimg.cn/blog_migrate/e91878e602f7ba11742f6fba31c9b860.jpeg)
get_input_packet():获取⼀帧压缩编码数据,即⼀个AVPacket。当中调⽤了av_read_frame()。
output_packet():解码压缩编码的数据并将之送⾄AVFilterContext。
output_packet()调⽤了例如以下函数:
decode_video():解码⼀帧视频(⼀个AVPacket)。
decode_audio():解码⾳频(并不⼀定是⼀帧,是⼀个AVPacket)。
do_streamcopy():假设不需要⼜⼀次编码的话,则调⽤此函数,⼀般⽤于封装格式之间的转换。速度⽐转码快⾮常多。
decode_video()调⽤了例如以下函数:
avcodec_decode_video2():解码⼀帧视频。
rate_emu_sleep():要求依照帧率处理数据的时候调⽤。能够避免FFmpeg处理速度过快。经常使⽤于⽹络实时流的处理(RTP/RTMP流的推送)。
configure_filtergraph():设置AVFilterGraph。
av_buffersrc_add_frame():将解码后的数据(⼀个AVFrame)送⾄AVFilterContext。
decode_audio()调⽤的函数和decode_video()基本⼀样。唯⼀的不同在于其解码⾳频的函数是avcodec_decode_audio4()。
reap_filters():主要完成了编码的工作。
其函数调⽤结构例如以下图:
![9bd2482e79d0ea2794c15f02d7e8f1d7.png](https://i-blog.csdnimg.cn/blog_migrate/64011dc9f0b9bc8fd0f5ab53012bc3a7.jpeg)
reap_filters()调⽤了例如以下函数:
av_buffersink_get_buffer_ref():从AVFilterContext中取出⼀帧解码后的数据(结构为AVFilterBufferRef。能够转换为AVFrame)。
avfilter_copy_buf_props():AVFilterBufferRef转换为AVFrame。
do_audio_out():编码⾳频。
do_video_out():编码视频。do_video_out()调⽤了例如以下函数:
avcodec_encode_video2():编码⼀帧视频。
write_frame():写⼊编码后的视频压缩数据。
write_frame()调⽤了例如以下函数:
av_bitstream_filter_filter():使⽤AVBitStreamFilter的时候。会调⽤此函数进⾏处理。
av_interleaved_write_frame():写⼊压缩编码数据。
avfilter_unref_buffer():释放资源。
do_audio_out()调⽤的函数与do_video_out()基本上⼀样。唯⼀的不同在于视频编码函数。
avcodec_encode_video2()变成了⾳频编码函数avcodec_encode_audio2()。
exit_program()主要完成了清理⼯作。调⽤关系例如以下图:
![4afcc58ec1f5655076821cf7d86ccce1.png](https://i-blog.csdnimg.cn/blog_migrate/9a59ad24851dbb0455a1e4539d9a773b.jpeg)
调⽤了如以下函数:
avfilter_graph_free():释放AVFilterGraph。
avformat_free_context():释放输出⽂件的AVFormatContext。
av_bitstream_filter_close():关闭AVBitStreamFilter。
avformat_close_input():关闭输⼊⽂件。
4.附加部分
(1)解析命令行ffmpeg_parse_options。
(2)打开输入文件。
(3)打开输出文件。
(4)读取输入文件,av_read_frame。函数调用栈如下:
![3652ee3462348938b18294bee430b6e0.png](https://i-blog.csdnimg.cn/blog_migrate/0facb409567cce67f48e9a5bc41ddd6b.jpeg)
(5)编解码
解码:avcodec_send_packet。
编码:avcode_send_frame。
解码video:
![86e916dff01e199772fc35b3815a3f4d.png](https://i-blog.csdnimg.cn/blog_migrate/f85fb9039e36b1cd48a364ffcd43e22e.jpeg)
![bb3392b87e4add1cd3a8bcaa7b69aa66.png](https://i-blog.csdnimg.cn/blog_migrate/470cedff803dcfe460bcd7b759577847.jpeg)
解码audio:
![5d36cbcb477b5169a416960bd1550616.png](https://i-blog.csdnimg.cn/blog_migrate/623f2201a75607e2d6d5dc169f1c968d.jpeg)
(6)将packet写入输出文件
avformat_write_header:写入头部。
av_interleaved_write_frame:写入packet。
av_write_trailer:写入尾部。
![4ef5edb29c5cee09cdd3d42af27bdbe6.png](https://i-blog.csdnimg.cn/blog_migrate/1d995670ed3b8df6aa718768b4683efc.jpeg)
本篇文章就分享到这里,欢迎关注,点赞,转发,收藏。
![690c7d0a3f86fee8d83e6165a12e11a0.png](https://i-blog.csdnimg.cn/blog_migrate/d972d3359253f3565b09c32bc777bab3.jpeg)