DirectShow グラフを既存のアプリケーションに統合する際に奇妙な問題が発生しています。
最初にカバーするいくつかのこと:
- グラフの目的は、公開された DirectShow インターフェイスを持つ FrameGrabber から生のビデオを取得することです。グラフは、VMR9 を介してビデオを表示する権利を取得し、生のフレームを ISampleGrabber を介していくつかのアルゴリズムに公開します (DirectShow の例)。
- グラフは、個々のプロジェクトで正常に作成および実行されました。ビデオは正常に表示され、すべてが満足しています。
これを既存のコードに統合するときに問題が発生します。アプリケーションの初期化から、まずグラフを作成して開始し、ウィンドウレス モードで VMR9 を実行します。初期化の後半で、_beginthreadex を介していくつかのワーカー スレッドを作成します。_beginthreadex の呼び出しは、グラフが作成されて実行された場合にのみ、戻りコード 12 (メモリ不足) で失敗します。
明らかな答えは、メモリが不足しているか、他のリソースが不足しているということです。ただし、スレッドが開始しようとしている時点で、2 GB のシステム メモリのうち約 420 MB を使用しています。スレッド スタック サイズは明示的に 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
__beginthreadex の代わりに CreateThread を使用してコードをテストしました。スレッドの起動に失敗した後、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);