2011-01-20 35 views
3

我遇到了一些将DirectShow图形集成到现有应用程序中的奇怪问题。DirectShow - 无法创建新线程

有两件事情首先要涵盖:

  1. 该图的目的是从具有暴露的DirectShow的接口采集卡带来的原始视频。该图通过VMR9正确显示视频,并通过ISampleGrabber(DirectShow示例)将原始帧暴露给某些算法。
  2. 该图已经在单个项目中成功构建和运行。视频显示正常,一切都很开心。

现在的问题出现在我将它集成到现有的代码中。从应用程序的初始化开始,我首先创建并启动图形,在无窗口模式下运行VMR9。后来在初始化过程中,我通过_beginthreadex创建了几个工作线程。对_beginthreadex的调用失败,返回代码为12(内存不足),当且仅当图形已经建立并运行时。

现在明显的答案是我内存不足或者其他一些资源。但是,在线程尝试启动的时候,我正在使用〜2GB的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

使用CreateTh阅读而不是__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

是否有可能在视频RAM上运行? – StefanE

回答

2

首先,我建议你用CreateThread然后更换_beginthreadex使用GetLastError来确定任何错误的原因,通常比由_beginthreadex设置的CRT错误代码更具体。让我知道你通过这样做的观察,我会更新我的答案。

此外,您可以发布导致线程创建失败的部分(DirectShow)代码,以及创建线程的代码行吗?

更新:无论我能找到关于具体错误的信息,您都会对可能的内存泄漏提示一些提示。请注意,只有420MB(如你所提到的)可能是承诺,但更多的页面可能已经保留,这些页面仍然计入您的应用程序的2GB虚拟空间限制。运行DirectShow图表可能已经用完了这个空间的剩余部分。

因此,很有可能DirectShow本身不是错误的原因,而是碰巧揭示了应用程序中存在的错误。

下面是从MSDN,可能是与你有关的一些额外的信息,特别是如果你在你的程序(Thread Stack Size)创建的其它线程更早:

每一个新的线程接收由双方保留和自己的堆栈空间最初承诺的记忆。保留的内存大小表示虚拟内存中的总堆栈分配。因此,保留的大小被限制在虚拟地址范围内。最初提交的页面在引用之前不会使用物理内存; ...当线程退出时释放堆栈。如果线程被另一个线程终止,它不会被释放。

+0

添加了Directshow代码,只要我测试了它就会添加有关CreateThread的注释。 – DeusAduro

+0

我已经添加了CreateThread测试的结果。此外,DirectShow图形还处于主应用程序的单独DLL中。我不确定这是否会增加这些问题,但我认为这值得一提。 – DeusAduro

0

如果这是一个问题,我不完全清楚你的解释,但对于大多数与DirectX相关的工具(我认为它包括DirectShow),你需要确保所有相关的调用都发生在同一个线程中;换句话说,如果您在给定线程上设置了DirectShow,请使用同一个线程对其进行所有调用。自从我使用DirectShow以来,已经有很长一段时间了,所以我并不是100%肯定的,但它肯定解决了D3D这个密切相关的技术的许多问题。

FWIW。

+0

嗨,我相信这将适用于DirectShow,但我已经这样做了(所有DS调用在它创建的同一个线程中)。感谢您的输入。 – DeusAduro

相关问题