| 11 | cycrow | 1 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 2 | // File: DShowTextures.cpp
 | 
        
           |  |  | 3 | //
 | 
        
           |  |  | 4 | // Desc: DirectShow sample code - adds support for DirectShow videos playing
 | 
        
           |  |  | 5 | //       on a DirectX 9.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) Microsoft Corporation.  All rights reserved.
 | 
        
           |  |  | 9 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 10 |   | 
        
           |  |  | 11 | #include "Textures.h"
 | 
        
           |  |  | 12 | #include "DShowTextures.h"
 | 
        
           |  |  | 13 | #include "DXUtil.h"
 | 
        
           |  |  | 14 |   | 
        
           |  |  | 15 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 16 | // Global Constants
 | 
        
           |  |  | 17 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 18 |   | 
        
           |  |  | 19 | // Define this if you want to render only the video component with no audio
 | 
        
           |  |  | 20 | //
 | 
        
           |  |  | 21 | //   #define NO_AUDIO_RENDERER
 | 
        
           |  |  | 22 |   | 
        
           |  |  | 23 | // An application can advertise the existence of its filter graph
 | 
        
           |  |  | 24 | // by registering the graph with a global Running Object Table (ROT).
 | 
        
           |  |  | 25 | // The GraphEdit application can detect and remotely view the running
 | 
        
           |  |  | 26 | // filter graph, allowing you to 'spy' on the graph with GraphEdit.
 | 
        
           |  |  | 27 | //
 | 
        
           |  |  | 28 | // To enable registration in this sample, define REGISTER_FILTERGRAPH.
 | 
        
           |  |  | 29 | //
 | 
        
           |  |  | 30 | #define REGISTER_FILTERGRAPH
 | 
        
           |  |  | 31 |   | 
        
           |  |  | 32 | LPDIRECT3DDEVICE9       g_pd3dDevice; // Our rendering device
 | 
        
           |  |  | 33 | LPDIRECT3DTEXTURE9      g_pTexture;   // Our texture
 | 
        
           |  |  | 34 |   | 
        
           |  |  | 35 | // File filter for OpenFile dialog
 | 
        
           |  |  | 36 | #define FILE_FILTER_TEXT \
 | 
        
           |  |  | 37 |     TEXT("Video Files (*.avi; *.qt; *.mov; *.mpg; *.mpeg; *.m1v)\0*.avi; *.qt; *.mov; *.mpg; *.mpeg; *.m1v\0")\
 | 
        
           |  |  | 38 |     TEXT("Audio files (*.wav; *.mpa; *.mp2; *.mp3; *.au; *.aif; *.aiff; *.snd)\0*.wav; *.mpa; *.mp2; *.mp3; *.au; *.aif; *.aiff; *.snd\0")\
 | 
        
           |  |  | 39 |     TEXT("MIDI Files (*.mid, *.midi, *.rmi)\0*.mid; *.midi; *.rmi\0") \
 | 
        
           |  |  | 40 |     TEXT("Image Files (*.jpg, *.bmp, *.gif, *.tga)\0*.jpg; *.bmp; *.gif; *.tga\0") \
 | 
        
           |  |  | 41 |     TEXT("All Files (*.*)\0*.*;\0\0")
 | 
        
           |  |  | 42 |   | 
        
           |  |  | 43 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 44 | // Global DirectShow pointers
 | 
        
           |  |  | 45 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 46 | CComPtr<IGraphBuilder>  g_pGB;          // GraphBuilder
 | 
        
           |  |  | 47 | CComPtr<IMediaControl>  g_pMC;          // Media Control
 | 
        
           |  |  | 48 | CComPtr<IMediaPosition> g_pMP;          // Media Position
 | 
        
           |  |  | 49 | CComPtr<IMediaEvent>    g_pME;          // Media Event
 | 
        
           |  |  | 50 | CComPtr<IBaseFilter>    g_pRenderer;    // our custom renderer
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 | D3DFORMAT               g_TextureFormat; // Texture format
 | 
        
           |  |  | 53 |   | 
        
           |  |  | 54 | //extern HWND g_hWnd;
 | 
        
           |  |  | 55 |   | 
        
           |  |  | 56 | TCHAR g_achCopy[]     = TEXT("Bitwise copy of the sample");
 | 
        
           |  |  | 57 | TCHAR g_achOffscr[]   = TEXT("Using offscreen surfaces and StretchCopy()");
 | 
        
           |  |  | 58 | TCHAR g_achDynTextr[] = TEXT("Using Dynamic Textures");
 | 
        
           |  |  | 59 | TCHAR* g_pachRenderMethod = NULL;
 | 
        
           |  |  | 60 |   | 
        
           |  |  | 61 |   | 
        
           |  |  | 62 |   | 
        
           |  |  | 63 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 64 | // InitDShowTextureRenderer : Create DirectShow filter graph and run the graph
 | 
        
           |  |  | 65 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 66 | HRESULT InitDShowTextureRenderer( const char *szVideoFilename, LPDIRECT3DTEXTURE9 texture, LPDIRECT3DDEVICE9 device )
 | 
        
           |  |  | 67 | {
 | 
        
           |  |  | 68 | 	g_pTexture = texture;
 | 
        
           |  |  | 69 | 	g_pd3dDevice = device;
 | 
        
           |  |  | 70 |   | 
        
           |  |  | 71 |     HRESULT hr = S_OK;
 | 
        
           |  |  | 72 |   | 
        
           |  |  | 73 |     CComPtr<IBaseFilter>    pFSrc;          // Source Filter
 | 
        
           |  |  | 74 |     CComPtr<IPin>           pFSrcPinOut;    // Source Filter Output Pin
 | 
        
           |  |  | 75 |     CTextureRenderer        *pCTR=0;        // DirectShow Texture renderer
 | 
        
           |  |  | 76 |   | 
        
           |  |  | 77 |     // Create the filter graph
 | 
        
           |  |  | 78 |     if (FAILED(g_pGB.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC)))
 | 
        
           |  |  | 79 |         return E_FAIL;
 | 
        
           |  |  | 80 |   | 
        
           |  |  | 81 | #ifdef REGISTER_FILTERGRAPH
 | 
        
           |  |  | 82 |     // Register the graph in the Running Object Table (for debug purposes)
 | 
        
           |  |  | 83 |     AddToROT(g_pGB);
 | 
        
           |  |  | 84 | #endif
 | 
        
           |  |  | 85 |   | 
        
           |  |  | 86 |     // Create the Texture Renderer object
 | 
        
           |  |  | 87 |     pCTR = new CTextureRenderer(NULL, &hr);
 | 
        
           |  |  | 88 |     if (FAILED(hr) || !pCTR)
 | 
        
           |  |  | 89 |     {
 | 
        
           |  |  | 90 |         delete pCTR;
 | 
        
           |  |  | 91 |         Msg(TEXT("Could not create texture renderer object!  hr=0x%x"), hr);
 | 
        
           |  |  | 92 |         return E_FAIL;
 | 
        
           |  |  | 93 |     }
 | 
        
           |  |  | 94 |   | 
        
           |  |  | 95 |     // Get a pointer to the IBaseFilter on the TextureRenderer, add it to graph
 | 
        
           |  |  | 96 |     g_pRenderer = pCTR;
 | 
        
           |  |  | 97 |     if (FAILED(hr = g_pGB->AddFilter(g_pRenderer, L"TEXTURERENDERER")))
 | 
        
           |  |  | 98 |     {
 | 
        
           |  |  | 99 |         Msg(TEXT("Could not add renderer filter to graph!  hr=0x%x"), hr);
 | 
        
           |  |  | 100 |         return hr;
 | 
        
           |  |  | 101 |     }
 | 
        
           |  |  | 102 |   | 
        
           |  |  | 103 |     // Determine the file to load based on windows directory
 | 
        
           |  |  | 104 |     // Use the standard win32 API to do this.
 | 
        
           |  |  | 105 |     TCHAR strFileName[MAX_PATH] = {0};
 | 
        
           |  |  | 106 |     WCHAR wFileName[MAX_PATH];
 | 
        
           |  |  | 107 |   | 
        
           |  |  | 108 | 	lstrcpyn( strFileName, szVideoFilename, MAX_PATH - 1 );
 | 
        
           |  |  | 109 |   | 
        
           |  |  | 110 | 	/*
 | 
        
           |  |  | 111 |     if (! GetClipFileName(strFileName))
 | 
        
           |  |  | 112 |     {
 | 
        
           |  |  | 113 |         DWORD dwDlgErr = CommDlgExtendedError();
 | 
        
           |  |  | 114 |   | 
        
           |  |  | 115 |         // Don't show output if user cancelled the selection (no dlg error)
 | 
        
           |  |  | 116 |         if (dwDlgErr)
 | 
        
           |  |  | 117 |         {
 | 
        
           |  |  | 118 |             Msg(TEXT("GetClipFileName Failed! Error=0x%x\r\n"), GetLastError());
 | 
        
           |  |  | 119 |         }
 | 
        
           |  |  | 120 |         return E_FAIL;
 | 
        
           |  |  | 121 |     }
 | 
        
           |  |  | 122 | */
 | 
        
           |  |  | 123 |     strFileName[MAX_PATH-1] = 0;  // NULL-terminate
 | 
        
           |  |  | 124 |     wFileName[MAX_PATH-1] = 0;    // NULL-terminate
 | 
        
           |  |  | 125 |   | 
        
           |  |  | 126 |     USES_CONVERSION;
 | 
        
           |  |  | 127 |     (void)StringCchCopyW(wFileName, NUMELMS(wFileName), T2W(strFileName));
 | 
        
           |  |  | 128 |   | 
        
           |  |  | 129 | 	return hr;
 | 
        
           |  |  | 130 |   | 
        
           |  |  | 131 |     // Add the source filter to the graph.
 | 
        
           |  |  | 132 |     hr = g_pGB->AddSourceFilter (wFileName, L"SOURCE", &pFSrc);
 | 
        
           |  |  | 133 |   | 
        
           |  |  | 134 |     // If the media file was not found, inform the user.
 | 
        
           |  |  | 135 |     if (hr == VFW_E_NOT_FOUND)
 | 
        
           |  |  | 136 |     {
 | 
        
           |  |  | 137 |         Msg(TEXT("Could not add source filter to graph!  (hr==VFW_E_NOT_FOUND)\r\n\r\n")
 | 
        
           |  |  | 138 |             TEXT("This sample reads a media file from your windows directory.\r\n")
 | 
        
           |  |  | 139 |             TEXT("This file is missing from this machine."));
 | 
        
           |  |  | 140 |         return hr;
 | 
        
           |  |  | 141 |     }
 | 
        
           |  |  | 142 |     else if(FAILED(hr))
 | 
        
           |  |  | 143 |     {
 | 
        
           |  |  | 144 |         Msg(TEXT("Could not add source filter to graph!  hr=0x%x"), hr);
 | 
        
           |  |  | 145 |         return hr;
 | 
        
           |  |  | 146 |     }
 | 
        
           |  |  | 147 |   | 
        
           |  |  | 148 |     if (FAILED(hr = pFSrc->FindPin(L"Output", &pFSrcPinOut)))
 | 
        
           |  |  | 149 |     {
 | 
        
           |  |  | 150 |         Msg(TEXT("Could not find output pin!  hr=0x%x"), hr);
 | 
        
           |  |  | 151 |         return hr;
 | 
        
           |  |  | 152 |     }
 | 
        
           |  |  | 153 |   | 
        
           |  |  | 154 |     // Render the source filter's output pin.  The Filter Graph Manager
 | 
        
           |  |  | 155 |     // will connect the video stream to the loaded CTextureRenderer
 | 
        
           |  |  | 156 |     // and will load and connect an audio renderer (if needed).
 | 
        
           |  |  | 157 | /*
 | 
        
           |  |  | 158 |     if (FAILED(hr = g_pGB->Render(pFSrcPinOut)))
 | 
        
           |  |  | 159 |     {
 | 
        
           |  |  | 160 |         Msg(TEXT("Could not render source output pin!  hr=0x%x"), hr);
 | 
        
           |  |  | 161 |         return hr;
 | 
        
           |  |  | 162 |     }
 | 
        
           |  |  | 163 | */
 | 
        
           |  |  | 164 |     // Get the graph's media control, event & position interfaces
 | 
        
           |  |  | 165 |     g_pGB.QueryInterface(&g_pMC);
 | 
        
           |  |  | 166 |     g_pGB.QueryInterface(&g_pMP);
 | 
        
           |  |  | 167 |     g_pGB.QueryInterface(&g_pME);
 | 
        
           |  |  | 168 |   | 
        
           |  |  | 169 | 	/*
 | 
        
           |  |  | 170 |     // Start the graph running;
 | 
        
           |  |  | 171 |     if (FAILED(hr = g_pMC->Run()))
 | 
        
           |  |  | 172 |     {
 | 
        
           |  |  | 173 |         Msg(TEXT("Could not run the DirectShow graph!  hr=0x%x"), hr);
 | 
        
           |  |  | 174 |         return hr;
 | 
        
           |  |  | 175 |     }
 | 
        
           |  |  | 176 | */
 | 
        
           |  |  | 177 |   | 
        
           |  |  | 178 |     return S_OK;
 | 
        
           |  |  | 179 | }
 | 
        
           |  |  | 180 |   | 
        
           |  |  | 181 |   | 
        
           |  |  | 182 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 183 | // CheckMovieStatus: If the movie has ended, rewind to beginning
 | 
        
           |  |  | 184 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 185 | void CheckMovieStatus(void)
 | 
        
           |  |  | 186 | {
 | 
        
           |  |  | 187 |     long lEventCode;
 | 
        
           |  |  | 188 |     LONG_PTR lParam1, lParam2;
 | 
        
           |  |  | 189 |     HRESULT hr;
 | 
        
           |  |  | 190 |   | 
        
           |  |  | 191 |     if (!g_pME)
 | 
        
           |  |  | 192 |         return;
 | 
        
           |  |  | 193 |   | 
        
           |  |  | 194 |     // Check for completion events
 | 
        
           |  |  | 195 |     hr = g_pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
 | 
        
           |  |  | 196 |     if (SUCCEEDED(hr))
 | 
        
           |  |  | 197 |     {
 | 
        
           |  |  | 198 |         // If we have reached the end of the media file, reset to beginning
 | 
        
           |  |  | 199 |         if (EC_COMPLETE == lEventCode)
 | 
        
           |  |  | 200 |         {
 | 
        
           |  |  | 201 |             hr = g_pMP->put_CurrentPosition(0);
 | 
        
           |  |  | 202 |         }
 | 
        
           |  |  | 203 |   | 
        
           |  |  | 204 |         // Free any memory associated with this event
 | 
        
           |  |  | 205 |         hr = g_pME->FreeEventParams(lEventCode, lParam1, lParam2);
 | 
        
           |  |  | 206 |     }
 | 
        
           |  |  | 207 | }
 | 
        
           |  |  | 208 |   | 
        
           |  |  | 209 |   | 
        
           |  |  | 210 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 211 | // CleanupDShow
 | 
        
           |  |  | 212 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 213 | void CleanupDShow(void)
 | 
        
           |  |  | 214 | {
 | 
        
           |  |  | 215 | #ifdef REGISTER_FILTERGRAPH
 | 
        
           |  |  | 216 |     // Pull graph from Running Object Table (Debug)
 | 
        
           |  |  | 217 |     RemoveFromROT();
 | 
        
           |  |  | 218 | #endif
 | 
        
           |  |  | 219 |   | 
        
           |  |  | 220 |     // Shut down the graph
 | 
        
           |  |  | 221 |     if (!(!g_pMC)) g_pMC->Stop();
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |     if (!(!g_pMC)) g_pMC.Release();
 | 
        
           |  |  | 224 |     if (!(!g_pME)) g_pME.Release();
 | 
        
           |  |  | 225 |     if (!(!g_pMP)) g_pMP.Release();
 | 
        
           |  |  | 226 |     if (!(!g_pGB)) g_pGB.Release();
 | 
        
           |  |  | 227 |     if (!(!g_pRenderer)) g_pRenderer.Release();
 | 
        
           |  |  | 228 | }
 | 
        
           |  |  | 229 |   | 
        
           |  |  | 230 |   | 
        
           |  |  | 231 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 232 | // CTextureRenderer constructor
 | 
        
           |  |  | 233 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 234 | CTextureRenderer::CTextureRenderer( LPUNKNOWN pUnk, HRESULT *phr )
 | 
        
           |  |  | 235 |                                   : CBaseVideoRenderer(__uuidof(CLSID_TextureRenderer),
 | 
        
           |  |  | 236 |                                     NAME("Texture Renderer"), pUnk, phr),
 | 
        
           |  |  | 237 |                                     m_bUseDynamicTextures(FALSE)
 | 
        
           |  |  | 238 | {
 | 
        
           |  |  | 239 |     // Store and AddRef the texture for our use.
 | 
        
           |  |  | 240 |     ASSERT(phr);
 | 
        
           |  |  | 241 |     if (phr)
 | 
        
           |  |  | 242 |         *phr = S_OK;
 | 
        
           |  |  | 243 | }
 | 
        
           |  |  | 244 |   | 
        
           |  |  | 245 |   | 
        
           |  |  | 246 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 247 | // CTextureRenderer destructor
 | 
        
           |  |  | 248 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 249 | CTextureRenderer::~CTextureRenderer()
 | 
        
           |  |  | 250 | {
 | 
        
           |  |  | 251 |     // Do nothing
 | 
        
           |  |  | 252 | }
 | 
        
           |  |  | 253 |   | 
        
           |  |  | 254 |   | 
        
           |  |  | 255 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 256 | // CheckMediaType: This method forces the graph to give us an R8G8B8 video
 | 
        
           |  |  | 257 | // type, making our copy to texture memory trivial.
 | 
        
           |  |  | 258 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 259 | HRESULT CTextureRenderer::CheckMediaType(const CMediaType *pmt)
 | 
        
           |  |  | 260 | {
 | 
        
           |  |  | 261 |     HRESULT   hr = E_FAIL;
 | 
        
           |  |  | 262 |     VIDEOINFO *pvi=0;
 | 
        
           |  |  | 263 |   | 
        
           |  |  | 264 |     CheckPointer(pmt,E_POINTER);
 | 
        
           |  |  | 265 |   | 
        
           |  |  | 266 |     // Reject the connection if this is not a video type
 | 
        
           |  |  | 267 |     if( *pmt->FormatType() != FORMAT_VideoInfo ) {
 | 
        
           |  |  | 268 |         return E_INVALIDARG;
 | 
        
           |  |  | 269 |     }
 | 
        
           |  |  | 270 |   | 
        
           |  |  | 271 |     // Only accept RGB24 video
 | 
        
           |  |  | 272 |     pvi = (VIDEOINFO *)pmt->Format();
 | 
        
           |  |  | 273 |   | 
        
           |  |  | 274 |     if(IsEqualGUID( *pmt->Type(),    MEDIATYPE_Video)  &&
 | 
        
           |  |  | 275 |        IsEqualGUID( *pmt->Subtype(), MEDIASUBTYPE_RGB24))
 | 
        
           |  |  | 276 |     {
 | 
        
           |  |  | 277 |         hr = S_OK;
 | 
        
           |  |  | 278 |     }
 | 
        
           |  |  | 279 |   | 
        
           |  |  | 280 |     return hr;
 | 
        
           |  |  | 281 | }
 | 
        
           |  |  | 282 |   | 
        
           |  |  | 283 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 284 | // SetMediaType: Graph connection has been made.
 | 
        
           |  |  | 285 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 286 | HRESULT CTextureRenderer::SetMediaType(const CMediaType *pmt)
 | 
        
           |  |  | 287 | {
 | 
        
           |  |  | 288 |     HRESULT hr;
 | 
        
           |  |  | 289 |   | 
        
           |  |  | 290 |     UINT uintWidth = 2;
 | 
        
           |  |  | 291 |     UINT uintHeight = 2;
 | 
        
           |  |  | 292 |   | 
        
           |  |  | 293 |     // Retrive the size of this media type
 | 
        
           |  |  | 294 |     D3DCAPS9 caps;
 | 
        
           |  |  | 295 |     VIDEOINFO *pviBmp;                      // Bitmap info header
 | 
        
           |  |  | 296 |     pviBmp = (VIDEOINFO *)pmt->Format();
 | 
        
           |  |  | 297 |   | 
        
           |  |  | 298 |     m_lVidWidth  = pviBmp->bmiHeader.biWidth;
 | 
        
           |  |  | 299 |     m_lVidHeight = abs(pviBmp->bmiHeader.biHeight);
 | 
        
           |  |  | 300 |     m_lVidPitch  = (m_lVidWidth * 3 + 3) & ~(3); // We are forcing RGB24
 | 
        
           |  |  | 301 |   | 
        
           |  |  | 302 |     // here let's check if we can use dynamic textures
 | 
        
           |  |  | 303 |     ZeroMemory( &caps, sizeof(D3DCAPS9));
 | 
        
           |  |  | 304 |     hr = g_pd3dDevice->GetDeviceCaps( &caps );
 | 
        
           |  |  | 305 |     if( caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES )
 | 
        
           |  |  | 306 |     {
 | 
        
           |  |  | 307 |         m_bUseDynamicTextures = TRUE;
 | 
        
           |  |  | 308 |     }
 | 
        
           |  |  | 309 |   | 
        
           |  |  | 310 |     if( caps.TextureCaps & D3DPTEXTURECAPS_POW2 )
 | 
        
           |  |  | 311 |     {
 | 
        
           |  |  | 312 |         while( (LONG)uintWidth < m_lVidWidth )
 | 
        
           |  |  | 313 |         {
 | 
        
           |  |  | 314 |             uintWidth = uintWidth << 1;
 | 
        
           |  |  | 315 |         }
 | 
        
           |  |  | 316 |         while( (LONG)uintHeight < m_lVidHeight )
 | 
        
           |  |  | 317 |         {
 | 
        
           |  |  | 318 |             uintHeight = uintHeight << 1;
 | 
        
           |  |  | 319 |         }
 | 
        
           |  |  | 320 |     }
 | 
        
           |  |  | 321 |     else
 | 
        
           |  |  | 322 |     {
 | 
        
           |  |  | 323 |         uintWidth = m_lVidWidth;
 | 
        
           |  |  | 324 |         uintHeight = m_lVidHeight;
 | 
        
           |  |  | 325 |     }
 | 
        
           |  |  | 326 |   | 
        
           |  |  | 327 |     // Create the texture that maps to this media type
 | 
        
           |  |  | 328 |     hr = E_UNEXPECTED;
 | 
        
           |  |  | 329 |     if( m_bUseDynamicTextures )
 | 
        
           |  |  | 330 |     {
 | 
        
           |  |  | 331 |         hr = g_pd3dDevice->CreateTexture(uintWidth, uintHeight, 1, D3DUSAGE_DYNAMIC,
 | 
        
           |  |  | 332 |                                          D3DFMT_X8R8G8B8,D3DPOOL_DEFAULT,
 | 
        
           |  |  | 333 |                                          &g_pTexture, NULL);
 | 
        
           |  |  | 334 |         g_pachRenderMethod = g_achDynTextr;
 | 
        
           |  |  | 335 |         if( FAILED(hr))
 | 
        
           |  |  | 336 |         {
 | 
        
           |  |  | 337 |             m_bUseDynamicTextures = FALSE;
 | 
        
           |  |  | 338 |         }
 | 
        
           |  |  | 339 |     }
 | 
        
           |  |  | 340 |     if( FALSE == m_bUseDynamicTextures )
 | 
        
           |  |  | 341 |     {
 | 
        
           |  |  | 342 |         hr = g_pd3dDevice->CreateTexture(uintWidth, uintHeight, 1, 0,
 | 
        
           |  |  | 343 |                                          D3DFMT_X8R8G8B8,D3DPOOL_MANAGED,
 | 
        
           |  |  | 344 |                                          &g_pTexture, NULL);
 | 
        
           |  |  | 345 |         g_pachRenderMethod = g_achCopy;
 | 
        
           |  |  | 346 |     }
 | 
        
           |  |  | 347 |     if( FAILED(hr))
 | 
        
           |  |  | 348 |     {
 | 
        
           |  |  | 349 |         Msg(TEXT("Could not create the D3DX texture!  hr=0x%x"), hr);
 | 
        
           |  |  | 350 |         return hr;
 | 
        
           |  |  | 351 |     }
 | 
        
           |  |  | 352 |   | 
        
           |  |  | 353 |     // CreateTexture can silently change the parameters on us
 | 
        
           |  |  | 354 |     D3DSURFACE_DESC ddsd;
 | 
        
           |  |  | 355 |     ZeroMemory(&ddsd, sizeof(ddsd));
 | 
        
           |  |  | 356 |   | 
        
           |  |  | 357 |     if ( FAILED( hr = g_pTexture->GetLevelDesc( 0, &ddsd ) ) ) {
 | 
        
           |  |  | 358 |         Msg(TEXT("Could not get level Description of D3DX texture! hr = 0x%x"), hr);
 | 
        
           |  |  | 359 |         return hr;
 | 
        
           |  |  | 360 |     }
 | 
        
           |  |  | 361 |   | 
        
           |  |  | 362 |   | 
        
           |  |  | 363 |     CComPtr<IDirect3DSurface9> pSurf;
 | 
        
           |  |  | 364 |   | 
        
           |  |  | 365 |     if (SUCCEEDED(hr = g_pTexture->GetSurfaceLevel(0, &pSurf)))
 | 
        
           |  |  | 366 |         pSurf->GetDesc(&ddsd);
 | 
        
           |  |  | 367 |   | 
        
           |  |  | 368 |     // Save format info
 | 
        
           |  |  | 369 |     g_TextureFormat = ddsd.Format;
 | 
        
           |  |  | 370 |   | 
        
           |  |  | 371 |     if (g_TextureFormat != D3DFMT_X8R8G8B8 &&
 | 
        
           |  |  | 372 |         g_TextureFormat != D3DFMT_A1R5G5B5) {
 | 
        
           |  |  | 373 |         Msg(TEXT("Texture is format we can't handle! Format = 0x%x"), g_TextureFormat);
 | 
        
           |  |  | 374 |         return VFW_E_TYPE_NOT_ACCEPTED;
 | 
        
           |  |  | 375 |     }
 | 
        
           |  |  | 376 |   | 
        
           |  |  | 377 |     return S_OK;
 | 
        
           |  |  | 378 | }
 | 
        
           |  |  | 379 |   | 
        
           |  |  | 380 |   | 
        
           |  |  | 381 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 382 | // DoRenderSample: A sample has been delivered. Copy it to the texture.
 | 
        
           |  |  | 383 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 384 | HRESULT CTextureRenderer::DoRenderSample( IMediaSample * pSample )
 | 
        
           |  |  | 385 | {
 | 
        
           |  |  | 386 |     BYTE  *pBmpBuffer, *pTxtBuffer; // Bitmap buffer, texture buffer
 | 
        
           |  |  | 387 |     LONG  lTxtPitch;                // Pitch of bitmap, texture
 | 
        
           |  |  | 388 |   | 
        
           |  |  | 389 |     BYTE  * pbS = NULL;
 | 
        
           |  |  | 390 |     DWORD * pdwS = NULL;
 | 
        
           |  |  | 391 |     DWORD * pdwD = NULL;
 | 
        
           |  |  | 392 |     UINT row, col, dwordWidth;
 | 
        
           |  |  | 393 |   | 
        
           |  |  | 394 |     CheckPointer(pSample,E_POINTER);
 | 
        
           |  |  | 395 |     CheckPointer(g_pTexture,E_UNEXPECTED);
 | 
        
           |  |  | 396 |   | 
        
           |  |  | 397 |     // Get the video bitmap buffer
 | 
        
           |  |  | 398 |     pSample->GetPointer( &pBmpBuffer );
 | 
        
           |  |  | 399 |   | 
        
           |  |  | 400 |     // Lock the Texture
 | 
        
           |  |  | 401 |     D3DLOCKED_RECT d3dlr;
 | 
        
           |  |  | 402 |     if( m_bUseDynamicTextures )
 | 
        
           |  |  | 403 |     {
 | 
        
           |  |  | 404 |         if( FAILED(g_pTexture->LockRect(0, &d3dlr, 0, D3DLOCK_DISCARD)))
 | 
        
           |  |  | 405 |             return E_FAIL;
 | 
        
           |  |  | 406 |     }
 | 
        
           |  |  | 407 |     else
 | 
        
           |  |  | 408 |     {
 | 
        
           |  |  | 409 |         if (FAILED(g_pTexture->LockRect(0, &d3dlr, 0, 0)))
 | 
        
           |  |  | 410 |             return E_FAIL;
 | 
        
           |  |  | 411 |     }
 | 
        
           |  |  | 412 |     // Get the texture buffer & pitch
 | 
        
           |  |  | 413 |     pTxtBuffer = static_cast<byte *>(d3dlr.pBits);
 | 
        
           |  |  | 414 |     lTxtPitch = d3dlr.Pitch;
 | 
        
           |  |  | 415 |   | 
        
           |  |  | 416 |   | 
        
           |  |  | 417 |     // Copy the bits
 | 
        
           |  |  | 418 |   | 
        
           |  |  | 419 |     if (g_TextureFormat == D3DFMT_X8R8G8B8)
 | 
        
           |  |  | 420 |     {
 | 
        
           |  |  | 421 |         // Instead of copying data bytewise, we use DWORD alignment here.
 | 
        
           |  |  | 422 |         // We also unroll loop by copying 4 pixels at once.
 | 
        
           |  |  | 423 |         //
 | 
        
           |  |  | 424 |         // original BYTE array is [b0][g0][r0][b1][g1][r1][b2][g2][r2][b3][g3][r3]
 | 
        
           |  |  | 425 |         //
 | 
        
           |  |  | 426 |         // aligned DWORD array is     [b1 r0 g0 b0][g2 b2 r1 g1][r3 g3 b3 r2]
 | 
        
           |  |  | 427 |         //
 | 
        
           |  |  | 428 |         // We want to transform it to [ff r0 g0 b0][ff r1 g1 b1][ff r2 g2 b2][ff r3 b3 g3]
 | 
        
           |  |  | 429 |         // below, bitwise operations do exactly this.
 | 
        
           |  |  | 430 |   | 
        
           |  |  | 431 |         dwordWidth = m_lVidWidth / 4; // aligned width of the row, in DWORDS
 | 
        
           |  |  | 432 |                                       // (pixel by 3 bytes over sizeof(DWORD))
 | 
        
           |  |  | 433 |   | 
        
           |  |  | 434 |         for( row = 0; row< (UINT)m_lVidHeight; row++)
 | 
        
           |  |  | 435 |         {
 | 
        
           |  |  | 436 |             pdwS = ( DWORD*)pBmpBuffer;
 | 
        
           |  |  | 437 |             pdwD = ( DWORD*)pTxtBuffer;
 | 
        
           |  |  | 438 |   | 
        
           |  |  | 439 |             for( col = 0; col < dwordWidth; col ++ )
 | 
        
           |  |  | 440 |             {
 | 
        
           |  |  | 441 |                 pdwD[0] =  pdwS[0] | 0xFF000000;
 | 
        
           |  |  | 442 |                 pdwD[1] = ((pdwS[1]<<8)  | 0xFF000000) | (pdwS[0]>>24);
 | 
        
           |  |  | 443 |                 pdwD[2] = ((pdwS[2]<<16) | 0xFF000000) | (pdwS[1]>>16);
 | 
        
           |  |  | 444 |                 pdwD[3] = 0xFF000000 | (pdwS[2]>>8);
 | 
        
           |  |  | 445 |                 pdwD +=4;
 | 
        
           |  |  | 446 |                 pdwS +=3;
 | 
        
           |  |  | 447 |             }
 | 
        
           |  |  | 448 |   | 
        
           |  |  | 449 |             // we might have remaining (misaligned) bytes here
 | 
        
           |  |  | 450 |             pbS = (BYTE*) pdwS;
 | 
        
           |  |  | 451 |             for( col = 0; col < (UINT)m_lVidWidth % 4; col++)
 | 
        
           |  |  | 452 |             {
 | 
        
           |  |  | 453 |                 *pdwD = 0xFF000000     |
 | 
        
           |  |  | 454 |                         (pbS[2] << 16) |
 | 
        
           |  |  | 455 |                         (pbS[1] <<  8) |
 | 
        
           |  |  | 456 |                         (pbS[0]);
 | 
        
           |  |  | 457 |                 pdwD++;
 | 
        
           |  |  | 458 |                 pbS += 3;
 | 
        
           |  |  | 459 |             }
 | 
        
           |  |  | 460 |   | 
        
           |  |  | 461 |             pBmpBuffer  += m_lVidPitch;
 | 
        
           |  |  | 462 |             pTxtBuffer += lTxtPitch;
 | 
        
           |  |  | 463 |         }// for rows
 | 
        
           |  |  | 464 |     }
 | 
        
           |  |  | 465 |   | 
        
           |  |  | 466 |     if (g_TextureFormat == D3DFMT_A1R5G5B5)
 | 
        
           |  |  | 467 |     {
 | 
        
           |  |  | 468 |         for(int y = 0; y < m_lVidHeight; y++ )
 | 
        
           |  |  | 469 |         {
 | 
        
           |  |  | 470 |             BYTE *pBmpBufferOld = pBmpBuffer;
 | 
        
           |  |  | 471 |             BYTE *pTxtBufferOld = pTxtBuffer;
 | 
        
           |  |  | 472 |   | 
        
           |  |  | 473 |             for (int x = 0; x < m_lVidWidth; x++)
 | 
        
           |  |  | 474 |             {
 | 
        
           |  |  | 475 |                 *(WORD *)pTxtBuffer = (WORD)
 | 
        
           |  |  | 476 |                     (0x8000 +
 | 
        
           |  |  | 477 |                     ((pBmpBuffer[2] & 0xF8) << 7) +
 | 
        
           |  |  | 478 |                     ((pBmpBuffer[1] & 0xF8) << 2) +
 | 
        
           |  |  | 479 |                     (pBmpBuffer[0] >> 3));
 | 
        
           |  |  | 480 |   | 
        
           |  |  | 481 |                 pTxtBuffer += 2;
 | 
        
           |  |  | 482 |                 pBmpBuffer += 3;
 | 
        
           |  |  | 483 |             }
 | 
        
           |  |  | 484 |   | 
        
           |  |  | 485 |             pBmpBuffer = pBmpBufferOld + m_lVidPitch;
 | 
        
           |  |  | 486 |             pTxtBuffer = pTxtBufferOld + lTxtPitch;
 | 
        
           |  |  | 487 |         }
 | 
        
           |  |  | 488 |     }
 | 
        
           |  |  | 489 |   | 
        
           |  |  | 490 |     // Unlock the Texture
 | 
        
           |  |  | 491 |     if (FAILED(g_pTexture->UnlockRect(0)))
 | 
        
           |  |  | 492 |         return E_FAIL;
 | 
        
           |  |  | 493 |   | 
        
           |  |  | 494 |     return S_OK;
 | 
        
           |  |  | 495 | }
 | 
        
           |  |  | 496 |   | 
        
           |  |  | 497 |   | 
        
           |  |  | 498 | #ifdef REGISTER_FILTERGRAPH
 | 
        
           |  |  | 499 |   | 
        
           |  |  | 500 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 501 | // Running Object Table functions: Used to debug. By registering the graph
 | 
        
           |  |  | 502 | // in the running object table, GraphEdit is able to connect to the running
 | 
        
           |  |  | 503 | // graph. This code should be removed before the application is shipped in
 | 
        
           |  |  | 504 | // order to avoid third parties from spying on your graph.
 | 
        
           |  |  | 505 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 506 | DWORD dwROTReg = 0xfedcba98;
 | 
        
           |  |  | 507 |   | 
        
           |  |  | 508 | HRESULT AddToROT(IUnknown *pUnkGraph)
 | 
        
           |  |  | 509 | {
 | 
        
           |  |  | 510 |     IMoniker * pmk;
 | 
        
           |  |  | 511 |     IRunningObjectTable *pROT;
 | 
        
           |  |  | 512 |     if (FAILED(GetRunningObjectTable(0, &pROT))) {
 | 
        
           |  |  | 513 |         return E_FAIL;
 | 
        
           |  |  | 514 |     }
 | 
        
           |  |  | 515 |   | 
        
           |  |  | 516 |     WCHAR wsz[256];
 | 
        
           |  |  | 517 |     (void)StringCchPrintfW(wsz, NUMELMS(wsz),L"FilterGraph %08x  pid %08x\0", (DWORD_PTR) 0, GetCurrentProcessId());
 | 
        
           |  |  | 518 |   | 
        
           |  |  | 519 |     HRESULT hr = CreateItemMoniker(L"!", wsz, &pmk);
 | 
        
           |  |  | 520 |     if (SUCCEEDED(hr))
 | 
        
           |  |  | 521 |     {
 | 
        
           |  |  | 522 |         // Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference
 | 
        
           |  |  | 523 |         // to the object.  Using this flag will cause the object to remain
 | 
        
           |  |  | 524 |         // registered until it is explicitly revoked with the Revoke() method.
 | 
        
           |  |  | 525 |         //
 | 
        
           |  |  | 526 |         // Not using this flag means that if GraphEdit remotely connects
 | 
        
           |  |  | 527 |         // to this graph and then GraphEdit exits, this object registration
 | 
        
           |  |  | 528 |         // will be deleted, causing future attempts by GraphEdit to fail until
 | 
        
           |  |  | 529 |         // this application is restarted or until the graph is registered again.
 | 
        
           |  |  | 530 |         hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
 | 
        
           |  |  | 531 |                             pmk, &dwROTReg);
 | 
        
           |  |  | 532 |         pmk->Release();
 | 
        
           |  |  | 533 |     }
 | 
        
           |  |  | 534 |   | 
        
           |  |  | 535 |     pROT->Release();
 | 
        
           |  |  | 536 |     return hr;
 | 
        
           |  |  | 537 | }
 | 
        
           |  |  | 538 |   | 
        
           |  |  | 539 |   | 
        
           |  |  | 540 | void RemoveFromROT(void)
 | 
        
           |  |  | 541 | {
 | 
        
           |  |  | 542 |     IRunningObjectTable *pirot=0;
 | 
        
           |  |  | 543 |   | 
        
           |  |  | 544 |     if (SUCCEEDED(GetRunningObjectTable(0, &pirot)))
 | 
        
           |  |  | 545 |     {
 | 
        
           |  |  | 546 |         pirot->Revoke(dwROTReg);
 | 
        
           |  |  | 547 |         pirot->Release();
 | 
        
           |  |  | 548 |     }
 | 
        
           |  |  | 549 | }
 | 
        
           |  |  | 550 |   | 
        
           |  |  | 551 | #endif
 | 
        
           |  |  | 552 |   | 
        
           |  |  | 553 |   | 
        
           |  |  | 554 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 555 | // Msg: Display an error message box if needed
 | 
        
           |  |  | 556 | //-----------------------------------------------------------------------------
 | 
        
           |  |  | 557 | void Msg(TCHAR *szFormat, ...)
 | 
        
           |  |  | 558 | {
 | 
        
           |  |  | 559 |     TCHAR szBuffer[1024];  // Large buffer for long filenames or URLs
 | 
        
           |  |  | 560 |     const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
 | 
        
           |  |  | 561 |     const int LASTCHAR = NUMCHARS - 1;
 | 
        
           |  |  | 562 |   | 
        
           |  |  | 563 |     // Format the input string
 | 
        
           |  |  | 564 |     va_list pArgs;
 | 
        
           |  |  | 565 |     va_start(pArgs, szFormat);
 | 
        
           |  |  | 566 |   | 
        
           |  |  | 567 |     // Use a bounded buffer size to prevent buffer overruns.  Limit count to
 | 
        
           |  |  | 568 |     // character size minus one to allow for a NULL terminating character.
 | 
        
           |  |  | 569 |     (void)StringCchVPrintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
 | 
        
           |  |  | 570 |     va_end(pArgs);
 | 
        
           |  |  | 571 |   | 
        
           |  |  | 572 |     // Ensure that the formatted string is NULL-terminated
 | 
        
           |  |  | 573 |     szBuffer[LASTCHAR] = TEXT('\0');
 | 
        
           |  |  | 574 |   | 
        
           |  |  | 575 |     MessageBox(NULL, szBuffer, TEXT("DirectShow Texture3D9 Sample"),
 | 
        
           |  |  | 576 |                MB_OK | MB_ICONERROR);
 | 
        
           |  |  | 577 | }
 | 
        
           |  |  | 578 |   | 
        
           |  |  | 579 |   | 
        
           |  |  | 580 | /*
 | 
        
           |  |  | 581 |   | 
        
           |  |  | 582 | BOOL GetClipFileName(LPTSTR szName)
 | 
        
           |  |  | 583 | {
 | 
        
           |  |  | 584 |     OPENFILENAME ofn;
 | 
        
           |  |  | 585 |     ZeroMemory(&ofn, sizeof(ofn));
 | 
        
           |  |  | 586 |   | 
        
           |  |  | 587 |   | 
        
           |  |  | 588 |     // Reset filename
 | 
        
           |  |  | 589 |     *szName = 0;
 | 
        
           |  |  | 590 |   | 
        
           |  |  | 591 |     // Fill in standard structure fields
 | 
        
           |  |  | 592 |     ofn.lStructSize       = sizeof(OPENFILENAME);
 | 
        
           |  |  | 593 | //    ofn.hwndOwner         = g_hWnd;
 | 
        
           |  |  | 594 |     ofn.lpstrFilter       = FILE_FILTER_TEXT;
 | 
        
           |  |  | 595 |     ofn.lpstrCustomFilter = NULL;
 | 
        
           |  |  | 596 |     ofn.nFilterIndex      = 1;
 | 
        
           |  |  | 597 |     ofn.lpstrFile         = szName;
 | 
        
           |  |  | 598 |     ofn.nMaxFile          = MAX_PATH;
 | 
        
           |  |  | 599 |     ofn.lpstrTitle        = TEXT("Open Media File...\0");
 | 
        
           |  |  | 600 |     ofn.lpstrFileTitle    = NULL;
 | 
        
           |  |  | 601 |     ofn.lpstrDefExt       = TEXT("*\0");
 | 
        
           |  |  | 602 |     ofn.Flags             = OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST;
 | 
        
           |  |  | 603 |   | 
        
           |  |  | 604 |   | 
        
           |  |  | 605 |     // Create the standard file open dialog and return its result
 | 
        
           |  |  | 606 |     return GetOpenFileName((LPOPENFILENAME)&ofn);
 | 
        
           |  |  | 607 | }
 | 
        
           |  |  | 608 |   | 
        
           |  |  | 609 | */
 |