BACKGROUND
I am building a basic MFC application which helps me to run tests. The GUI is extremely spartaic. One button to START and another button to STOP the test, plus a static text object to display a few letters and digits indicating what stage the test is performing. This has been working satisfactorily for weeks.
I would find it useful if my application also made a video screen recording while the test is performed. The big plan is to compile FFmpeg library function calls into the code to implement this capability, but this will certainly take me weeks to learn, try and complete. In the meantime, a quick but sufficient solution is to call a precompiled ffmpeg.exe from a downloaded Windows binary build.
I added code to the ::OnBnClickedButtonStarttest()
method to call ffmpeg.exe via CreateProcess()
. This is working fine. The FFmpeg screen recording process starts in a new console window and does its intended job very well. When I select that console window and press Ctrl+C, the recording stops and I have the desired video file. I also added code to the ::OnBnClickedButtonStoptest()
method to send the required Ctrl+C to the STDIN of the ffmpeg.exe process and finish recording when the STOP button is clicked. This is also working fine. MOST OF THE TIME.
These two portions of my source code are based on the example published at https://learn.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output by Microsoft.
PROBLEM
Stopping the screen recording process MOST OF THE TIME means that IT DOES NOT ALWAYS STOP. There are times when the solution does not work. And I am unable to find any reason why the same solution that works most of the time, happens to fail on other times. Eventually I would prefer to hide the FFmpeg console window and let it work behind the scene, but that would require a reliable way to stop the child process, and my current code proves to be not working reliably. Note: there is a #define BUFSIZE 128
line at the top of the source code.
DWORD dwNumOfBytesToWrite = 7;
DWORD dwWritten = 0;
CHAR chBuf[BUFSIZE] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x0A, 0x0D, 0x03, 0x0A, 0x0D };
BOOL bSuccess = FALSE;
bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwNumOfBytesToWrite, &dwWritten, NULL);
Although sending a single Ctrl+C (0x03) should stop the ffmpeg process, I send a little more input to be sure. Still, for some reason I have to send the above WriteFile
instruction twice, in order to actually see the process stop. I do not know why. This does not concern me much though, as long as the second time it does work.
What does concern me is the fact that there are times when the child process does not stop. No matter how many times I send it the above WriteFile
line.
I found another promising example. This time without anonymous pipes -which I suspect to be the source of the unreliable behaviour.
https://www.techpowerup.com/forums/threads/c-c-c-console-redirection-with-sockets-win32.62350/
This appear to use a named channel of its own to access the standard input of the child process. I prefer this approach. Unfortunately, it is not only that it does not work, it also does not compile. The Socket thisSocket;
line refers to a non-existing type. There is no such type as Socket
, not with an uppercase S
and lowercase ocket
. I tried to use all uppercase SOCKET
type in its place, which does compile, but an accordingly modified WriteFile((HANDLE)thisSocket, chBuf, dwNumOfBytesToWrite, &dwWritten, NULL);
line always returns FAILURE, and does not stop the child process.
To make my investigation more difficult, a large number of internet search hits take me to WINSOCK related topics instead.
Did I miss something?
What would be the reliable way of sending a Ctrl+C to the ffmpeg.exe process, in order to tactfully ask it to finish recording?
Mind you, I can brutally kill the FFmpeg console window via TerminateProcess(g_ffmpeg_process_handle, 0)
, but that does not always allow the child to properly close the video file, resulting a damaged screen recording.