我在视频应用程序中插入了一些代码,以使用ffmpeg进行导出使用stdin(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
edit
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
我进行了一些更改,我在打开处添加了无缓冲标志
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日志中,我看到它被误解了,无法识别视频格式,并且它查找的音频不存在。
已修复,在waitForFinished()
之后添加closeWriteChannel()
,关闭stdin并等待ffmpeg自行终止。