I am having some strange issues integrating a DirectShow graph into an existing application.
A couple things to cover first:
- The graph's purpose is to bring raw video from a FrameGrabber which has an exposed DirectShow interface. The graph takes the video right to display through VMR9 as well as exposing the raw frames to some algorithms through the ISampleGrabber (DirectShow Examples).
- The graph has been built and run succesfully in an individual project. The video is displayed fine and everything is happy.
Now the issue comes in when I am integrating this into existing code. From the initialization of the application I first create and start the graph, running VMR9 in a windowless mode. Later in the initialization I create a couple of worker threads via _beginthreadex. The calls to _beginthreadex fail with a return code of 12 (Out of memory) when and ONLY when the graph has both been built and ran.
Now the obvious answer is I am out of memory or perhaps some other resource. However, at the point when the threads are trying to start I am using ~420MB of the 2GB system memory. The thread stack size has been explicitly set to 1MB. So I am not out of memory as far as I can tell. Additionally, there are a total of 15 threads in the running application so I am not creating an absurd amount.
Has anyone had/experienced a similar issue with DirectShow? I am looking for any input at all, we have been trying to debug this issue for quite some time now and have not been succesful.
I will post any code that you require, as with most DirectShow graphs the code is lengthy.
Edit
As requested. I'm not sure what part of the DirectShow code causes the threads to fail to launch. However, if I only build, but do not run the graph, the threads work alright. So I would guess that the failure occurs after the run call. My code to run the graph is as follows:
if (CurrentState != Stopped)
return WrongState;
HRESULT hr;
printf("Attempting to run graph... ");
Timer->Start();
hr = pMediaControl->Run();
if (FAILED(hr))
{
OAFilterState State;
hr = pMediaControl->GetState(1000, &State);
if ((SUCCEEDED(hr) && State != State_Running) || FAILED(hr))
{
return FailedToStartGraph;
}
}
CurrentState = Streaming;
SetVMRSize();
Timer->Stop();
RunTime->Start();
FrameRate->Reset();
return NoError;
The SetVMRSize function simply resizes the VMR to its parent window:
void KontronGraph::SetVMRSize()
{
if (CurrentState == Disconnected || VideoMode != ParentWindow)
return;
long lWidth, lHeight;
HRESULT hr = pWindowController->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
if (SUCCEEDED(hr))
{
RECT rcSrc, rcDest;
// Set the source rectangle.
rcSrc.left = 0;
rcSrc.right = lWidth;
rcSrc.top = 0;
rcSrc.bottom = lHeight;
// Get the window client area.
GetClientRect(MyHwnd, &rcDest);
// Set the destination rectangle.
rcDest.right = rcDest.right - rcDest.left;
rcDest.bottom = rcDest.bottom - rcDest.top;
rcDest.left = 0;
rcDest.top = 0;
// Set the video position.
hr = pWindowController->SetVideoPosition(&rcSrc, &rcDest);
}
}
Of note, pWindowController is IVMRWindowlessControl9
and pMediaControl is IMediaControl
Edit 2
Tested the code using CreateThread instead of __beginthreadex. After failing to launch the threads, GetLastError() returns:
8 : Not enough storage is available to process this command.
The code to create threads looks like:
HANDLE worker_thread = CreateThread(0,
Thread_Stack_Size, worker_thread_op, thread_param, 0, 0);
Some of the parameters for CreateThread:
Thread_Stack_Size = 1024 * 1024;
typedef DWORD (WINAPI *worker_thread_op_type)(LPVOID params);