我在将 DirectShow 图形集成到现有应用程序中时遇到了一些奇怪的问题。
首先要介绍几件事:
- 该图的目的是从具有暴露 DirectShow 接口的 FrameGrabber 中获取原始视频。该图通过 VMR9 将视频正确显示,并通过 ISampleGrabber(DirectShow 示例)将原始帧暴露给某些算法。
- 该图已在单个项目中成功构建并运行。视频显示良好,一切都很愉快。
现在,当我将其集成到现有代码中时,问题就出现了。从应用程序的初始化开始,我首先创建并启动图形,在无窗口模式下运行 VMR9。在初始化的后期,我通过 _beginthreadex 创建了几个工作线程。当且仅当图形已构建并运行时,对 _beginthreadex 的调用失败并返回代码 12(内存不足)。
现在显而易见的答案是我内存不足或可能是其他一些资源。但是,当线程尝试启动时,我正在使用约 420MB 的 2GB 系统内存。线程堆栈大小已明确设置为 1MB。所以据我所知,我并没有失忆。此外,正在运行的应用程序中总共有 15 个线程,所以我并没有创造一个荒谬的数量。
有没有人遇到过与 DirectShow 类似的问题?我正在寻找任何输入,我们已经尝试调试这个问题很长一段时间了,但一直没有成功。
我将发布您需要的任何代码,与大多数 DirectShow 图表一样,代码很长。
编辑
按照要求。我不确定 DirectShow 代码的哪一部分导致线程无法启动。但是,如果我只构建而不运行图表,则线程可以正常工作。所以我猜想失败发生在运行调用之后。我运行图表的代码如下:
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;
SetVMRSize 函数只是将 VMR 调整为其父窗口的大小:
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);
}
}
值得注意的是,pWindowControllerIVMRWindowlessControl9
和 pMediaControl 是IMediaControl
编辑 2
使用 CreateThread 而不是 __beginthreadex 测试了代码。启动线程失败后,GetLastError() 返回:
8:没有足够的存储空间来处理这个命令。
创建线程的代码如下所示:
HANDLE worker_thread = CreateThread(0,
Thread_Stack_Size, worker_thread_op, thread_param, 0, 0);
CreateThread 的一些参数:
Thread_Stack_Size = 1024 * 1024;
typedef DWORD (WINAPI *worker_thread_op_type)(LPVOID params);