3

这就是我想要做的:

ffmpeg.exe -y \
-f dshow -i video="Microsoft LifeCam Cinema" \
-f dshow -i video="Microsoft LifeCam VX-2000" \
-filter_complex "[0:v]pad=iw*2:ih:0[left];[left][1:v]overlay=W/2.0[fileout]" \
-map "[fileout]" -vcodec libx264 -f flv out.flv

基本上,我有 2 个网络摄像头,我想将它们组合成一个视频文件,其中帧大小为 2x1,左侧一个摄像头的帧,右侧另一个摄像头的帧。

换句话说,可以称为“马赛克”或“并排合成”。这不是串联 - 即一个文件一个接一个(所以不使用 concat 过滤器)。

我已经看到这种使用-filter_complex填充然后定位框架出现在规定的方式。事实上,当我用这样的文件测试它时:

ffmpeg.exe -y -i test1.flv -i test2.flv -filter_complex "[0:v]pad=iw*2:ih:0[left];[left][1:v]overlay=W/2.0[fileout]" -map "[fileout]" -vcodec libx264 -f flv testout.flv

它工作正常!

然而,在“现场”版本中,两台相机似乎都启动了(它们的灯亮了),但捕捉却停滞不前。

(怀疑像在单独的输入设备线程上有一些 DirectShow 死锁......)

所以,我想知道有没有办法克服这个问题并强制两个输入流的数据合并?

我也尝试过 dshow 过滤器选项的扩展格式,如下所示:

-f dshow -i video="Microsoft LifeCam Cinema":video="Microsoft LifeCam VX-2000"

但是然后只选择了一个摄像机(我怀疑这个选项实际上只是为了使单独的视频和音频流能够合并)。

我还尝试将每个输入设备显式设置为具有完全相同的帧大小和速率-f dshow -video_size 640x480 -framerate 30。虽然没有喜悦。一旦相机被列出,它仍然会停止。

这是输出的结尾(-v debug打开):

Finished splitting the commandline.
Parsing a group of options: global .
Applying option y (overwrite output files) with argument 1.
Applying option v (set libav* logging level) with argument debug.
Applying option filter_complex (create a complex filtergraph) with argument [0:v]pad=iw*2:ih:0[left];[left][1:v]overlay=W/2.0[fileout].
Successfully parsed a group of options.
Parsing a group of options: input file video=Microsoft LifeCam Cinema.
Applying option f (force format) with argument dshow.
Successfully parsed a group of options.
Opening an input file: video=Microsoft LifeCam Cinema.
[dshow @ 00000000016e79a0] All info found
[dshow @ 00000000016e79a0] Estimating duration from bitrate, this may be inaccurate
Input #0, dshow, from 'video=Microsoft LifeCam Cinema':
  Duration: N/A, start: 1130406.072000, bitrate: N/A
    Stream #0:0, 1, 1/10000000: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 640x480, 333333/10000000, 30 tbr, 10000k tbn, 30 tbc
Successfully opened the file.
Parsing a group of options: input file video=Microsoft LifeCam VX-2000.
Applying option f (force format) with argument dshow.
Successfully parsed a group of options.
Opening an input file: video=Microsoft LifeCam VX-2000.
[dshow @ 00000000016e79a0] real-time buffer 101% full! frame dropped!

编辑尝试在代码中修复的更多详细信息... *

我一直从过去的 Windows DirectShow 工作中了解到,在同一个线程上多次调用 CoInitialize() 是不好的。见这里。也许我误解了 FFMPEG 是如何多线程的(即,如果每个输入设备都在它自己的线程上),但我想尝试用一个保护变量来调节调用(a static int com_init = 0;- 这可能应该是互斥锁......) .

例如在 libavdevice/dshow.c 方法中dshow_read_header

889    if (com_init==0)
890     CoInitialize(0);
891    com_init++

与 dshow_read_close 类似

170    com_init--;
171    if (com_init==0)
172     CoUninitialize()

可悲的是,这不起作用。第一个相机启动,但第二个没有,错误是:

[dshow @ 0000000000301760] Could not set video options
video=Microsoft LifeCam VX-2000: Input/output error

(值得一试。看起来每个输入设备确实在同一个线程上......)

4

0 回答 0