00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include "mplayerc.h"
00024 #include <atlbase.h>
00025 #include <atlcoll.h>
00026 #include "..\..\DSUtil\DSUtil.h"
00027
00028 #include <Videoacc.h>
00029
00030 #include <initguid.h>
00031 #include "DX9AllocatorPresenter.h"
00032 #include <d3d9.h>
00033 #include <d3dx9.h>
00034 #include <Vmr9.h>
00035 #include "..\..\SubPic\DX9SubPic.h"
00036 #include "..\..\..\include\RealMedia\pntypes.h"
00037 #include "..\..\..\include\RealMedia\pnwintyp.h"
00038 #include "..\..\..\include\RealMedia\pncom.h"
00039 #include "..\..\..\include\RealMedia\rmavsurf.h"
00040 #include "IQTVideoSurface.h"
00041
00042 #include "MacrovisionKicker.h"
00043 #include "IPinHook.h"
00044
00045 #include "PixelShaderCompiler.h"
00046
00047 bool IsVMR9InGraph(IFilterGraph* pFG)
00048 {
00049 BeginEnumFilters(pFG, pEF, pBF)
00050 if(CComQIPtr<IVMRWindowlessControl9>(pBF)) return(true);
00051 EndEnumFilters
00052 return(false);
00053 }
00054
00055 namespace DSObjects
00056 {
00057
00058 class CDX9AllocatorPresenter
00059 : public ISubPicAllocatorPresenterImpl
00060 {
00061 protected:
00062 CSize m_ScreenSize;
00063 bool m_fVMRSyncFix;
00064
00065 CComPtr<IDirect3D9> m_pD3D;
00066 CComPtr<IDirect3DDevice9> m_pD3DDev;
00067 CComPtr<IDirect3DTexture9> m_pVideoTexture[2];
00068 CComPtr<IDirect3DSurface9> m_pVideoSurface[2];
00069 CComPtr<IDirect3DPixelShader9> m_pPixelShader, m_pResizerPixelShader[4];
00070 D3DTEXTUREFILTERTYPE m_Filter;
00071
00072 CAutoPtr<CPixelShaderCompiler> m_pPSC;
00073
00074 virtual HRESULT CreateDevice();
00075 virtual HRESULT AllocSurfaces();
00076 virtual void DeleteSurfaces();
00077
00078 UINT GetAdapter(IDirect3D9 *pD3D);
00079
00080 public:
00081 CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00082
00083
00084 STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
00085 STDMETHODIMP_(bool) Paint(bool fAll);
00086 STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size);
00087 STDMETHODIMP SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget);
00088 };
00089
00090 class CVMR9AllocatorPresenter
00091 : public CDX9AllocatorPresenter
00092 , public IVMRSurfaceAllocator9
00093 , public IVMRImagePresenter9
00094 , public IVMRWindowlessControl9
00095 {
00096 protected:
00097 CComPtr<IVMRSurfaceAllocatorNotify9> m_pIVMRSurfAllocNotify;
00098 CInterfaceArray<IDirect3DSurface9> m_pSurfaces;
00099
00100 HRESULT CreateDevice();
00101 void DeleteSurfaces();
00102
00103 bool m_fUseInternalTimer;
00104
00105 public:
00106 CVMR9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00107
00108 DECLARE_IUNKNOWN
00109 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00110
00111
00112 STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
00113 STDMETHODIMP_(void) SetTime(REFERENCE_TIME rtNow);
00114
00115
00116 STDMETHODIMP InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo* lpAllocInfo, DWORD* lpNumBuffers);
00117 STDMETHODIMP TerminateDevice(DWORD_PTR dwID);
00118 STDMETHODIMP GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9** lplpSurface);
00119 STDMETHODIMP AdviseNotify(IVMRSurfaceAllocatorNotify9* lpIVMRSurfAllocNotify);
00120
00121
00122 STDMETHODIMP StartPresenting(DWORD_PTR dwUserID);
00123 STDMETHODIMP StopPresenting(DWORD_PTR dwUserID);
00124 STDMETHODIMP PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo* lpPresInfo);
00125
00126
00127 STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight);
00128 STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
00129 STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
00130 STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect);
00131 STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect);
00132 STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode);
00133 STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode);
00134 STDMETHODIMP SetVideoClippingWindow(HWND hwnd);
00135 STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc);
00136 STDMETHODIMP DisplayModeChanged();
00137 STDMETHODIMP GetCurrentImage(BYTE** lpDib);
00138 STDMETHODIMP SetBorderColor(COLORREF Clr);
00139 STDMETHODIMP GetBorderColor(COLORREF* lpClr);
00140 };
00141
00142 class CRM9AllocatorPresenter
00143 : public CDX9AllocatorPresenter
00144 , public IRMAVideoSurface
00145 {
00146 CComPtr<IDirect3DSurface9> m_pVideoSurfaceOff;
00147 CComPtr<IDirect3DSurface9> m_pVideoSurfaceYUY2;
00148
00149 RMABitmapInfoHeader m_bitmapInfo;
00150 RMABitmapInfoHeader m_lastBitmapInfo;
00151
00152 protected:
00153 HRESULT AllocSurfaces();
00154 void DeleteSurfaces();
00155
00156 public:
00157 CRM9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00158
00159 DECLARE_IUNKNOWN
00160 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00161
00162
00163 STDMETHODIMP Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect);
00164 STDMETHODIMP BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo);
00165 STDMETHODIMP OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect);
00166 STDMETHODIMP EndOptimizedBlt();
00167 STDMETHODIMP GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType);
00168 STDMETHODIMP GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType);
00169 };
00170
00171 class CQT9AllocatorPresenter
00172 : public CDX9AllocatorPresenter
00173 , public IQTVideoSurface
00174 {
00175 CComPtr<IDirect3DSurface9> m_pVideoSurfaceOff;
00176
00177 protected:
00178 HRESULT AllocSurfaces();
00179 void DeleteSurfaces();
00180
00181 public:
00182 CQT9AllocatorPresenter(HWND hWnd, HRESULT& hr);
00183
00184 DECLARE_IUNKNOWN
00185 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00186
00187
00188 STDMETHODIMP BeginBlt(const BITMAP& bm);
00189 STDMETHODIMP DoBlt(const BITMAP& bm);
00190 };
00191
00192 }
00193 using namespace DSObjects;
00194
00195
00196
00197 HRESULT CreateAP9(const CLSID& clsid, HWND hWnd, ISubPicAllocatorPresenter** ppAP)
00198 {
00199 CheckPointer(ppAP, E_POINTER);
00200
00201 *ppAP = NULL;
00202
00203 HRESULT hr;
00204 if(clsid == CLSID_VMR9AllocatorPresenter && !(*ppAP = new CVMR9AllocatorPresenter(hWnd, hr))
00205 || clsid == CLSID_RM9AllocatorPresenter && !(*ppAP = new CRM9AllocatorPresenter(hWnd, hr))
00206 || clsid == CLSID_QT9AllocatorPresenter && !(*ppAP = new CQT9AllocatorPresenter(hWnd, hr)))
00207 return E_OUTOFMEMORY;
00208
00209 if(*ppAP == NULL)
00210 return E_FAIL;
00211
00212 (*ppAP)->AddRef();
00213
00214 if(FAILED(hr))
00215 {
00216 (*ppAP)->Release();
00217 *ppAP = NULL;
00218 }
00219
00220 return hr;
00221 }
00222
00223
00224
00225 static HRESULT TextureBlt(CComPtr<IDirect3DTexture9> pTexture, Vector dst[4], CRect src, DWORD filter = D3DTEXF_LINEAR)
00226 {
00227 if(!pTexture)
00228 return E_POINTER;
00229
00230 CComPtr<IDirect3DDevice9> pD3DDev;
00231 if(FAILED(pTexture->GetDevice(&pD3DDev)) || !pD3DDev)
00232 return E_FAIL;
00233
00234 HRESULT hr;
00235
00236 do
00237 {
00238 D3DSURFACE_DESC d3dsd;
00239 ZeroMemory(&d3dsd, sizeof(d3dsd));
00240 if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)))
00241 break;
00242
00243 float w = (float)d3dsd.Width;
00244 float h = (float)d3dsd.Height;
00245
00246 struct
00247 {
00248 float x, y, z, rhw;
00249 float tu, tv;
00250 }
00251 pVertices[] =
00252 {
00253
00254
00255
00256 {(float)dst[0].x, (float)dst[0].y, (float)dst[0].z, 1.0f/(float)dst[0].z, (float)src.left / w, (float)src.top / h},
00257 {(float)dst[1].x, (float)dst[1].y, (float)dst[1].z, 1.0f/(float)dst[1].z, (float)src.right / w, (float)src.top / h},
00258 {(float)dst[2].x, (float)dst[2].y, (float)dst[2].z, 1.0f/(float)dst[2].z, (float)src.left / w, (float)src.bottom / h},
00259 {(float)dst[3].x, (float)dst[3].y, (float)dst[3].z, 1.0f/(float)dst[3].z, (float)src.right / w, (float)src.bottom / h},
00260 };
00261
00262 for(int i = 0; i < countof(pVertices); i++)
00263 {
00264 pVertices[i].x -= 0.5;
00265 pVertices[i].y -= 0.5;
00266 }
00267
00268 hr = pD3DDev->SetTexture(0, pTexture);
00269
00270 hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
00271 hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
00272 hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
00273 hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
00274 hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
00275
00276 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, filter);
00277 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, filter);
00278 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, filter);
00279
00280 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
00281 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
00282
00283
00284
00285 if(FAILED(hr = pD3DDev->BeginScene()))
00286 break;
00287
00288 hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
00289
00290 hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
00291
00292 hr = pD3DDev->EndScene();
00293
00294
00295
00296 pD3DDev->SetTexture(0, NULL);
00297
00298 return S_OK;
00299 }
00300 while(0);
00301
00302 return E_FAIL;
00303 }
00304
00305 static HRESULT TextureBlt(CComPtr<IDirect3DTexture9> pTexture, CRect dst, CRect src, DWORD filter = D3DTEXF_LINEAR)
00306 {
00307 if(!pTexture)
00308 return E_POINTER;
00309
00310 CComPtr<IDirect3DDevice9> pD3DDev;
00311 if(FAILED(pTexture->GetDevice(&pD3DDev)) || !pD3DDev)
00312 return E_FAIL;
00313
00314 HRESULT hr;
00315
00316 do
00317 {
00318 D3DSURFACE_DESC d3dsd;
00319 ZeroMemory(&d3dsd, sizeof(d3dsd));
00320 if(FAILED(pTexture->GetLevelDesc(0, &d3dsd)))
00321 break;
00322
00323 float w = (float)d3dsd.Width;
00324 float h = (float)d3dsd.Height;
00325
00326 struct
00327 {
00328 float x, y, z, rhw;
00329 float tu, tv;
00330 }
00331 pVertices[] =
00332 {
00333 {(float)dst.left, (float)dst.top, 0.5f, 2.0f, (float)src.left / w, (float)src.top / h},
00334 {(float)dst.right, (float)dst.top, 0.5f, 2.0f, (float)src.right / w, (float)src.top / h},
00335 {(float)dst.left, (float)dst.bottom, 0.5f, 2.0f, (float)src.left / w, (float)src.bottom / h},
00336 {(float)dst.right, (float)dst.bottom, 0.5f, 2.0f, (float)src.right / w, (float)src.bottom / h},
00337 };
00338
00339 for(int i = 0; i < countof(pVertices); i++)
00340 {
00341 pVertices[i].x -= 0.5;
00342 pVertices[i].y -= 0.5;
00343 }
00344
00345 hr = pD3DDev->SetTexture(0, pTexture);
00346
00347 hr = pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
00348 hr = pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
00349 hr = pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
00350 hr = pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
00351 hr = pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
00352
00353 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, filter);
00354 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, filter);
00355 hr = pD3DDev->SetSamplerState(0, D3DSAMP_MIPFILTER, filter);
00356
00357 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
00358 hr = pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
00359
00360
00361
00362 if(FAILED(hr = pD3DDev->BeginScene()))
00363 break;
00364
00365 hr = pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
00366 hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(pVertices[0]));
00367
00368 hr = pD3DDev->EndScene();
00369
00370
00371
00372 pD3DDev->SetTexture(0, NULL);
00373
00374 return S_OK;
00375 }
00376 while(0);
00377
00378 return E_FAIL;
00379 }
00380
00381
00382
00383 CDX9AllocatorPresenter::CDX9AllocatorPresenter(HWND hWnd, HRESULT& hr)
00384 : ISubPicAllocatorPresenterImpl(hWnd)
00385 , m_ScreenSize(0, 0)
00386 {
00387 if(!IsWindow(m_hWnd))
00388 {
00389 hr = E_INVALIDARG;
00390 return;
00391 }
00392
00393 m_pD3D.Attach(Direct3DCreate9(D3D_SDK_VERSION));
00394 if(!m_pD3D) m_pD3D.Attach(Direct3DCreate9(D3D9b_SDK_VERSION));
00395
00396 if(!m_pD3D)
00397 {
00398 hr = E_FAIL;
00399 return;
00400 }
00401
00402 GetWindowRect(m_hWnd, &m_WindowRect);
00403
00404 hr = CreateDevice();
00405 }
00406
00407 HRESULT CDX9AllocatorPresenter::CreateDevice()
00408 {
00409 m_pPSC.Free();
00410 m_pD3DDev = NULL;
00411
00412 D3DDISPLAYMODE d3ddm;
00413 ZeroMemory(&d3ddm, sizeof(d3ddm));
00414 if(FAILED(m_pD3D->GetAdapterDisplayMode(GetAdapter(m_pD3D), &d3ddm)))
00415 return E_UNEXPECTED;
00416
00417 m_ScreenSize.SetSize(d3ddm.Width, d3ddm.Height);
00418
00419 D3DPRESENT_PARAMETERS pp;
00420 ZeroMemory(&pp, sizeof(pp));
00421 pp.Windowed = TRUE;
00422 pp.hDeviceWindow = m_hWnd;
00423 pp.SwapEffect = D3DSWAPEFFECT_COPY;
00424 pp.Flags = D3DPRESENTFLAG_VIDEO;
00425 pp.BackBufferWidth = d3ddm.Width;
00426 pp.BackBufferHeight = d3ddm.Height;
00427
00428 if(m_fVMRSyncFix = AfxGetMyApp()->m_s.fVMRSyncFix)
00429 pp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
00430
00431 HRESULT hr = m_pD3D->CreateDevice(
00432 GetAdapter(m_pD3D), D3DDEVTYPE_HAL, m_hWnd,
00433 D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED,
00434 &pp, &m_pD3DDev);
00435 if(FAILED(hr))
00436 return hr;
00437
00438 m_pPSC.Attach(new CPixelShaderCompiler(m_pD3DDev, true));
00439
00440
00441
00442 m_Filter = D3DTEXF_NONE;
00443
00444 D3DCAPS9 caps;
00445 ZeroMemory(&caps, sizeof(caps));
00446 m_pD3DDev->GetDeviceCaps(&caps);
00447 if((caps.StretchRectFilterCaps&D3DPTFILTERCAPS_MINFLINEAR)
00448 && (caps.StretchRectFilterCaps&D3DPTFILTERCAPS_MAGFLINEAR))
00449 m_Filter = D3DTEXF_LINEAR;
00450
00451
00452
00453 if(caps.PixelShaderVersion >= D3DVS_VERSION(2, 0))
00454 {
00455 CStringA data;
00456 if(LoadResource(IDF_SHADER_RESIZER, data, _T("FILE")))
00457 {
00458 m_pPSC->CompileShader(data, "main_bilinear", "ps_2_0", 0, &m_pResizerPixelShader[0]);
00459
00460 {
00461 CStringA str = data;
00462 str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-0.60)");
00463 m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[1]);
00464 }
00465
00466 {
00467 CStringA str = data;
00468 str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-0.75)");
00469 m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[2]);
00470 }
00471
00472 {
00473 CStringA str = data;
00474 str.Replace("_The_Value_Of_A_Is_Set_Here_", "(-1.00)");
00475 m_pPSC->CompileShader(str, "main_bicubic", "ps_2_0", 0, &m_pResizerPixelShader[3]);
00476 }
00477 }
00478 }
00479
00480
00481
00482 CComPtr<ISubPicProvider> pSubPicProvider;
00483 if(m_pSubPicQueue) m_pSubPicQueue->GetSubPicProvider(&pSubPicProvider);
00484
00485 CSize size;
00486 switch(AfxGetAppSettings().nSPCMaxRes)
00487 {
00488 case 0: default: size = m_ScreenSize; break;
00489 case 1: size.SetSize(1024, 768); break;
00490 case 2: size.SetSize(800, 600); break;
00491 case 3: size.SetSize(640, 480); break;
00492 case 4: size.SetSize(512, 384); break;
00493 case 5: size.SetSize(384, 288); break;
00494 }
00495
00496 if(m_pAllocator)
00497 {
00498 m_pAllocator->ChangeDevice(m_pD3DDev);
00499 }
00500 else
00501 {
00502 m_pAllocator = new CDX9SubPicAllocator(m_pD3DDev, size, AfxGetAppSettings().fSPCPow2Tex);
00503 if(!m_pAllocator)
00504 return E_FAIL;
00505 }
00506
00507 hr = S_OK;
00508 m_pSubPicQueue = AfxGetAppSettings().nSPCSize > 0
00509 ? (ISubPicQueue*)new CSubPicQueue(AfxGetAppSettings().nSPCSize, m_pAllocator, &hr)
00510 : (ISubPicQueue*)new CSubPicQueueNoThread(m_pAllocator, &hr);
00511 if(!m_pSubPicQueue || FAILED(hr))
00512 return E_FAIL;
00513
00514 if(pSubPicProvider) m_pSubPicQueue->SetSubPicProvider(pSubPicProvider);
00515
00516 return S_OK;
00517 }
00518
00519 HRESULT CDX9AllocatorPresenter::AllocSurfaces()
00520 {
00521 CAutoLock cAutoLock(this);
00522
00523 AppSettings& s = AfxGetAppSettings();
00524
00525 m_pVideoTexture[0] = NULL;
00526 m_pVideoTexture[1] = NULL;
00527 m_pVideoSurface[0] = NULL;
00528 m_pVideoSurface[1] = NULL;
00529
00530 HRESULT hr;
00531
00532 if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D || s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
00533 {
00534 if(FAILED(hr = m_pD3DDev->CreateTexture(
00535 m_NativeVideoSize.cx, m_NativeVideoSize.cy, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
00536 D3DPOOL_DEFAULT, &m_pVideoTexture[0], NULL)))
00537 return hr;
00538
00539 if(FAILED(hr = m_pVideoTexture[0]->GetSurfaceLevel(0, &m_pVideoSurface[0])))
00540 return hr;
00541
00542 if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
00543 {
00544 if(FAILED(hr = m_pD3DDev->CreateTexture(
00545 m_NativeVideoSize.cx, m_NativeVideoSize.cy, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
00546 D3DPOOL_DEFAULT, &m_pVideoTexture[1], NULL)))
00547 return hr;
00548
00549 if(FAILED(hr = m_pVideoTexture[1]->GetSurfaceLevel(0, &m_pVideoSurface[1])))
00550 return hr;
00551 }
00552
00553 if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D)
00554 m_pVideoTexture[0] = NULL, m_pVideoTexture[1] = NULL;
00555 }
00556 else
00557 {
00558 if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
00559 m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8,
00560 D3DPOOL_DEFAULT, &m_pVideoSurface[0], NULL)))
00561 return hr;
00562 }
00563
00564 hr = m_pD3DDev->ColorFill(m_pVideoSurface[0], NULL, 0);
00565
00566 return S_OK;
00567 }
00568
00569 void CDX9AllocatorPresenter::DeleteSurfaces()
00570 {
00571 CAutoLock cAutoLock(this);
00572
00573 m_pVideoTexture[0] = m_pVideoTexture[1] = NULL;
00574 m_pVideoSurface[0] = m_pVideoSurface[1] = NULL;
00575 }
00576
00577 UINT CDX9AllocatorPresenter::GetAdapter(IDirect3D9 *pD3D)
00578 {
00579 if(m_hWnd == NULL || pD3D == NULL)
00580 return D3DADAPTER_DEFAULT;
00581
00582 HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
00583 if(hMonitor == NULL) return D3DADAPTER_DEFAULT;
00584
00585 for(UINT adp = 0, num_adp = pD3D->GetAdapterCount(); adp < num_adp; ++adp)
00586 {
00587 HMONITOR hAdpMon = pD3D->GetAdapterMonitor(adp);
00588 if(hAdpMon == hMonitor) return adp;
00589 }
00590
00591 return D3DADAPTER_DEFAULT;
00592 }
00593
00594
00595
00596 STDMETHODIMP CDX9AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
00597 {
00598 return E_NOTIMPL;
00599 }
00600
00601 static bool ClipToSurface(IDirect3DSurface9* pSurface, CRect& s, CRect& d)
00602 {
00603 D3DSURFACE_DESC d3dsd;
00604 ZeroMemory(&d3dsd, sizeof(d3dsd));
00605 if(FAILED(pSurface->GetDesc(&d3dsd)))
00606 return(false);
00607
00608 int w = d3dsd.Width, h = d3dsd.Height;
00609 int sw = s.Width(), sh = s.Height();
00610 int dw = d.Width(), dh = d.Height();
00611
00612 if(d.left >= w || d.right < 0 || d.top >= h || d.bottom < 0
00613 || sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0)
00614 {
00615 s.SetRectEmpty();
00616 d.SetRectEmpty();
00617 return(true);
00618 }
00619
00620 if(d.right > w) {s.right -= (d.right-w)*sw/dw; d.right = w;}
00621 if(d.bottom > h) {s.bottom -= (d.bottom-h)*sh/dh; d.bottom = h;}
00622 if(d.left < 0) {s.left += (0-d.left)*sw/dw; d.left = 0;}
00623 if(d.top < 0) {s.top += (0-d.top)*sh/dh; d.top = 0;}
00624
00625 return(true);
00626 }
00627
00628 STDMETHODIMP_(bool) CDX9AllocatorPresenter::Paint(bool fAll)
00629 {
00630 CAutoLock cAutoLock(this);
00631
00632 if(m_WindowRect.right <= m_WindowRect.left || m_WindowRect.bottom <= m_WindowRect.top
00633 || m_NativeVideoSize.cx <= 0 || m_NativeVideoSize.cy <= 0
00634 || !m_pVideoSurface)
00635 return(false);
00636
00637 HRESULT hr;
00638
00639 CRect rSrcVid(CPoint(0, 0), m_NativeVideoSize);
00640 CRect rDstVid(m_VideoRect);
00641
00642 CRect rSrcPri(CPoint(0, 0), m_WindowRect.Size());
00643 CRect rDstPri(m_WindowRect);
00644
00645 CComPtr<IDirect3DSurface9> pBackBuffer;
00646 m_pD3DDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
00647
00648 if(fAll)
00649 {
00650
00651
00652 hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
00653
00654
00655
00656 if(!rDstVid.IsRectEmpty())
00657 {
00658 if(m_pVideoTexture[0])
00659 {
00660 CComPtr<IDirect3DTexture9> pVideoTexture = m_pVideoTexture[0];
00661
00662 if(m_pVideoTexture[1] && m_pPixelShader)
00663 {
00664 static __int64 counter = 0;
00665 static long start = clock();
00666
00667 long stop = clock();
00668 long diff = stop - start;
00669
00670 if(diff >= 10*60*CLOCKS_PER_SEC) start = stop;
00671
00672 float fConstData[][4] =
00673 {
00674 {(float)m_NativeVideoSize.cx, (float)m_NativeVideoSize.cy, (float)(counter++), (float)diff / CLOCKS_PER_SEC},
00675 {1.0f / m_NativeVideoSize.cx, 1.0f / m_NativeVideoSize.cy, 0, 0},
00676 };
00677
00678 CComPtr<IDirect3DSurface9> pRT;
00679 hr = m_pD3DDev->GetRenderTarget(0, &pRT);
00680 hr = m_pD3DDev->SetRenderTarget(0, m_pVideoSurface[1]);
00681 hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, countof(fConstData));
00682 hr = m_pD3DDev->SetPixelShader(m_pPixelShader);
00683
00684 TextureBlt(m_pVideoTexture[0], rSrcVid, rSrcVid);
00685
00686 hr = m_pD3DDev->SetRenderTarget(0, pRT);
00687 hr = m_pD3DDev->SetPixelShader(NULL);
00688
00689 pVideoTexture = m_pVideoTexture[1];
00690 }
00691
00692 DWORD resizer = AfxGetAppSettings().iDX9Resizer;
00693 DWORD filter = resizer == 0 ? D3DTEXF_POINT : D3DTEXF_LINEAR;
00694
00695 CComPtr<IDirect3DPixelShader9> pResizerPixelShader;
00696
00697 if(rSrcVid != rDstVid)
00698 {
00699 if(resizer == 2 && m_pResizerPixelShader[0]) pResizerPixelShader = m_pResizerPixelShader[0];
00700 else if(resizer == 3 && m_pResizerPixelShader[1]) pResizerPixelShader = m_pResizerPixelShader[1];
00701 else if(resizer == 4 && m_pResizerPixelShader[2]) pResizerPixelShader = m_pResizerPixelShader[2];
00702 else if(resizer == 5 && m_pResizerPixelShader[3]) pResizerPixelShader = m_pResizerPixelShader[3];
00703 }
00704
00705 if(pResizerPixelShader)
00706 {
00707 float fConstData[][4] =
00708 {
00709 {(float)m_NativeVideoSize.cx, (float)m_NativeVideoSize.cy, 0, 0},
00710 {1.0f / m_NativeVideoSize.cx, 1.0f / m_NativeVideoSize.cy, 0, 0},
00711 {1.0f / m_NativeVideoSize.cx, 0, 0, 0},
00712 {0, 1.0f / m_NativeVideoSize.cy, 0, 0},
00713 };
00714
00715 hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, countof(fConstData));
00716 hr = m_pD3DDev->SetPixelShader(pResizerPixelShader);
00717
00718 filter = D3DTEXF_POINT;
00719 }
00720
00721 Vector v[4];
00722 Transform(rDstVid, v);
00723 hr = TextureBlt(pVideoTexture, v, rSrcVid, filter);
00724
00725 if(pResizerPixelShader)
00726 hr = m_pD3DDev->SetPixelShader(NULL);
00727 }
00728 else
00729 {
00730 if(pBackBuffer)
00731 {
00732 ClipToSurface(pBackBuffer, rSrcVid, rDstVid);
00733
00734 rSrcVid.left &= ~1; rSrcVid.right &= ~1;
00735 rSrcVid.top &= ~1; rSrcVid.bottom &= ~1;
00736 hr = m_pD3DDev->StretchRect(m_pVideoSurface[0], rSrcVid, pBackBuffer, rDstVid, m_Filter);
00737 }
00738 }
00739 }
00740
00741
00742
00743 AlphaBltSubPic(rSrcPri.Size());
00744 }
00745
00746 if(m_fVMRSyncFix)
00747 {
00748 D3DLOCKED_RECT lr;
00749 if(SUCCEEDED(pBackBuffer->LockRect(&lr, NULL, 0)))
00750 pBackBuffer->UnlockRect();
00751 }
00752
00753 hr = m_pD3DDev->Present(rSrcPri, rDstPri, NULL, NULL);
00754
00755 if(hr == D3DERR_DEVICELOST)
00756 {
00757 if(m_pD3DDev->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
00758 {
00759 DeleteSurfaces();
00760 if(FAILED(hr = CreateDevice()) || FAILED(hr = AllocSurfaces()))
00761 return(false);
00762 }
00763
00764 hr = S_OK;
00765 }
00766
00767 return(true);
00768 }
00769
00770 STDMETHODIMP CDX9AllocatorPresenter::GetDIB(BYTE* lpDib, DWORD* size)
00771 {
00772 CheckPointer(size, E_POINTER);
00773
00774 HRESULT hr;
00775
00776 D3DSURFACE_DESC desc;
00777 memset(&desc, 0, sizeof(desc));
00778 m_pVideoSurface[0]->GetDesc(&desc);
00779
00780 DWORD required = sizeof(BITMAPINFOHEADER) + (desc.Width * desc.Height * 32 >> 3);
00781 if(!lpDib) {*size = required; return S_OK;}
00782 if(*size < required) return E_OUTOFMEMORY;
00783 *size = required;
00784
00785 CComPtr<IDirect3DSurface9> pSurface = m_pVideoSurface[0];
00786 D3DLOCKED_RECT r;
00787 if(FAILED(hr = pSurface->LockRect(&r, NULL, D3DLOCK_READONLY)))
00788 {
00789 pSurface = NULL;
00790 if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pSurface, NULL))
00791 || FAILED(hr = m_pD3DDev->GetRenderTargetData(m_pVideoSurface[0], pSurface))
00792 || FAILED(hr = pSurface->LockRect(&r, NULL, D3DLOCK_READONLY)))
00793 return hr;
00794 }
00795
00796 BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)lpDib;
00797 memset(bih, 0, sizeof(BITMAPINFOHEADER));
00798 bih->biSize = sizeof(BITMAPINFOHEADER);
00799 bih->biWidth = desc.Width;
00800 bih->biHeight = desc.Height;
00801 bih->biBitCount = 32;
00802 bih->biPlanes = 1;
00803 bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount >> 3;
00804
00805 BitBltFromRGBToRGB(
00806 bih->biWidth, bih->biHeight,
00807 (BYTE*)(bih + 1), bih->biWidth*bih->biBitCount>>3, bih->biBitCount,
00808 (BYTE*)r.pBits + r.Pitch*(desc.Height-1), -(int)r.Pitch, 32);
00809
00810 pSurface->UnlockRect();
00811
00812 return S_OK;
00813 }
00814
00815 STDMETHODIMP CDX9AllocatorPresenter::SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget)
00816 {
00817 CAutoLock cAutoLock(this);
00818
00819 m_pPixelShader = NULL;
00820 m_pD3DDev->SetPixelShader(NULL);
00821
00822 if(!pSrcData || !pTarget)
00823 return E_INVALIDARG;
00824
00825 HRESULT hr = m_pPSC->CompileShader(pSrcData, "main", pTarget, 0, &m_pPixelShader);
00826 if(FAILED(hr)) return hr;
00827
00828 Paint(true);
00829
00830 return S_OK;
00831 }
00832
00833
00834
00835
00836
00837 #define MY_USER_ID 0x6ABE51
00838
00839 CVMR9AllocatorPresenter::CVMR9AllocatorPresenter(HWND hWnd, HRESULT& hr)
00840 : CDX9AllocatorPresenter(hWnd, hr)
00841 , m_fUseInternalTimer(true)
00842 {
00843 }
00844
00845 STDMETHODIMP CVMR9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00846 {
00847 CheckPointer(ppv, E_POINTER);
00848
00849 return
00850 QI(IVMRSurfaceAllocator9)
00851 QI(IVMRImagePresenter9)
00852 QI(IVMRWindowlessControl9)
00853 __super::NonDelegatingQueryInterface(riid, ppv);
00854 }
00855
00856 HRESULT CVMR9AllocatorPresenter::CreateDevice()
00857 {
00858 HRESULT hr = __super::CreateDevice();
00859 if(FAILED(hr)) return hr;
00860
00861 if(m_pIVMRSurfAllocNotify)
00862 {
00863 HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
00864 if(FAILED(hr = m_pIVMRSurfAllocNotify->ChangeD3DDevice(m_pD3DDev, hMonitor)))
00865 return(false);
00866 }
00867
00868 return hr;
00869 }
00870
00871 void CVMR9AllocatorPresenter::DeleteSurfaces()
00872 {
00873 CAutoLock cAutoLock(this);
00874
00875 m_pSurfaces.RemoveAll();
00876
00877 return __super::DeleteSurfaces();
00878 }
00879
00880
00881
00882 class COuterVMR9
00883 : public CUnknown
00884 , public IVideoWindow
00885 , public IBasicVideo2
00886 , public IVMRWindowlessControl
00887 {
00888 CComPtr<IUnknown> m_pVMR;
00889
00890 public:
00891
00892 COuterVMR9(const TCHAR* pName, LPUNKNOWN pUnk) : CUnknown(pName, pUnk)
00893 {
00894 m_pVMR.CoCreateInstance(CLSID_VideoMixingRenderer9, GetOwner());
00895 }
00896
00897 DECLARE_IUNKNOWN;
00898 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
00899 {
00900 HRESULT hr = m_pVMR ? m_pVMR->QueryInterface(riid, ppv) : E_NOINTERFACE;
00901
00902 if(m_pVMR && FAILED(hr))
00903 {
00904 if(riid == __uuidof(IVideoWindow))
00905 return GetInterface((IVideoWindow*)this, ppv);
00906 if(riid == __uuidof(IBasicVideo))
00907 return GetInterface((IBasicVideo*)this, ppv);
00908 if(riid == __uuidof(IBasicVideo2))
00909 return GetInterface((IBasicVideo2*)this, ppv);
00910
00911
00912 }
00913
00914 return SUCCEEDED(hr) ? hr : __super::NonDelegatingQueryInterface(riid, ppv);
00915 }
00916
00917
00918
00919 STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
00920 {
00921 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00922 {
00923 return pWC9->GetNativeVideoSize(lpWidth, lpHeight, lpARWidth, lpARHeight);
00924 }
00925
00926 return E_NOTIMPL;
00927 }
00928 STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
00929 STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
00930 STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;}
00931 STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
00932 {
00933 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00934 {
00935 return pWC9->GetVideoPosition(lpSRCRect, lpDSTRect);
00936 }
00937
00938 return E_NOTIMPL;
00939 }
00940 STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode)
00941 {
00942 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00943 {
00944 *lpAspectRatioMode = VMR_ARMODE_NONE;
00945 return S_OK;
00946 }
00947
00948 return E_NOTIMPL;
00949 }
00950 STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
00951 STDMETHODIMP SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
00952 STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
00953 STDMETHODIMP DisplayModeChanged() {return E_NOTIMPL;}
00954 STDMETHODIMP GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
00955 STDMETHODIMP SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
00956 STDMETHODIMP GetBorderColor(COLORREF* lpClr) {return E_NOTIMPL;}
00957 STDMETHODIMP SetColorKey(COLORREF Clr) {return E_NOTIMPL;}
00958 STDMETHODIMP GetColorKey(COLORREF* lpClr) {return E_NOTIMPL;}
00959
00960
00961 STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) {return E_NOTIMPL;}
00962 STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) {return E_NOTIMPL;}
00963 STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) {return E_NOTIMPL;}
00964 STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) {return E_NOTIMPL;}
00965 STDMETHODIMP put_Caption(BSTR strCaption) {return E_NOTIMPL;}
00966 STDMETHODIMP get_Caption(BSTR* strCaption) {return E_NOTIMPL;}
00967 STDMETHODIMP put_WindowStyle(long WindowStyle) {return E_NOTIMPL;}
00968 STDMETHODIMP get_WindowStyle(long* WindowStyle) {return E_NOTIMPL;}
00969 STDMETHODIMP put_WindowStyleEx(long WindowStyleEx) {return E_NOTIMPL;}
00970 STDMETHODIMP get_WindowStyleEx(long* WindowStyleEx) {return E_NOTIMPL;}
00971 STDMETHODIMP put_AutoShow(long AutoShow) {return E_NOTIMPL;}
00972 STDMETHODIMP get_AutoShow(long* AutoShow) {return E_NOTIMPL;}
00973 STDMETHODIMP put_WindowState(long WindowState) {return E_NOTIMPL;}
00974 STDMETHODIMP get_WindowState(long* WindowState) {return E_NOTIMPL;}
00975 STDMETHODIMP put_BackgroundPalette(long BackgroundPalette) {return E_NOTIMPL;}
00976 STDMETHODIMP get_BackgroundPalette(long* pBackgroundPalette) {return E_NOTIMPL;}
00977 STDMETHODIMP put_Visible(long Visible) {return E_NOTIMPL;}
00978 STDMETHODIMP get_Visible(long* pVisible) {return E_NOTIMPL;}
00979 STDMETHODIMP put_Left(long Left) {return E_NOTIMPL;}
00980 STDMETHODIMP get_Left(long* pLeft) {return E_NOTIMPL;}
00981 STDMETHODIMP put_Width(long Width) {return E_NOTIMPL;}
00982 STDMETHODIMP get_Width(long* pWidth)
00983 {
00984 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
00985 {
00986 CRect s, d;
00987 HRESULT hr = pWC9->GetVideoPosition(&s, &d);
00988 *pWidth = d.Width();
00989 return hr;
00990 }
00991
00992 return E_NOTIMPL;
00993 }
00994 STDMETHODIMP put_Top(long Top) {return E_NOTIMPL;}
00995 STDMETHODIMP get_Top(long* pTop) {return E_NOTIMPL;}
00996 STDMETHODIMP put_Height(long Height) {return E_NOTIMPL;}
00997 STDMETHODIMP get_Height(long* pHeight)
00998 {
00999 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01000 {
01001 CRect s, d;
01002 HRESULT hr = pWC9->GetVideoPosition(&s, &d);
01003 *pHeight = d.Height();
01004 return hr;
01005 }
01006
01007 return E_NOTIMPL;
01008 }
01009 STDMETHODIMP put_Owner(OAHWND Owner) {return E_NOTIMPL;}
01010 STDMETHODIMP get_Owner(OAHWND* Owner) {return E_NOTIMPL;}
01011 STDMETHODIMP put_MessageDrain(OAHWND Drain) {return E_NOTIMPL;}
01012 STDMETHODIMP get_MessageDrain(OAHWND* Drain) {return E_NOTIMPL;}
01013 STDMETHODIMP get_BorderColor(long* Color) {return E_NOTIMPL;}
01014 STDMETHODIMP put_BorderColor(long Color) {return E_NOTIMPL;}
01015 STDMETHODIMP get_FullScreenMode(long* FullScreenMode) {return E_NOTIMPL;}
01016 STDMETHODIMP put_FullScreenMode(long FullScreenMode) {return E_NOTIMPL;}
01017 STDMETHODIMP SetWindowForeground(long Focus) {return E_NOTIMPL;}
01018 STDMETHODIMP NotifyOwnerMessage(OAHWND hwnd, long uMsg, LONG_PTR wParam, LONG_PTR lParam) {return E_NOTIMPL;}
01019 STDMETHODIMP SetWindowPosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
01020 STDMETHODIMP GetWindowPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight) {return E_NOTIMPL;}
01021 STDMETHODIMP GetMinIdealImageSize(long* pWidth, long* pHeight) {return E_NOTIMPL;}
01022 STDMETHODIMP GetMaxIdealImageSize(long* pWidth, long* pHeight) {return E_NOTIMPL;}
01023 STDMETHODIMP GetRestorePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight) {return E_NOTIMPL;}
01024 STDMETHODIMP HideCursor(long HideCursor) {return E_NOTIMPL;}
01025 STDMETHODIMP IsCursorHidden(long* CursorHidden) {return E_NOTIMPL;}
01026
01027
01028 STDMETHODIMP get_AvgTimePerFrame(REFTIME* pAvgTimePerFrame) {return E_NOTIMPL;}
01029 STDMETHODIMP get_BitRate(long* pBitRate) {return E_NOTIMPL;}
01030 STDMETHODIMP get_BitErrorRate(long* pBitErrorRate) {return E_NOTIMPL;}
01031 STDMETHODIMP get_VideoWidth(long* pVideoWidth) {return E_NOTIMPL;}
01032 STDMETHODIMP get_VideoHeight(long* pVideoHeight) {return E_NOTIMPL;}
01033 STDMETHODIMP put_SourceLeft(long SourceLeft) {return E_NOTIMPL;}
01034 STDMETHODIMP get_SourceLeft(long* pSourceLeft) {return E_NOTIMPL;}
01035 STDMETHODIMP put_SourceWidth(long SourceWidth) {return E_NOTIMPL;}
01036 STDMETHODIMP get_SourceWidth(long* pSourceWidth) {return E_NOTIMPL;}
01037 STDMETHODIMP put_SourceTop(long SourceTop) {return E_NOTIMPL;}
01038 STDMETHODIMP get_SourceTop(long* pSourceTop) {return E_NOTIMPL;}
01039 STDMETHODIMP put_SourceHeight(long SourceHeight) {return E_NOTIMPL;}
01040 STDMETHODIMP get_SourceHeight(long* pSourceHeight) {return E_NOTIMPL;}
01041 STDMETHODIMP put_DestinationLeft(long DestinationLeft) {return E_NOTIMPL;}
01042 STDMETHODIMP get_DestinationLeft(long* pDestinationLeft) {return E_NOTIMPL;}
01043 STDMETHODIMP put_DestinationWidth(long DestinationWidth) {return E_NOTIMPL;}
01044 STDMETHODIMP get_DestinationWidth(long* pDestinationWidth) {return E_NOTIMPL;}
01045 STDMETHODIMP put_DestinationTop(long DestinationTop) {return E_NOTIMPL;}
01046 STDMETHODIMP get_DestinationTop(long* pDestinationTop) {return E_NOTIMPL;}
01047 STDMETHODIMP put_DestinationHeight(long DestinationHeight) {return E_NOTIMPL;}
01048 STDMETHODIMP get_DestinationHeight(long* pDestinationHeight) {return E_NOTIMPL;}
01049 STDMETHODIMP SetSourcePosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
01050 STDMETHODIMP GetSourcePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight)
01051 {
01052
01053 {
01054 *pLeft = *pTop = 0;
01055 return GetVideoSize(pWidth, pHeight);
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 return E_NOTIMPL;
01070 }
01071 STDMETHODIMP SetDefaultSourcePosition() {return E_NOTIMPL;}
01072 STDMETHODIMP SetDestinationPosition(long Left, long Top, long Width, long Height) {return E_NOTIMPL;}
01073 STDMETHODIMP GetDestinationPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight)
01074 {
01075 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01076 {
01077 CRect s, d;
01078 HRESULT hr = pWC9->GetVideoPosition(&s, &d);
01079 *pLeft = d.left;
01080 *pTop = d.top;
01081 *pWidth = d.Width();
01082 *pHeight = d.Height();
01083 return hr;
01084 }
01085
01086 return E_NOTIMPL;
01087 }
01088 STDMETHODIMP SetDefaultDestinationPosition() {return E_NOTIMPL;}
01089 STDMETHODIMP GetVideoSize(long* pWidth, long* pHeight)
01090 {
01091 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01092 {
01093 LONG aw, ah;
01094
01095
01096 HRESULT hr = pWC9->GetNativeVideoSize(pWidth, pHeight, &aw, &ah);
01097 *pWidth = *pHeight * aw / ah;
01098 return hr;
01099 }
01100
01101 return E_NOTIMPL;
01102 }
01103 STDMETHODIMP GetVideoPaletteEntries(long StartIndex, long Entries, long* pRetrieved, long* pPalette) {return E_NOTIMPL;}
01104 STDMETHODIMP GetCurrentImage(long* pBufferSize, long* pDIBImage) {return E_NOTIMPL;}
01105 STDMETHODIMP IsUsingDefaultSource() {return E_NOTIMPL;}
01106 STDMETHODIMP IsUsingDefaultDestination() {return E_NOTIMPL;}
01107
01108 STDMETHODIMP GetPreferredAspectRatio(long* plAspectX, long* plAspectY)
01109 {
01110 if(CComQIPtr<IVMRWindowlessControl9> pWC9 = m_pVMR)
01111 {
01112 LONG w, h;
01113 return pWC9->GetNativeVideoSize(&w, &h, plAspectX, plAspectY);
01114 }
01115
01116 return E_NOTIMPL;
01117 }
01118 };
01119
01120 STDMETHODIMP CVMR9AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
01121 {
01122 CheckPointer(ppRenderer, E_POINTER);
01123
01124 *ppRenderer = NULL;
01125
01126 HRESULT hr;
01127
01128 do
01129 {
01130 CMacrovisionKicker* pMK = new CMacrovisionKicker(NAME("CMacrovisionKicker"), NULL);
01131 CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)pMK;
01132 pMK->SetInner((IUnknown*)(INonDelegatingUnknown*)new COuterVMR9(NAME("COuterVMR9"), pUnk));
01133 CComQIPtr<IBaseFilter> pBF = pUnk;
01134
01135
01136
01137
01138
01139 CComQIPtr<IVMRFilterConfig9> pConfig = pBF;
01140 if(!pConfig)
01141 break;
01142
01143 if(FAILED(hr = pConfig->SetRenderingMode(VMR9Mode_Renderless)))
01144 break;
01145
01146 CComQIPtr<IVMRSurfaceAllocatorNotify9> pSAN = pBF;
01147 if(!pSAN)
01148 break;
01149
01150 if(FAILED(hr = pSAN->AdviseSurfaceAllocator(MY_USER_ID, static_cast<IVMRSurfaceAllocator9*>(this)))
01151 || FAILED(hr = AdviseNotify(pSAN)))
01152 break;
01153
01154 CComPtr<IPin> pPin = GetFirstPin(pBF);
01155 HookNewSegment((IPinC*)(IPin*)pPin);
01156
01157 *ppRenderer = (IUnknown*)pBF.Detach();
01158
01159 return S_OK;
01160 }
01161 while(0);
01162
01163 return E_FAIL;
01164 }
01165
01166 STDMETHODIMP_(void) CVMR9AllocatorPresenter::SetTime(REFERENCE_TIME rtNow)
01167 {
01168 m_fUseInternalTimer = false;
01169 __super::SetTime(rtNow);
01170 }
01171
01172
01173
01174 STDMETHODIMP CVMR9AllocatorPresenter::InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo* lpAllocInfo, DWORD* lpNumBuffers)
01175 {
01176 if(!lpAllocInfo || !lpNumBuffers)
01177 return E_POINTER;
01178
01179 if(!m_pIVMRSurfAllocNotify)
01180 return E_FAIL;
01181
01182
01183 if(lpAllocInfo->Format == '21VY' || lpAllocInfo->Format == '024Y')
01184 return E_FAIL;
01185
01186 DeleteSurfaces();
01187 m_pSurfaces.SetCount(*lpNumBuffers);
01188
01189 HRESULT hr;
01190
01191 hr = m_pIVMRSurfAllocNotify->AllocateSurfaceHelper(lpAllocInfo, lpNumBuffers, &m_pSurfaces[0]);
01192 if(FAILED(hr))
01193 return hr;
01194
01195 m_NativeVideoSize = CSize(lpAllocInfo->dwWidth, abs((int)lpAllocInfo->dwHeight));
01196 m_AspectRatio = m_NativeVideoSize;
01197 int arx = lpAllocInfo->szAspectRatio.cx, ary = lpAllocInfo->szAspectRatio.cy;
01198 if(arx > 0 && ary > 0) m_AspectRatio.SetSize(arx, ary);
01199
01200 if(FAILED(hr = AllocSurfaces()))
01201 return hr;
01202
01203
01204 if(FAILED(hr = m_pD3DDev->StretchRect(m_pSurfaces[0], NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE)))
01205 {
01206 DeleteSurfaces();
01207 return E_FAIL;
01208 }
01209
01210 hr = m_pD3DDev->ColorFill(m_pVideoSurface[0], NULL, 0);
01211
01212 return hr;
01213 }
01214
01215 STDMETHODIMP CVMR9AllocatorPresenter::TerminateDevice(DWORD_PTR dwUserID)
01216 {
01217 DeleteSurfaces();
01218 return S_OK;
01219 }
01220
01221 STDMETHODIMP CVMR9AllocatorPresenter::GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9** lplpSurface)
01222 {
01223 if(!lplpSurface)
01224 return E_POINTER;
01225
01226 if(SurfaceIndex >= m_pSurfaces.GetCount())
01227 return E_FAIL;
01228
01229 CAutoLock cAutoLock(this);
01230
01231 (*lplpSurface = m_pSurfaces[SurfaceIndex])->AddRef();
01232
01233 return S_OK;
01234 }
01235
01236 STDMETHODIMP CVMR9AllocatorPresenter::AdviseNotify(IVMRSurfaceAllocatorNotify9* lpIVMRSurfAllocNotify)
01237 {
01238 CAutoLock cAutoLock(this);
01239
01240 m_pIVMRSurfAllocNotify = lpIVMRSurfAllocNotify;
01241
01242 HRESULT hr;
01243 HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
01244 if(FAILED(hr = m_pIVMRSurfAllocNotify->SetD3DDevice(m_pD3DDev, hMonitor)))
01245 return hr;
01246
01247 return S_OK;
01248 }
01249
01250
01251
01252 STDMETHODIMP CVMR9AllocatorPresenter::StartPresenting(DWORD_PTR dwUserID)
01253 {
01254 CAutoLock cAutoLock(this);
01255
01256 ASSERT(m_pD3DDev);
01257
01258 return m_pD3DDev ? S_OK : E_FAIL;
01259 }
01260
01261 STDMETHODIMP CVMR9AllocatorPresenter::StopPresenting(DWORD_PTR dwUserID)
01262 {
01263 return S_OK;
01264 }
01265
01266 STDMETHODIMP CVMR9AllocatorPresenter::PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo* lpPresInfo)
01267 {
01268 HRESULT hr;
01269
01270 {
01271 if(!m_pIVMRSurfAllocNotify)
01272 return E_FAIL;
01273
01274 D3DDEVICE_CREATION_PARAMETERS Parameters;
01275 if(FAILED(m_pD3DDev->GetCreationParameters(&Parameters)))
01276 {
01277 ASSERT(0);
01278 return E_FAIL;
01279 }
01280
01281 HMONITOR hCurMonitor = m_pD3D->GetAdapterMonitor(Parameters.AdapterOrdinal);
01282 HMONITOR hMonitor = m_pD3D->GetAdapterMonitor(GetAdapter(m_pD3D));
01283
01284 if(hMonitor != hCurMonitor)
01285 {
01286 ASSERT(0);
01287 }
01288 }
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299 {
01300 if(!lpPresInfo || !lpPresInfo->lpSurf)
01301 return E_POINTER;
01302
01303 CAutoLock cAutoLock(this);
01304
01305 hr = m_pD3DDev->StretchRect(lpPresInfo->lpSurf, NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE);
01306
01307 if(lpPresInfo->rtEnd > lpPresInfo->rtStart)
01308 {
01309 REFERENCE_TIME rtTimePerFrame = lpPresInfo->rtEnd - lpPresInfo->rtStart;
01310 m_fps = 10000000.0 / rtTimePerFrame;
01311
01312 if(m_pSubPicQueue)
01313 {
01314 m_pSubPicQueue->SetFPS(m_fps);
01315 if(m_fUseInternalTimer) __super::SetTime(g_tSegmentStart + lpPresInfo->rtStart);
01316 }
01317 }
01318
01319 CSize VideoSize = m_NativeVideoSize;
01320 int arx = lpPresInfo->szAspectRatio.cx, ary = lpPresInfo->szAspectRatio.cy;
01321 if(arx > 0 && ary > 0) VideoSize.cx = VideoSize.cy*arx/ary;
01322 if(VideoSize != GetVideoSize())
01323 {
01324 m_AspectRatio.SetSize(arx, ary);
01325 AfxGetApp()->m_pMainWnd->PostMessage(WM_REARRANGERENDERLESS);
01326 }
01327
01328 Paint(true);
01329
01330 hr = S_OK;
01331 }
01332
01333 return hr;
01334 }
01335
01336
01337
01338
01339
01340
01341
01342 STDMETHODIMP CVMR9AllocatorPresenter::GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
01343 {
01344 if(lpWidth) *lpWidth = m_NativeVideoSize.cx;
01345 if(lpHeight) *lpHeight = m_NativeVideoSize.cy;
01346 if(lpARWidth) *lpARWidth = m_AspectRatio.cx;
01347 if(lpARHeight) *lpARHeight = m_AspectRatio.cy;
01348 return S_OK;
01349 }
01350 STDMETHODIMP CVMR9AllocatorPresenter::GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
01351 STDMETHODIMP CVMR9AllocatorPresenter::GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
01352 STDMETHODIMP CVMR9AllocatorPresenter::SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;}
01353 STDMETHODIMP CVMR9AllocatorPresenter::GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
01354 {
01355 CopyRect(lpSRCRect, CRect(CPoint(0, 0), m_NativeVideoSize));
01356 CopyRect(lpDSTRect, &m_VideoRect);
01357 return S_OK;
01358 }
01359 STDMETHODIMP CVMR9AllocatorPresenter::GetAspectRatioMode(DWORD* lpAspectRatioMode)
01360 {
01361 if(lpAspectRatioMode) *lpAspectRatioMode = AM_ARMODE_STRETCHED;
01362 return S_OK;
01363 }
01364 STDMETHODIMP CVMR9AllocatorPresenter::SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
01365 STDMETHODIMP CVMR9AllocatorPresenter::SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
01366 STDMETHODIMP CVMR9AllocatorPresenter::RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
01367 STDMETHODIMP CVMR9AllocatorPresenter::DisplayModeChanged() {return E_NOTIMPL;}
01368 STDMETHODIMP CVMR9AllocatorPresenter::GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
01369 STDMETHODIMP CVMR9AllocatorPresenter::SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
01370 STDMETHODIMP CVMR9AllocatorPresenter::GetBorderColor(COLORREF* lpClr)
01371 {
01372 if(lpClr) *lpClr = 0;
01373 return S_OK;
01374 }
01375
01376
01377
01378
01379
01380 CRM9AllocatorPresenter::CRM9AllocatorPresenter(HWND hWnd, HRESULT& hr)
01381 : CDX9AllocatorPresenter(hWnd, hr)
01382 {
01383 }
01384
01385 STDMETHODIMP CRM9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
01386 {
01387 CheckPointer(ppv, E_POINTER);
01388
01389 return
01390 QI2(IRMAVideoSurface)
01391 __super::NonDelegatingQueryInterface(riid, ppv);
01392 }
01393
01394 HRESULT CRM9AllocatorPresenter::AllocSurfaces()
01395 {
01396 CAutoLock cAutoLock(this);
01397
01398 m_pVideoSurfaceOff = NULL;
01399 m_pVideoSurfaceYUY2 = NULL;
01400
01401 HRESULT hr;
01402
01403 if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
01404 m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8,
01405 D3DPOOL_DEFAULT, &m_pVideoSurfaceOff, NULL)))
01406 return hr;
01407
01408 m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
01409
01410 if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
01411 m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_YUY2,
01412 D3DPOOL_DEFAULT, &m_pVideoSurfaceYUY2, NULL)))
01413 m_pVideoSurfaceYUY2 = NULL;
01414
01415 if(m_pVideoSurfaceYUY2)
01416 {
01417 m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0x80108010);
01418 }
01419
01420 return __super::AllocSurfaces();
01421 }
01422
01423 void CRM9AllocatorPresenter::DeleteSurfaces()
01424 {
01425 CAutoLock cAutoLock(this);
01426 m_pVideoSurfaceOff = NULL;
01427 m_pVideoSurfaceYUY2 = NULL;
01428 __super::DeleteSurfaces();
01429 }
01430
01431
01432
01433 STDMETHODIMP CRM9AllocatorPresenter::Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect)
01434 {
01435 if(!m_pVideoSurface || !m_pVideoSurfaceOff)
01436 return E_FAIL;
01437
01438 bool fRGB = false;
01439 bool fYUY2 = false;
01440
01441 CRect src((RECT*)&inSrcRect), dst((RECT*)&inDestRect), src2(CPoint(0,0), src.Size());
01442 if(src.Width() > dst.Width() || src.Height() > dst.Height())
01443 return E_FAIL;
01444
01445 D3DSURFACE_DESC d3dsd;
01446 ZeroMemory(&d3dsd, sizeof(d3dsd));
01447 if(FAILED(m_pVideoSurfaceOff->GetDesc(&d3dsd)))
01448 return E_FAIL;
01449
01450 int dbpp =
01451 d3dsd.Format == D3DFMT_R8G8B8 || d3dsd.Format == D3DFMT_X8R8G8B8 || d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 :
01452 d3dsd.Format == D3DFMT_R5G6B5 ? 16 : 0;
01453
01454 if(pBitmapInfo->biCompression == '024I')
01455 {
01456 DWORD pitch = pBitmapInfo->biWidth;
01457 DWORD size = pitch*abs(pBitmapInfo->biHeight);
01458
01459 BYTE* y = pImageData + src.top*pitch + src.left;
01460 BYTE* u = pImageData + size + src.top*(pitch/2) + src.left/2;
01461 BYTE* v = pImageData + size + size/4 + src.top*(pitch/2) + src.left/2;
01462
01463 if(m_pVideoSurfaceYUY2)
01464 {
01465 D3DLOCKED_RECT r;
01466 if(SUCCEEDED(m_pVideoSurfaceYUY2->LockRect(&r, src2, 0)))
01467 {
01468 BitBltFromI420ToYUY2(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, y, u, v, pitch);
01469 m_pVideoSurfaceYUY2->UnlockRect();
01470 fYUY2 = true;
01471 }
01472 }
01473 else
01474 {
01475 D3DLOCKED_RECT r;
01476 if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
01477 {
01478 BitBltFromI420ToRGB(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, dbpp, y, u, v, pitch);
01479 m_pVideoSurfaceOff->UnlockRect();
01480 fRGB = true;
01481 }
01482 }
01483 }
01484 else if(pBitmapInfo->biCompression == '2YUY')
01485 {
01486 DWORD w = pBitmapInfo->biWidth;
01487 DWORD h = abs(pBitmapInfo->biHeight);
01488 DWORD pitch = pBitmapInfo->biWidth*2;
01489
01490 BYTE* yvyu = pImageData + src.top*pitch + src.left*2;
01491
01492 if(m_pVideoSurfaceYUY2)
01493 {
01494 D3DLOCKED_RECT r;
01495 if(SUCCEEDED(m_pVideoSurfaceYUY2->LockRect(&r, src2, 0)))
01496 {
01497 BitBltFromYUY2ToYUY2(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, yvyu, pitch);
01498 m_pVideoSurfaceYUY2->UnlockRect();
01499 fYUY2 = true;
01500 }
01501 }
01502 else
01503 {
01504 D3DLOCKED_RECT r;
01505 if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
01506 {
01507 BitBltFromYUY2ToRGB(src.Width(), src.Height(), (BYTE*)r.pBits, r.Pitch, dbpp, yvyu, pitch);
01508 m_pVideoSurfaceOff->UnlockRect();
01509 fRGB = true;
01510 }
01511 }
01512 }
01513 else if(pBitmapInfo->biCompression == 0 || pBitmapInfo->biCompression == 3
01514 || pBitmapInfo->biCompression == 'BGRA')
01515 {
01516 DWORD w = pBitmapInfo->biWidth;
01517 DWORD h = abs(pBitmapInfo->biHeight);
01518 DWORD pitch = pBitmapInfo->biWidth*pBitmapInfo->biBitCount>>3;
01519
01520 BYTE* rgb = pImageData + src.top*pitch + src.left*(pBitmapInfo->biBitCount>>3);
01521
01522 D3DLOCKED_RECT r;
01523 if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, src2, 0)))
01524 {
01525 BYTE* pBits = (BYTE*)r.pBits;
01526 if(pBitmapInfo->biHeight > 0) {pBits += r.Pitch*(src.Height()-1); r.Pitch = -r.Pitch;}
01527 BitBltFromRGBToRGB(src.Width(), src.Height(), pBits, r.Pitch, dbpp, rgb, pitch, pBitmapInfo->biBitCount);
01528 m_pVideoSurfaceOff->UnlockRect();
01529 fRGB = true;
01530 }
01531 }
01532
01533 if(!fRGB && !fYUY2)
01534 {
01535 m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
01536
01537 HDC hDC;
01538 if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
01539 {
01540 CString str;
01541 str.Format(_T("Sorry, this format is not supported"));
01542
01543 SetBkColor(hDC, 0);
01544 SetTextColor(hDC, 0x404040);
01545 TextOut(hDC, 10, 10, str, str.GetLength());
01546
01547 m_pVideoSurfaceOff->ReleaseDC(hDC);
01548
01549 fRGB = true;
01550 }
01551 }
01552
01553 HRESULT hr;
01554
01555 if(fRGB)
01556 hr = m_pD3DDev->StretchRect(m_pVideoSurfaceOff, src2, m_pVideoSurface[0], dst, D3DTEXF_NONE);
01557 if(fYUY2)
01558 hr = m_pD3DDev->StretchRect(m_pVideoSurfaceYUY2, src2, m_pVideoSurface[0], dst, D3DTEXF_NONE);
01559
01560 Paint(true);
01561
01562 return PNR_OK;
01563 }
01564
01565 STDMETHODIMP CRM9AllocatorPresenter::BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo)
01566 {
01567 CAutoLock cAutoLock(this);
01568 DeleteSurfaces();
01569 m_NativeVideoSize = m_AspectRatio = CSize(pBitmapInfo->biWidth, abs(pBitmapInfo->biHeight));
01570 if(FAILED(AllocSurfaces())) return E_FAIL;
01571 return PNR_NOTIMPL;
01572 }
01573
01574 STDMETHODIMP CRM9AllocatorPresenter::OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect)
01575 {
01576 return PNR_NOTIMPL;
01577 }
01578
01579 STDMETHODIMP CRM9AllocatorPresenter::EndOptimizedBlt()
01580 {
01581 return PNR_NOTIMPL;
01582 }
01583
01584 STDMETHODIMP CRM9AllocatorPresenter::GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType)
01585 {
01586 return PNR_NOTIMPL;
01587 }
01588
01589 STDMETHODIMP CRM9AllocatorPresenter::GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType)
01590 {
01591 ulType = RMA_I420;
01592 return PNR_OK;
01593 }
01594
01595
01596
01597
01598
01599 CQT9AllocatorPresenter::CQT9AllocatorPresenter(HWND hWnd, HRESULT& hr)
01600 : CDX9AllocatorPresenter(hWnd, hr)
01601 {
01602 }
01603
01604 STDMETHODIMP CQT9AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
01605 {
01606 CheckPointer(ppv, E_POINTER);
01607
01608 return
01609 QI(IQTVideoSurface)
01610 __super::NonDelegatingQueryInterface(riid, ppv);
01611 }
01612
01613 HRESULT CQT9AllocatorPresenter::AllocSurfaces()
01614 {
01615 HRESULT hr;
01616
01617 m_pVideoSurfaceOff = NULL;
01618
01619 if(FAILED(hr = m_pD3DDev->CreateOffscreenPlainSurface(
01620 m_NativeVideoSize.cx, m_NativeVideoSize.cy, D3DFMT_X8R8G8B8,
01621 D3DPOOL_DEFAULT, &m_pVideoSurfaceOff, NULL)))
01622 return hr;
01623
01624 return __super::AllocSurfaces();
01625 }
01626
01627 void CQT9AllocatorPresenter::DeleteSurfaces()
01628 {
01629 m_pVideoSurfaceOff = NULL;
01630
01631 __super::DeleteSurfaces();
01632 }
01633
01634
01635
01636 STDMETHODIMP CQT9AllocatorPresenter::BeginBlt(const BITMAP& bm)
01637 {
01638 CAutoLock cAutoLock(this);
01639 DeleteSurfaces();
01640 m_NativeVideoSize = m_AspectRatio = CSize(bm.bmWidth, abs(bm.bmHeight));
01641 if(FAILED(AllocSurfaces())) return E_FAIL;
01642 return S_OK;
01643 }
01644
01645 STDMETHODIMP CQT9AllocatorPresenter::DoBlt(const BITMAP& bm)
01646 {
01647 if(!m_pVideoSurface || !m_pVideoSurfaceOff)
01648 return E_FAIL;
01649
01650 bool fOk = false;
01651
01652 D3DSURFACE_DESC d3dsd;
01653 ZeroMemory(&d3dsd, sizeof(d3dsd));
01654 if(FAILED(m_pVideoSurfaceOff->GetDesc(&d3dsd)))
01655 return E_FAIL;
01656
01657 int w = bm.bmWidth;
01658 int h = abs(bm.bmHeight);
01659 int bpp = bm.bmBitsPixel;
01660 int dbpp =
01661 d3dsd.Format == D3DFMT_R8G8B8 || d3dsd.Format == D3DFMT_X8R8G8B8 || d3dsd.Format == D3DFMT_A8R8G8B8 ? 32 :
01662 d3dsd.Format == D3DFMT_R5G6B5 ? 16 : 0;
01663
01664 if((bpp == 16 || bpp == 24 || bpp == 32) && w == d3dsd.Width && h == d3dsd.Height)
01665 {
01666 D3DLOCKED_RECT r;
01667 if(SUCCEEDED(m_pVideoSurfaceOff->LockRect(&r, NULL, 0)))
01668 {
01669 BitBltFromRGBToRGB(
01670 w, h,
01671 (BYTE*)r.pBits, r.Pitch, dbpp,
01672 (BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmBitsPixel);
01673 m_pVideoSurfaceOff->UnlockRect();
01674 fOk = true;
01675 }
01676 }
01677
01678 if(!fOk)
01679 {
01680 m_pD3DDev->ColorFill(m_pVideoSurfaceOff, NULL, 0);
01681
01682 HDC hDC;
01683 if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
01684 {
01685 CString str;
01686 str.Format(_T("Sorry, this color format is not supported"));
01687
01688 SetBkColor(hDC, 0);
01689 SetTextColor(hDC, 0x404040);
01690 TextOut(hDC, 10, 10, str, str.GetLength());
01691
01692 m_pVideoSurfaceOff->ReleaseDC(hDC);
01693 }
01694 }
01695
01696 m_pD3DDev->StretchRect(m_pVideoSurfaceOff, NULL, m_pVideoSurface[0], NULL, D3DTEXF_NONE);
01697
01698 Paint(true);
01699
01700 return S_OK;
01701 }