I'm trying to capture my screen using ffmpeg in a different thread (which I create using processthreadsapi::CreateProcess()) so I'd be able to do something else in the main thread, and redirect ffmpeg output, so it wouldn't pop up in the console for the user to see. To stop filming, I send a 'q' input using WriteFile(), and after that I want to save ffmpeg accumulated output using ReadFile().
However, if I set STARTUPINFO::hStdError (note, that ffmpeg output goes to stderr) to a pipe, from which I could read the accumulated data, the inputs I send using WriteFile() are no longer registered and ffmpeg.exe keeps running.
I've tried redirecting ffmpeg output in a simple command line, but I can still stop the process by pressing the q button.
Also, if I record for less than 8 seconds, the input is registered and ffmpeg.exe closes.
Is there something wrong with my code, or is it processthreadsapi issue, any hints will be kindly appreciared!
Here's a minimal code of how I am trying to do it:
#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;
}