3

DirectShow グラフを既存のアプリケーションに統合する際に奇妙な問題が発生しています。

最初にカバーするいくつかのこと:

  1. グラフの目的は、公開された DirectShow インターフェイスを持つ FrameGrabber から生のビデオを取得することです。グラフは、VMR9 を介してビデオを表示する権利を取得し、生のフレームを ISampleGrabber を介していくつかのアルゴリズムに公開します (DirectShow の例)。
  2. グラフは、個々のプロジェクトで正常に作成および実行されました。ビデオは正常に表示され、すべてが満足しています。

これを既存のコードに統合するときに問題が発生します。アプリケーションの初期化から、まずグラフを作成して開始し、ウィンドウレス モードで 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);
4

3 に答える 3

2

まず、で置き換え_beginthreadexCreateThreadから、を使用GetLastErrorしてエラーの原因を特定することをお勧めします。これは、によって設定されたCRTエラーコードよりも具体的であることがよくあります_beginthreadex。これを行うことによってあなたが観察したことを私に知らせてください、そして私は私の答えを更新します。

また、スレッドの作成に失敗する(DirectShow)コードの部分と、スレッドを作成するコード行を投稿できますか?

更新:特定のエラーに関して私が見つけたものは何でも、メモリリークの可能性についてのヒントを得ています。(おっしゃるように)420MBのみがコミットされる可能性がありますが、さらに多くのページが予約されている可能性があり、これらのページはアプリケーションの2GBの仮想スペース制限にカウントされることに注意してください。DirectShowグラフを実行すると、このスペースに残っているものがすべて使い果たされた可能性があります。

したがって、DirectShow自体がエラーの原因ではなく、アプリケーションの既存のエラーを明らかにした可能性があります。

特にプログラムの前半で他のスレッドを作成した場合(スレッドスタックサイズ) 、MSDNからの追加情報が関連している可能性があります。

新しいスレッドはそれぞれ、予約済みメモリと最初にコミットされたメモリの両方で構成される独自のスタックスペースを受け取ります。予約済みメモリサイズは、仮想メモリ内の合計スタック割り当てを表します。そのため、予約サイズは仮想アドレス範囲に制限されます。最初にコミットされたページは、参照されるまで物理メモリを利用しません。...スタックは、スレッドが終了すると解放されます。スレッドが別のスレッドで終了している場合は解放されません。

于 2011-01-24T17:34:22.493 に答える
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

これがお役に立てば幸いです。

于 2011-01-25T16:25:29.703 に答える
0

これが問題であるかどうかの説明からは完全にはわかりませんが、ほとんどの DirectX 関連ツール (DirectShow が含まれていると思います) では、関連するすべての呼び出しが同じスレッドで発生することを確認する必要があります。つまり、特定のスレッドで DirectShow をセットアップする場合、その同じスレッドを使用してすべての呼び出しを行います。DirectShow を使用してから長い時間が経っているので、これが当てはまると 100% 確信しているわけではありませんが、密接に関連するテクノロジである D3D の多くの問題を確実に解決します。

ふぅ。

于 2011-01-31T17:05:54.723 に答える