本文 以 ffmpeg4.4 源码为准,a.mp4下载链接:百度网盘,提取码:nl0s 。
命令如下:
ffmpeg.exe -i a.mp4 -ss 00:00:7.435 -vframes 1 out.png
上面的命令是 偏移到 7 秒左右的地方,截图 一张图片来进行保存。
-ss
在 《ffmpeg命令分析-ss》里面已经讲过,本文不再分析,本文主要讲解 -vframes
参数在 ffmpeg 工程中的实现。
vframes
的定义如下:
{ "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames },
"set the number of video frames to output", "number" },
会调用 opt_video_frames
函数,opt_video_frames
函数如下:
static int opt_video_frames(void *optctx, const char *opt, const char *arg)
{
OptionsContext *o = optctx;
return parse_option(o, "frames:v", arg, options);
}
从上面代码可以看出,-vframes
实际上 是 -frames:v
的另一种写法,所以真正的 定义是 -frames
,定义如下:
{ "frames", OPT_INT64 | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(max_frames) },
"set the number of frames to output", "number" },
从上面的代码可以看出,frames
最后就解析到 max_frames
,OFFSET 是一个宏,定位到 OptionsContext 的偏移位置。max_frames
实际上是 OptionsContext 里面的 max_frames 。
下面就看看 哪些地方使用了 max_frames
这个变量。
通过全局搜索 max_frames
可知,new_output_stream()
函数里面有使用,代码如下:
#ffmpeg_opt.c 1537行
ost->max_frames = INT64_MAX;
MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st);
从上面代码可以看出,命令行中的 max_frames
最后会赋值给 ost->max_frames
,ost 是一个 struct OutputStream
结构。
继续分析,ost->max_frames 又在哪里被使用了呢?答案如下:
在本文命令下,在 do_video_out()
函数中使用了 ost->max_frames
,代码如下:
//ffmpeg.c 1262行
nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
nb0_frames = FFMIN(nb0_frames, nb_frames);
do_video_out()
函数 的逻辑之前在 《ffmpeg源码分析-reap_filter》里详细讲过。
从上面两句代码可以看出,输出流的已经丢给编码器的 frame_number
如果等于大于 ost->max_frames
,nb_frames 变量 就会是0。
nb_frames
变成 0 就会导致 do_video_out 后面的 for (i = 0; i < nb_frames; i++) {}
循环不会执行,也就不会再有 AVFrame
输入给编码器。
这样就实现了 最大帧的功能。
最后 ost->max_frames
还在 need_output()
函数使用了一下,用于退出程序的。
版权所属:知识星球:弦外之音,QQ:2338195090。 由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。