fileapi::WriteFile() 不发送输入,如果设置了 processthreadsapi::STARTUPINFO::hStdError (ffmpeg)
fileapi::WriteFile() doesn't send an input, if processthreadsapi::STARTUPINFO::hStdError is set (ffmpeg)
我正在尝试在另一个线程中使用 ffmpeg
捕获我的屏幕(我使用 processthreadsapi::CreateProcess())
创建它,这样我就可以在主线程中执行其他操作,并重定向ffmpeg
输出,所以它不会在控制台中弹出供用户查看。要停止拍摄,我使用 WriteFile()
发送 'q' 输入,然后我想保存ffmpeg
使用 ReadFile()
.
累积输出
但是,如果我将 STARTUPINFO::hStdError
(注意,ffmpeg
输出转到 stderr
)到一个管道,我可以从中读取累积数据,我发送的输入使用 WriteFile()
不再注册并且 ffmpeg.exe 保留 运行.
我已经尝试在一个简单的命令行中重定向 ffmpeg
输出,但我仍然可以通过按 q 按钮停止该过程。
此外,如果我的记录时间少于 8 秒,输入将被注册并 ffmpeg.exe
关闭。
我的代码有问题吗,或者是processthreadsapi问题,任何提示将不胜感激!
这是我尝试执行此操作的最少代码:
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
int main()
{
//Create IN and OUT pipes
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.lpSecurityDescriptor = NULL;
if (! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
cout<<"StdoutRd CreatePipe error"<<endl;
if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0) )
cout<<"Stdin CreatePipe error"<<endl;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
//Start recording
if(!CreateProcess(NULL,
"ffmpeg -y -f gdigrab -framerate 2 -i desktop record.avi", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo)) // receives PROCESS_INFORMATION
{
cout<<"Error create process"<<endl;
}
else
{
cout<<"Process created successfully"<<endl;
cout<<"Press k to stop recording"<<endl;
}
//Record for a while
while(getch() != 'k'){
cout<<"While press k"<<endl;
};
cout<<"Stop recording called"<<endl;
//Stop recording by emulating a Q button push
DWORD dwWritten;
CHAR chBufW[1] = {'q'};
if ( ! WriteFile(g_hChildStd_IN_Wr, chBufW, 1, &dwWritten, NULL) )
cout<<"Error write file"<<endl;
//Save stdError (ffmpeg) data
DWORD dwRead;
char stdErrorData[4096];
bool bSuccess;
bSuccess = ReadFile( g_hChildStd_OUT_Wr, stdErrorData, 4096, &dwRead, NULL);
if(!bSuccess || dwRead == 0)
cout<<"Read failed"<<endl;
else{
cout<<"Read success"<<endl;
}
cout<<"Press to exit"<<endl;
while(getch() != 'k');
return 0;
}
为了回答我自己的问题,问题是当 ffmpeg 输出的句柄管道填满时,它会停止 ffmpeg 进程,直到我为新的清除一些 space要输入的文本。这正在发生,因为 ffmpeg 不断输出记录信息。
我希望这对某人有用:)
我正在尝试在另一个线程中使用 ffmpeg
捕获我的屏幕(我使用 processthreadsapi::CreateProcess())
创建它,这样我就可以在主线程中执行其他操作,并重定向ffmpeg
输出,所以它不会在控制台中弹出供用户查看。要停止拍摄,我使用 WriteFile()
发送 'q' 输入,然后我想保存ffmpeg
使用 ReadFile()
.
但是,如果我将 STARTUPINFO::hStdError
(注意,ffmpeg
输出转到 stderr
)到一个管道,我可以从中读取累积数据,我发送的输入使用 WriteFile()
不再注册并且 ffmpeg.exe 保留 运行.
我已经尝试在一个简单的命令行中重定向 ffmpeg
输出,但我仍然可以通过按 q 按钮停止该过程。
此外,如果我的记录时间少于 8 秒,输入将被注册并 ffmpeg.exe
关闭。
我的代码有问题吗,或者是processthreadsapi问题,任何提示将不胜感激!
这是我尝试执行此操作的最少代码:
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
int main()
{
//Create IN and OUT pipes
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.lpSecurityDescriptor = NULL;
if (! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
cout<<"StdoutRd CreatePipe error"<<endl;
if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0) )
cout<<"Stdin CreatePipe error"<<endl;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
//Start recording
if(!CreateProcess(NULL,
"ffmpeg -y -f gdigrab -framerate 2 -i desktop record.avi", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo)) // receives PROCESS_INFORMATION
{
cout<<"Error create process"<<endl;
}
else
{
cout<<"Process created successfully"<<endl;
cout<<"Press k to stop recording"<<endl;
}
//Record for a while
while(getch() != 'k'){
cout<<"While press k"<<endl;
};
cout<<"Stop recording called"<<endl;
//Stop recording by emulating a Q button push
DWORD dwWritten;
CHAR chBufW[1] = {'q'};
if ( ! WriteFile(g_hChildStd_IN_Wr, chBufW, 1, &dwWritten, NULL) )
cout<<"Error write file"<<endl;
//Save stdError (ffmpeg) data
DWORD dwRead;
char stdErrorData[4096];
bool bSuccess;
bSuccess = ReadFile( g_hChildStd_OUT_Wr, stdErrorData, 4096, &dwRead, NULL);
if(!bSuccess || dwRead == 0)
cout<<"Read failed"<<endl;
else{
cout<<"Read success"<<endl;
}
cout<<"Press to exit"<<endl;
while(getch() != 'k');
return 0;
}
为了回答我自己的问题,问题是当 ffmpeg 输出的句柄管道填满时,它会停止 ffmpeg 进程,直到我为新的清除一些 space要输入的文本。这正在发生,因为 ffmpeg 不断输出记录信息。
我希望这对某人有用:)