home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / Players / Texture3D / DShowTextures.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  13.1 KB  |  384 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DShowTextures.cpp
  3. //
  4. // Desc: DirectShow sample code - adds support for DirectShow videos playing 
  5. //       on a DirectX 8.0 texture surface. Turns the D3D texture tutorial into 
  6. //       a recreation of the VideoTex sample from previous versions of DirectX.
  7. //
  8. // Copyright (c) 2000-2001 Microsoft Corporation.  All rights reserved.
  9. //-----------------------------------------------------------------------------
  10. #include "Textures.h"
  11. #include "DShowTextures.h"
  12. #include "DXUtil.h"
  13.  
  14. //-----------------------------------------------------------------------------
  15. // Global Constants
  16. //-----------------------------------------------------------------------------
  17. #define SOURCE_FILE     TEXT("skiing.avi")
  18.  
  19. // An application can advertise the existence of its filter graph
  20. // by registering the graph with a global Running Object Table (ROT).
  21. // The GraphEdit application can detect and remotely view the running
  22. // filter graph, allowing you to 'spy' on the graph with GraphEdit.
  23. //
  24. // To enable registration in this sample, define REGISTER_FILTERGRAPH.
  25. //
  26. #define REGISTER_FILTERGRAPH
  27.  
  28. //-----------------------------------------------------------------------------
  29. // Global DirectShow pointers
  30. //-----------------------------------------------------------------------------
  31. CComPtr<IGraphBuilder>  g_pGB;          // GraphBuilder
  32. CComPtr<IMediaControl>  g_pMC;          // Media Control
  33. CComPtr<IMediaPosition> g_pMP;          // Media Postion
  34. CComPtr<IMediaEvent>    g_pME;          // Media Event
  35.  
  36. D3DFORMAT               g_TextureFormat; // Texture format
  37.  
  38. //-----------------------------------------------------------------------------
  39. // InitDShowTextureRenderer : Create DirectShow filter graph and run the graph
  40. //-----------------------------------------------------------------------------
  41. HRESULT InitDShowTextureRenderer(LPDIRECT3DTEXTURE8 pTexture)
  42. {
  43.     HRESULT hr = S_OK;
  44.     CComPtr<IBaseFilter>    pFTR;           // Texture Renderer Filter
  45.     CComPtr<IPin>           pFTRPinIn;      // Texture Renderer Input Pin
  46.     CComPtr<IBaseFilter>    pFSrc;          // Source Filter
  47.     CComPtr<IPin>           pFSrcPinOut;    // Source Filter Output Pin   
  48.     CTextureRenderer        *pCTR;          // DShow Texture renderer
  49.     
  50.     // Create the filter graph
  51.     if (FAILED(g_pGB.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC)))
  52.         return E_FAIL;
  53.  
  54. #ifdef REGISTER_FILTERGRAPH
  55.     // Register the graph in the Running Object Table (for debug purposes)
  56.     AddToROT(g_pGB);
  57. #endif
  58.     
  59.     // Create the Texture Renderer object
  60.     pCTR = new CTextureRenderer(NULL, &hr);
  61.     if (FAILED(hr))                                      
  62.     {
  63.         Msg(TEXT("Could not create texture renderer object!  hr=0x%x"), hr);
  64.         return E_FAIL;
  65.     }
  66.     
  67.     // Get a pointer to the IBaseFilter on the TextureRenderer, add it to graph
  68.     pFTR = pCTR;
  69.     if (FAILED(hr = g_pGB->AddFilter(pFTR, L"TEXTURERENDERER")))
  70.     {
  71.         Msg(TEXT("Could not add renderer filter to graph!  hr=0x%x"), hr);
  72.         return hr;
  73.     }
  74.     
  75.     // Determine the file to load based on DirectX Media path (from SDK)
  76.     // Use a helper function included in DXUtils.cpp
  77.     TCHAR strFileName[MAX_PATH];
  78.     WCHAR wFileName[MAX_PATH];
  79.     lstrcpy( strFileName, DXUtil_GetDXSDKMediaPath() );
  80.     lstrcat( strFileName, SOURCE_FILE );
  81.  
  82.     #ifndef UNICODE
  83.         MultiByteToWideChar(CP_ACP, 0, strFileName, -1, wFileName, MAX_PATH);
  84.     #else
  85.         lstrcpy(wFileName, strFileName);
  86.     #endif
  87.  
  88.     // Add the source filter
  89.     if (FAILED(hr = g_pGB->AddSourceFilter (wFileName, L"SOURCE", &pFSrc)))
  90.     {
  91.         Msg(TEXT("Could not create source filter to graph!  hr=0x%x"), hr);
  92.         return hr;
  93.     }
  94.  
  95.     // Find the source's output pin and the renderer's input pin
  96.     if (FAILED(hr = pFTR->FindPin(L"In", &pFTRPinIn)))
  97.     {
  98.         Msg(TEXT("Could not find input pin!  hr=0x%x"), hr);
  99.         return hr;
  100.     }
  101.  
  102.     if (FAILED(hr = pFSrc->FindPin(L"Output", &pFSrcPinOut)))
  103.     {
  104.         Msg(TEXT("Could not find output pin!  hr=0x%x"), hr);
  105.         return hr;
  106.     }
  107.     
  108.     // Connect these two filters
  109.     if (FAILED(hr = g_pGB->Connect(pFSrcPinOut, pFTRPinIn)))
  110.     {
  111.         Msg(TEXT("Could not connect pins!  hr=0x%x"), hr);
  112.         return hr;
  113.     }
  114.    
  115.     // Get the graph's media control, event & position interfaces
  116.     g_pGB.QueryInterface(&g_pMC);
  117.     g_pGB.QueryInterface(&g_pMP);
  118.     g_pGB.QueryInterface(&g_pME);
  119.     
  120.     // Start the graph running;
  121.     if (FAILED(hr = g_pMC->Run()))
  122.     {
  123.         Msg(TEXT("Could not run the DirectShow graph!  hr=0x%x"), hr);
  124.         return hr;
  125.     }
  126.     return S_OK;
  127. }
  128.  
  129.  
  130. //-----------------------------------------------------------------------------
  131. // CheckMovieStatus: If the movie has ended, rewind to beginning
  132. //-----------------------------------------------------------------------------
  133. void CheckMovieStatus(void)
  134. {
  135.     long lEventCode;
  136.     long lParam1;
  137.     long lParam2;
  138.     HRESULT hr;
  139.  
  140.     // Check for completion events
  141.     hr = g_pME->GetEvent(&lEventCode, (LONG_PTR *) &lParam1, (LONG_PTR *) &lParam2, 0);
  142.     if (SUCCEEDED(hr))
  143.     {
  144.         if (EC_COMPLETE == lEventCode) 
  145.         {
  146.             hr = g_pMP->put_CurrentPosition(0);
  147.         }
  148.  
  149.         // Free any memory associated with this event
  150.         hr = g_pME->FreeEventParams(lEventCode, lParam1, lParam2);
  151.     }
  152. }
  153.  
  154.  
  155. //-----------------------------------------------------------------------------
  156. // CleanupDShow
  157. //-----------------------------------------------------------------------------
  158. void CleanupDShow(void)
  159. {
  160. #ifdef REGISTER_FILTERGRAPH
  161.     // Pull graph from Running Object Table (Debug)
  162.     RemoveFromROT();
  163. #endif
  164.  
  165.     // Shut down the graph
  166.     if (!(!g_pMC)) g_pMC->Stop();
  167.     if (!(!g_pMC)) g_pMC.Release();
  168.     if (!(!g_pME)) g_pME.Release();
  169.     if (!(!g_pMP)) g_pMP.Release();
  170.     if (!(!g_pGB)) g_pGB.Release();
  171. }
  172.     
  173.  
  174. //-----------------------------------------------------------------------------
  175. // CTextureRenderer constructor
  176. //-----------------------------------------------------------------------------
  177. CTextureRenderer::CTextureRenderer( LPUNKNOWN pUnk, HRESULT *phr )
  178.                                    : CBaseVideoRenderer(__uuidof(CLSID_TextureRenderer), 
  179.                                    NAME("Texture Renderer"), pUnk, phr)
  180. {
  181.     // Store and AddRef the texture for our use.
  182.     *phr = S_OK;
  183. }
  184.  
  185.  
  186. //-----------------------------------------------------------------------------
  187. // CTextureRenderer destructor
  188. //-----------------------------------------------------------------------------
  189. CTextureRenderer::~CTextureRenderer()
  190. {
  191.     // Do nothing
  192. }
  193.  
  194.  
  195. //-----------------------------------------------------------------------------
  196. // CheckMediaType: This method forces the graph to give us an R8G8B8 video
  197. // type, making our copy to texture memory trivial.
  198. //-----------------------------------------------------------------------------
  199. HRESULT CTextureRenderer::CheckMediaType(const CMediaType *pmt)
  200. {
  201.     HRESULT   hr = E_FAIL;
  202.     VIDEOINFO *pvi;
  203.     
  204.     // Reject the connection if this is not a video type
  205.     if( *pmt->FormatType() != FORMAT_VideoInfo ) {
  206.         return E_INVALIDARG;
  207.     }
  208.     
  209.     // Only accept RGB24
  210.     pvi = (VIDEOINFO *)pmt->Format();
  211.     if(IsEqualGUID( *pmt->Type(),    MEDIATYPE_Video)  &&
  212.        IsEqualGUID( *pmt->Subtype(), MEDIASUBTYPE_RGB24))
  213.     {
  214.         hr = S_OK;
  215.     }
  216.     
  217.     return hr;
  218. }
  219.  
  220.  
  221. //-----------------------------------------------------------------------------
  222. // SetMediaType: Graph connection has been made. 
  223. //-----------------------------------------------------------------------------
  224. HRESULT CTextureRenderer::SetMediaType(const CMediaType *pmt)
  225. {
  226.     HRESULT hr;
  227.  
  228.     // Retrive the size of this media type
  229.     VIDEOINFO *pviBmp;                      // Bitmap info header
  230.     pviBmp = (VIDEOINFO *)pmt->Format();
  231.     m_lVidWidth  = pviBmp->bmiHeader.biWidth;
  232.     m_lVidHeight = abs(pviBmp->bmiHeader.biHeight);
  233.     m_lVidPitch = (m_lVidWidth * 3 + 3) & ~(3); // We are forcing RGB24
  234.  
  235.     // Create the texture that maps to this media type
  236.     if( FAILED( hr = D3DXCreateTexture(g_pd3dDevice,
  237.                     m_lVidWidth, m_lVidHeight,
  238.                     1, 0, 
  239.                     D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &g_pTexture ) ) )
  240.     {
  241.         Msg(TEXT("Could not create the D3DX texture!  hr=0x%x"), hr);
  242.         return hr;
  243.     }
  244.  
  245.     // D3DXCreateTexture can silently change the parameters on us
  246.     D3DSURFACE_DESC ddsd;
  247.     if ( FAILED( hr = g_pTexture->GetLevelDesc( 0, &ddsd ) ) ) {
  248.         Msg(TEXT("Could not get level Description of D3DX texture! hr = 0x%x"), hr);
  249.         return hr;
  250.     }
  251.     g_TextureFormat = ddsd.Format;
  252.     if (g_TextureFormat != D3DFMT_A8R8G8B8 &&
  253.         g_TextureFormat != D3DFMT_A1R5G5B5) {
  254.         Msg(TEXT("Texture is format we can't handle! Format = 0x%x"), g_TextureFormat);
  255.         return VFW_E_TYPE_NOT_ACCEPTED;
  256.     }
  257.  
  258.     return S_OK;
  259. }
  260.  
  261.  
  262. //-----------------------------------------------------------------------------
  263. // DoRenderSample: A sample has been delivered. Copy it to the texture.
  264. //-----------------------------------------------------------------------------
  265. HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
  266. {
  267.     BYTE  *pBmpBuffer, *pTxtBuffer;     // Bitmap buffer, texture buffer
  268.     LONG  lTxtPitch;                // Pitch of bitmap, texture
  269.     
  270.     // Get the video bitmap buffer
  271.     pSample->GetPointer( &pBmpBuffer );
  272.  
  273.     // Lock the Texture
  274.     D3DLOCKED_RECT d3dlr;
  275.     if (FAILED(g_pTexture->LockRect(0, &d3dlr, 0, 0)))
  276.         return E_FAIL;
  277.     
  278.     // Get the texture buffer & pitch
  279.     pTxtBuffer = static_cast<byte *>(d3dlr.pBits);
  280.     lTxtPitch = d3dlr.Pitch;
  281.     
  282.     // Copy the bits    
  283.     // OPTIMIZATION OPPORTUNITY: Use a video and texture
  284.     // format that allows a simpler copy than this one.
  285.     if (g_TextureFormat == D3DFMT_A8R8G8B8) {
  286.         for(int y = 0; y < m_lVidHeight; y++ ) {
  287.             BYTE *pBmpBufferOld = pBmpBuffer;
  288.             BYTE *pTxtBufferOld = pTxtBuffer;   
  289.             for (int x = 0; x < m_lVidWidth; x++) {
  290.                 pTxtBuffer[0] = pBmpBuffer[0];
  291.                 pTxtBuffer[1] = pBmpBuffer[1];
  292.                 pTxtBuffer[2] = pBmpBuffer[2];
  293.                 pTxtBuffer[3] = 0xff;
  294.                 pTxtBuffer += 4;
  295.                 pBmpBuffer += 3;
  296.             }
  297.             pBmpBuffer = pBmpBufferOld + m_lVidPitch;
  298.             pTxtBuffer = pTxtBufferOld + lTxtPitch;
  299.         }
  300.     }
  301.  
  302.     if (g_TextureFormat == D3DFMT_A1R5G5B5) {
  303.         for(int y = 0; y < m_lVidHeight; y++ ) {
  304.             BYTE *pBmpBufferOld = pBmpBuffer;
  305.             BYTE *pTxtBufferOld = pTxtBuffer;   
  306.             for (int x = 0; x < m_lVidWidth; x++) {
  307.                 *(WORD *)pTxtBuffer = (WORD)
  308.                     (0x8000 +
  309.                     ((pBmpBuffer[2] & 0xF8) << 7) +
  310.                     ((pBmpBuffer[1] & 0xF8) << 2) +
  311.                     (pBmpBuffer[0] >> 3));
  312.                 pTxtBuffer += 2;
  313.                 pBmpBuffer += 3;
  314.             }
  315.             pBmpBuffer = pBmpBufferOld + m_lVidPitch;
  316.             pTxtBuffer = pTxtBufferOld + lTxtPitch;
  317.         }
  318.     }
  319.  
  320.         
  321.     // Unlock the Texture
  322.     if (FAILED(g_pTexture->UnlockRect(0)))
  323.         return E_FAIL;
  324.     
  325.     return S_OK;
  326. }
  327.  
  328.  
  329. #ifdef REGISTER_FILTERGRAPH
  330.  
  331. //-----------------------------------------------------------------------------
  332. // Running Object Table functions: Used to debug. By registering the graph
  333. // in the running object table, GraphEdit is able to connect to the running
  334. // graph. This code should be removed before the application is shipped in
  335. // order to avoid third parties from spying on your graph.
  336. //-----------------------------------------------------------------------------
  337. DWORD dwROTReg = 0xfedcba98;
  338.  
  339. HRESULT AddToROT(IUnknown *pUnkGraph) 
  340. {
  341.     IMoniker * pmk;
  342.     IRunningObjectTable *pirot;
  343.     if (FAILED(GetRunningObjectTable(0, &pirot))) {
  344.         return E_FAIL;
  345.     }
  346.     WCHAR wsz[256];
  347.     wsprintfW(wsz, L"FilterGraph %08x  pid %08x", (DWORD_PTR) 0, GetCurrentProcessId());
  348.     HRESULT hr = CreateItemMoniker(L"!", wsz, &pmk);
  349.     if (SUCCEEDED(hr)) {
  350.         hr = pirot->Register(0, pUnkGraph, pmk, &dwROTReg);
  351.         pmk->Release();
  352.     }
  353.     pirot->Release();
  354.     return hr;
  355. }
  356.  
  357. void RemoveFromROT(void)
  358. {
  359.     IRunningObjectTable *pirot;
  360.     if (SUCCEEDED(GetRunningObjectTable(0, &pirot))) {
  361.         pirot->Revoke(dwROTReg);
  362.         pirot->Release();
  363.     }
  364. }
  365.  
  366. #endif
  367.  
  368.  
  369. //-----------------------------------------------------------------------------
  370. // Msg: Display an error message box if needed
  371. //-----------------------------------------------------------------------------
  372. void Msg(TCHAR *szFormat, ...)
  373. {
  374.     TCHAR szBuffer[512];
  375.  
  376.     va_list pArgs;
  377.     va_start(pArgs, szFormat);
  378.     _vstprintf(szBuffer, szFormat, pArgs);
  379.     va_end(pArgs);
  380.  
  381.     MessageBox(NULL, szBuffer, TEXT("DirectShow Texture3D Sample"), 
  382.                MB_OK | MB_ICONERROR);
  383. }
  384.