Date

texture3DサンプルはWindows SDKに付属しているサンプルコードである。DirectShowとDirect3D9を使ってテクスチャに画像をレンダリングして表示する。

またアプリケーション内部にDirectShowフィルタを記述する方法のサンプルでもある。この場合regsvr32を用いてレジストリへ登録する必要がない。

フィルタグラフの構築はDShowTextures.cppのInitDShowTextureRenderer関数で行っている。そこでは次のような順で処理をしている。

  1. テクスチャにレンダリングするフィルタCTextureRendererクラスのインスタンスを作成する。
  2. CTextureRendererをフィルタグラフへ追加する。
  3. AddSourceFilterでソースフィルタを追加する。
  4. FindPinでソースフィルタの出力ピンを取得する。
  5. ソースフィルタの出力ピンを引数としてRenderでピンの接続する。

このときソースフィルタの出力ピンの取得に失敗することがある。それはFindPinの引数にピンの名前として「Video」で固定しているためである。もう少し汎用的に書き換えてみよう。

  1. AddSourceFilterFindPinRenderメソッドをコメントアウトする。
  2. 代わりにRenderFileメソッドを呼び出す。

RenderFileメソッドは、引数で指定したファイルのソースフィルタを追加し、既定のレンダラーフィルタでレンダリングするためのフィルタグラフを構築してくれるが、フィルタグラフ上に未接続のフィルタが置かれている場合、そのフィルタを使おうとする。

つまりCTextureRendererフィルタをAddfilterしておけば、ソースフィルタからそれに向かって接続してくれるというわけだ。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
//-----------------------------------------------------------------------------
// InitDShowTextureRenderer : Create DirectShow filter graph and run the graph
//-----------------------------------------------------------------------------
HRESULT InitDShowTextureRenderer()
{
    HRESULT hr = S_OK;
    SmartPtr<IBaseFilter>    pFSrc;          // Source Filter
    SmartPtr<IPin>           pFSrcPinOut;    // Source Filter Output Pin
    CTextureRenderer        *pCTR=0;        // DirectShow Texture renderer
    // Create the filter graph
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&g_pGB);
    if (FAILED(hr))
        return E_FAIL;
#ifdef REGISTER_FILTERGRAPH
    // Register the graph in the Running Object Table (for debug purposes)
    AddToROT(g_pGB);
#endif
    // Create the Texture Renderer object
    pCTR = new CTextureRenderer(NULL, &hr);
    if (FAILED(hr) || !pCTR)
    {
        delete pCTR;
        Msg(TEXT("Could not create texture renderer object!  hr=0x%x"), hr);
        return E_FAIL;
    }
    // Get a pointer to the IBaseFilter on the TextureRenderer, add it to graph
    g_pRenderer = pCTR;
    if (FAILED(hr = g_pGB->AddFilter(g_pRenderer, L"TEXTURERENDERER")))
    {
        Msg(TEXT("Could not add renderer filter to graph!  hr=0x%x"), hr);
        return hr;
    }
    // Determine the file to load based on windows directory
    // Use the standard win32 API to do this.
    TCHAR strFileName[MAX_PATH] = {0};
    WCHAR wFileName[MAX_PATH];
    if (! GetClipFileName(strFileName))
    {
        DWORD dwDlgErr = CommDlgExtendedError();
        // Don't show output if user cancelled the selection (no dlg error)
        if (dwDlgErr)
        {
            Msg(TEXT("GetClipFileName Failed! Error=0x%x\r\n"), GetLastError());
        }
        return E_FAIL;
    }
    strFileName[MAX_PATH-1] = 0;  // NULL-terminate
    wFileName[MAX_PATH-1] = 0;    // NULL-terminate
    (void)StringCchCopyW(wFileName, NUMELMS(wFileName), strFileName);
    // Add the source filter to the graph.
    /*
    hr = g_pGB->AddSourceFilter (wFileName, L"SOURCE", &pFSrc);
    // If the media file was not found, inform the user.
    if (hr == VFW_E_NOT_FOUND)
    {
        Msg(TEXT("Could not add source filter to graph!  (hr==VFW_E_NOT_FOUND)\r\n\r\n")
            TEXT("This sample reads a media file from your windows directory.\r\n")
            TEXT("This file is missing from this machine."));
        return hr;
    }
    else if(FAILED(hr))
    {
        Msg(TEXT("Could not add source filter to graph!  hr=0x%x"), hr);
        return hr;
    }
    */
    /*
    if (FAILED(hr = pFSrc->FindPin(L"Generate Still Video", &pFSrcPinOut)))
    {
        Msg(TEXT("Could not find output pin!  hr=0x%x"), hr);
        return hr;
    }
    */
#ifdef NO_AUDIO_RENDERER
    // If no audio component is desired, directly connect the two video pins
    // instead of allowing the Filter Graph Manager to render all pins.
    CComPtr<IPin> pFTRPinIn;      // Texture Renderer Input Pin
    // Find the source's output pin and the renderer's input pin
    if (FAILED(hr = pFTR->FindPin(L"In", &pFTRPinIn)))
    {
        Msg(TEXT("Could not find input pin!  hr=0x%x"), hr);
        return hr;
    }
    // Connect these two filters
    if (FAILED(hr = g_pGB->Connect(pFSrcPinOut, pFTRPinIn)))
    {
        Msg(TEXT("Could not connect pins!  hr=0x%x"), hr);
        return hr;
    }
#else
    // Render the source filter's output pin.  The Filter Graph Manager
    // will connect the video stream to the loaded CTextureRenderer
    // and will load and connect an audio renderer (if needed).
    /*
    if (FAILED(hr = g_pGB->Render(pFSrcPinOut)))
    {
        Msg(TEXT("Could not render source output pin!  hr=0x%x"), hr);
        return hr;
    }
    */
    hr=g_pGB->RenderFile(wFileName,NULL);
#endif
    // Get the graph's media control, event & position interfaces
    g_pGB.QueryInterface(&g_pMC);
    g_pGB.QueryInterface(&g_pMP);
    g_pGB.QueryInterface(&g_pME);
/*以下省略*/

Comments

comments powered by Disqus