我遇到一些将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);
}
}
值得注意的是,pWindowController为IVMRWindowlessControl9
,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);
答案 0 :(得分:2)
首先,我建议您将_beginthreadex
替换为CreateThread
,然后使用GetLastError
确定任何错误的原因,这通常比CRT错误代码更具体由_beginthreadex
设置。通过这样做让我知道你观察到了什么,我会更新我的答案。
另外,你可以发布导致线程创建失败的(DirectShow)代码部分,以及创建线程的代码行吗?
更新:无论我发现有关具体错误的内容,您都会收到有关内存泄漏的提示。请注意,只有420MB(如您所述)可能已提交,但更多页面可能已保留,这些页面仍会计入应用程序的2GB虚拟空间限制。运行DirectShow图可能已经用完了这个空间的剩余部分。
因此,DirectShow本身很可能不是错误的原因,而是恰好揭示了应用程序中的现有错误。
以下是MSDN中可能与您相关的一些其他信息,特别是如果您在程序中先前创建了其他线程(Thread Stack Size):
每个新线程都会收到自己的堆栈空间,包括保留和初始提交的内存。保留的内存大小表示虚拟内存中的总堆栈分配。因此,保留大小限于虚拟地址范围。最初提交的页面在引用之前不使用物理内存; ...当线程退出时,堆栈被释放。如果线程被另一个线程终止,则不会释放它。
答案 1 :(得分:0)
在sysinternals-web-pages中,有许多视频涉及内存的使用方式和使用方式。也许这可以帮助你解决问题。
http://technet.microsoft.com/en-us/sysinternals/bb963887
http://player.microsoftpdc.com/Session/1689962d-dea2-48bd-80d8-96e954fa5329
http://player.microsoftpdc.com/Session/1c97b279-d7e3-4a3e-9a76-0dac23dfddb5
希望这会对你有所帮助。
答案 2 :(得分:0)
如果这是一个问题,我不完全清楚你的解释,但是对于大多数与DirectX相关的工具(我假设包括DirectShow),你需要确保所有相关的调用都发生在同一个线程上;换句话说,如果您在给定线程上设置DirectShow,请使用同一个线程对它进行所有调用。自从我使用DirectShow以来已经很长时间了,所以我不是100%肯定这是适用的,但它确实解决了D3D的许多问题,这是一种密切相关的技术。
FWIW。