《FFmpeg原理》的社群来了,想加入社群的朋友请购买 VIP 版,VIP 版有更高级的内容与答疑服务。
本系列 以 ffmpeg4.2 源码为准,下载地址:链接:百度网盘 提取码:g3k8
本系列主要分析各种 ffmpeg 命令参数 在代码里是如何实现的。a.mp4下载链接:百度网盘,提取码:nl0s 。
命令如下:ffmpeg -i a.mp4 -t 10 a2.mp4
-t 10 ,从开头截取10秒的视频数据。
命令行参数 -t 定义如下:
ffmpeg_opt.c 3404行
{ "t", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{.off = OFFSET(recording_time) },
"record or transcode \"duration\" seconds of audio/video",
"duration" },
从上面定义可以看出,-t 10 会解析赋值 给 OptionsContext 的 recording_time 字段。
我刚开始搜索的时候,以为是 check_recording_time() 实现了上面那条命令的时间限制,断点调试下来发现不是,根本没跑进去 check_recording_time()。
一步一步加断点,发现到最后一帧的时候 av_buffersrc_add_frame_flags() 函数执行之后,avfilter_graph_request_oldest() 立即返回了 AVERROR_EOF,这个很奇怪。如图:
看ffmpeg的源码,函数说明,只有传递进 av_buffersrc_add_frame_flags() 函数 的AVFrame 是NULL,下次调 avfilter_graph_request_oldest() 才会返回 AVERROR_EOF。
最后一帧AVFrame 明明不是NULL,却也导致 avfilter_graph_request_oldest() 返回了 AVERROR_EOF。非常奇怪。
能让 filter 链返回结束,输入的AVFrame 又是正常的,我思索了30分钟,那只能在 初始化 filter那里搞了点事情。
重新看回 configure_input_video_filter() 函数,发现里面果然用了 recording_time 这个变量,请看下图。
总结:
能让 avfilter_graph_request_oldest() 返回了 AVERROR_EOF,有两种情况。
1,传递进 av_buffersrc_add_frame_flags() 函数 的AVFrame 是NULL。
2,初始化filter 的时候用了 trim filter,时间裁剪滤镜,到时间了,avfilter_graph_request_oldest() 也会返回了 AVERROR_EOF。
由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。