使用 Qt 的 QProcess 作为 popen(使用 ffmpeg rawvideo)
Posted
技术标签:
【中文标题】使用 Qt 的 QProcess 作为 popen(使用 ffmpeg rawvideo)【英文标题】:using Qt's QProcess as popen (with ffmpeg rawvideo) 【发布时间】:2019-10-06 22:18:43 【问题描述】:我在视频应用程序中插入了一些代码以使用 ffmpeg 导出
使用标准输入(rawideo rgba 格式),快速测试它是否有效
使用popen()
,测试进行得很顺利,因为应用程序是
使用 Qt 编写我想使用QProcess
修改补丁和
->write()
.
应用程序没有显示错误并且可以正常工作,但是生成的
视频文件既不能用 vlc 也不能用 mplayer 播放,而
使用popen()
生成的那些都可以完美地工作。我有
感觉->close()
或->terminate()
没有正确关闭
ffmpeg 和因此文件,但我不知道如何验证它
我也没有找到结束执行命令的替代方法,除了
->waitForBytesWritten()
应该等待数据写入,
建议?我做错了吗?
(显然我无法准备一个可测试的示例,这将花费我更多时间 比补丁花费的时间)
下面是我输入的代码,如#else
为Qt代码
初始化
#if defined(EXPORT_POPEN) && EXPORT_POPEN == 1
pipe_frame.file = popen("/tmp/ffmpeg-rawpipe.sh", "w");
if (pipe_frame.file == NULL)
return false;
#else
pipe_frame.qproc = new QProcess;
pipe_frame.qproc->start("/tmp/ffmpeg-rawpipe.sh", QIODevice::WriteOnly);
if(!pipe_frame.qproc->waitForStarted())
return false;
#endif
编写框架
#if defined(EXPORT_POPEN) && EXPORT_POPEN == 1
fwrite(pipe_frame.data, pipe_frame.width*4*pipe_frame.height , 1, pipe_frame.file);
#else
qint64 towrite = pipe_frame.width*4*pipe_frame.height,
written = 0, partial;
while(written < towrite)
partial = pipe_frame.qproc->write(&pipe_frame.data[written], towrite-written);
pipe_frame.qproc->waitForBytesWritten(-1);
written += partial;
#endif
终止
#if defined(EXPORT_POPEN) && EXPORT_POPEN == 1
pclose(pipe_frame.file);
#else
pipe_frame.qproc->terminate();
//pipe_frame.qproc->close();
#endif
编辑
ffmpeg-rawpipe.sh
#!/bin/sh
exec ffmpeg-cuda -y -f rawvideo -s 1920x1080 -pix_fmt rgba -r 25 -i - -an -c:v h264_nvenc \
-cq:v 19 \
-profile:v high /tmp/test.mp4
我做了一些更改,我在 open 中添加了无缓冲标志
pipe_frame.qproc->start("/tmp/ffmpeg-rawpipe.sh", QIODevice::WriteOnly|QIODevice::Unbuffered);
因此简化了写作
qint64 towrite = pipe_frame.width*4*pipe_frame.height;
pipe_frame.qproc->write(pipe_frame.data, towrite);
pipe_frame.qproc->waitForBytesWritten(-1);
我在关闭应用程序之前添加了一个 closeWriteChannel(希望停止 stdin ffmpeg 管道正确结束,以防万一,我不确定它不会)
pipe_frame.qproc->waitForBytesWritten(-1);
pipe_frame.qproc->closeWriteChannel();
//pipe_frame.qproc->terminate();
pipe_frame.qproc->close();
但没有任何变化,mp4 文件已创建并包含数据,但从 mplayer 日志中我看到它被误解了,视频格式无法识别,它会查找不存在的音频。
【问题讨论】:
分享.sh ... @eyllanesc 当然,我将它添加到答案中,但它不相关,相同的 .sh 用于 popen 和 QProcess。 【参考方案1】:修复,在closeWriteChannel()
之后添加waitForFinished()
,关闭stdin并等待ffmpeg自行终止。
pipe_frame.qproc->waitForBytesWritten(-1); // perhaps not necessary
pipe_frame.qproc->closeWriteChannel();
pipe_frame.qproc->waitForFinished();
pipe_frame.qproc->close();
编辑
注意,即使使用 unbuffered 标志初始化,QProcess 和 QIODevice 似乎缓冲了很多,似乎waitForBytesWritten ()
不起作用,如果你正在输入高清视频,你会很快耗尽内存。
【讨论】:
以上是关于使用 Qt 的 QProcess 作为 popen(使用 ffmpeg rawvideo)的主要内容,如果未能解决你的问题,请参考以下文章