DX7AllocatorPresenter.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:37k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "mplayerc.h"
  23. #include <atlbase.h>
  24. #include <atlcoll.h>
  25. #include "....DSUtilDSUtil.h"
  26. #include <initguid.h>
  27. #include "DX7AllocatorPresenter.h"
  28. #include <ddraw.h>
  29. #include <d3d.h>
  30. #include "....SubPicDX7SubPic.h"
  31. #include "......includeRealMediapntypes.h"
  32. #include "......includeRealMediapnwintyp.h"
  33. #include "......includeRealMediapncom.h"
  34. #include "......includeRealMediarmavsurf.h"
  35. #include "IQTVideoSurface.h"
  36. #include "IPinHook.h"
  37. bool IsVMR7InGraph(IFilterGraph* pFG)
  38. {
  39. BeginEnumFilters(pFG, pEF, pBF)
  40. if(CComQIPtr<IVMRWindowlessControl>(pBF)) return(true);
  41. EndEnumFilters
  42. return(false);
  43. }
  44. namespace DSObjects
  45. {
  46. class CDX7AllocatorPresenter
  47. : public ISubPicAllocatorPresenterImpl
  48. {
  49. protected:
  50. CSize m_ScreenSize;
  51. CComPtr<IDirectDraw7> m_pDD;
  52. CComQIPtr<IDirect3D7, &IID_IDirect3D7> m_pD3D;
  53.     CComPtr<IDirect3DDevice7> m_pD3DDev;
  54. CComPtr<IDirectDrawSurface7> m_pPrimary, m_pBackBuffer;
  55. CComPtr<IDirectDrawSurface7> m_pVideoTexture, m_pVideoSurface;
  56.     virtual HRESULT CreateDevice();
  57. virtual HRESULT AllocSurfaces();
  58. virtual void DeleteSurfaces();
  59. public:
  60. CDX7AllocatorPresenter(HWND hWnd, HRESULT& hr);
  61. // ISubPicAllocatorPresenter
  62. STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
  63. STDMETHODIMP_(bool) Paint(bool fAll);
  64. STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size);
  65. };
  66. class CVMR7AllocatorPresenter
  67. : public CDX7AllocatorPresenter
  68. , public IVMRSurfaceAllocator
  69. , public IVMRImagePresenter
  70. , public IVMRWindowlessControl
  71. {
  72. CComPtr<IVMRSurfaceAllocatorNotify> m_pIVMRSurfAllocNotify;
  73. CComPtr<IVMRSurfaceAllocator> m_pSA;
  74. HRESULT CreateDevice();
  75. void DeleteSurfaces();
  76. bool m_fUseInternalTimer;
  77. public:
  78. CVMR7AllocatorPresenter(HWND hWnd, HRESULT& hr);
  79. DECLARE_IUNKNOWN
  80.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
  81. // ISubPicAllocatorPresenter
  82. STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
  83. STDMETHODIMP_(void) SetTime(REFERENCE_TIME rtNow);
  84. // IVMRSurfaceAllocator
  85.     STDMETHODIMP AllocateSurface(DWORD_PTR dwUserID, VMRALLOCATIONINFO* lpAllocInfo, DWORD* lpdwBuffer, LPDIRECTDRAWSURFACE7* lplpSurface);
  86.     STDMETHODIMP FreeSurface(DWORD_PTR dwUserID);
  87.     STDMETHODIMP PrepareSurface(DWORD_PTR dwUserID, IDirectDrawSurface7* lpSurface, DWORD dwSurfaceFlags);
  88.     STDMETHODIMP AdviseNotify(IVMRSurfaceAllocatorNotify* lpIVMRSurfAllocNotify);
  89. // IVMRImagePresenter
  90.     STDMETHODIMP StartPresenting(DWORD_PTR dwUserID);
  91.     STDMETHODIMP StopPresenting(DWORD_PTR dwUserID);
  92.     STDMETHODIMP PresentImage(DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo);
  93. // IVMRWindowlessControl
  94. STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight);
  95. STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
  96. STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
  97. STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect);
  98.     STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect);
  99. STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode);
  100. STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode);
  101. STDMETHODIMP SetVideoClippingWindow(HWND hwnd);
  102. STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc);
  103. STDMETHODIMP DisplayModeChanged();
  104. STDMETHODIMP GetCurrentImage(BYTE** lpDib);
  105. STDMETHODIMP SetBorderColor(COLORREF Clr);
  106. STDMETHODIMP GetBorderColor(COLORREF* lpClr);
  107. STDMETHODIMP SetColorKey(COLORREF Clr);
  108. STDMETHODIMP GetColorKey(COLORREF* lpClr);
  109. };
  110. class CRM7AllocatorPresenter
  111. : public CDX7AllocatorPresenter
  112. , public IRMAVideoSurface
  113. {
  114. CComPtr<IDirectDrawSurface7> m_pVideoSurfaceOff;
  115. CComPtr<IDirectDrawSurface7> m_pVideoSurfaceYUY2;
  116.     RMABitmapInfoHeader m_bitmapInfo;
  117.     RMABitmapInfoHeader m_lastBitmapInfo;
  118. protected:
  119. HRESULT AllocSurfaces();
  120. void DeleteSurfaces();
  121. public:
  122. CRM7AllocatorPresenter(HWND hWnd, HRESULT& hr);
  123. DECLARE_IUNKNOWN
  124.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
  125. // IRMAVideoSurface
  126.     STDMETHODIMP Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect);
  127. STDMETHODIMP BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo);
  128. STDMETHODIMP OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect);
  129. STDMETHODIMP EndOptimizedBlt();
  130. STDMETHODIMP GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType);
  131.     STDMETHODIMP GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType);
  132. };
  133. class CQT7AllocatorPresenter
  134. : public CDX7AllocatorPresenter
  135. , public IQTVideoSurface
  136. {
  137. CComPtr<IDirectDrawSurface7> m_pVideoSurfaceOff;
  138. protected:
  139. HRESULT AllocSurfaces();
  140. void DeleteSurfaces();
  141. public:
  142. CQT7AllocatorPresenter(HWND hWnd, HRESULT& hr);
  143. DECLARE_IUNKNOWN
  144.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
  145. // IQTVideoSurface
  146. STDMETHODIMP BeginBlt(const BITMAP& bm);
  147. STDMETHODIMP DoBlt(const BITMAP& bm);
  148. };
  149. }
  150. using namespace DSObjects;
  151. //
  152. HRESULT CreateAP7(const CLSID& clsid, HWND hWnd, ISubPicAllocatorPresenter** ppAP)
  153. {
  154. CheckPointer(ppAP, E_POINTER);
  155. *ppAP = NULL;
  156. HRESULT hr;
  157. if(clsid == CLSID_VMR7AllocatorPresenter && !(*ppAP = new CVMR7AllocatorPresenter(hWnd, hr))
  158. || clsid == CLSID_RM7AllocatorPresenter && !(*ppAP = new CRM7AllocatorPresenter(hWnd, hr))
  159. || clsid == CLSID_QT7AllocatorPresenter && !(*ppAP = new CQT7AllocatorPresenter(hWnd, hr)))
  160. return E_OUTOFMEMORY;
  161. if(*ppAP == NULL)
  162. return E_FAIL;
  163. (*ppAP)->AddRef();
  164. if(FAILED(hr))
  165. {
  166. (*ppAP)->Release();
  167. *ppAP = NULL;
  168. }
  169. return hr;
  170. }
  171. //
  172. static HRESULT TextureBlt(CComPtr<IDirect3DDevice7> pD3DDev, CComPtr<IDirectDrawSurface7> pTexture, Vector dst[4], CRect src)
  173. {
  174. if(!pTexture)
  175. return E_POINTER;
  176. HRESULT hr;
  177.     do
  178. {
  179. DDSURFACEDESC2 ddsd;
  180. INITDDSTRUCT(ddsd);
  181. if(FAILED(hr = pTexture->GetSurfaceDesc(&ddsd)))
  182. break;
  183.         float w = (float)ddsd.dwWidth;
  184.         float h = (float)ddsd.dwHeight;
  185. struct
  186. {
  187. float x, y, z, rhw;
  188. float tu, tv;
  189. }
  190. pVertices[] =
  191. {
  192. {(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},
  193. {(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},
  194. {(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},
  195. {(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},
  196. };
  197. for(int i = 0; i < countof(pVertices); i++)
  198. {
  199. pVertices[i].x -= 0.5;
  200. pVertices[i].y -= 0.5;
  201. }
  202.         hr = pD3DDev->SetTexture(0, pTexture);
  203.         pD3DDev->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
  204.         pD3DDev->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
  205.         pD3DDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, FALSE);
  206. pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE); 
  207.         pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
  208.         pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
  209.         pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
  210.         pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
  211. //
  212.         if(FAILED(hr = pD3DDev->BeginScene()))
  213. break;
  214. hr = pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP,
  215. D3DFVF_XYZRHW | D3DFVF_TEX1,
  216. pVertices, 4, D3DDP_WAIT);
  217. pD3DDev->EndScene();
  218.         //
  219. pD3DDev->SetTexture(0, NULL);
  220. return S_OK;
  221.     }
  222. while(0);
  223.     return E_FAIL;
  224. }
  225. //
  226. // CDX7AllocatorPresenter
  227. //
  228. CDX7AllocatorPresenter::CDX7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  229. : ISubPicAllocatorPresenterImpl(hWnd)
  230. , m_ScreenSize(0, 0)
  231. {
  232.     if(!IsWindow(m_hWnd))
  233.     {
  234.         hr = E_INVALIDARG;
  235.         return;
  236.     }
  237. if(FAILED(hr = DirectDrawCreateEx(NULL, (VOID**)&m_pDD, IID_IDirectDraw7, NULL))
  238. || FAILED(hr = m_pDD->SetCooperativeLevel(AfxGetMainWnd()->GetSafeHwnd(), DDSCL_NORMAL)))
  239. return;
  240. if(!(m_pD3D = m_pDD))
  241. {
  242. hr = E_NOINTERFACE;
  243. return;
  244. }
  245. GetWindowRect(m_hWnd, &m_WindowRect);
  246. hr = CreateDevice();
  247. }
  248. HRESULT CDX7AllocatorPresenter::CreateDevice()
  249. {
  250.     m_pD3DDev = NULL;
  251. m_pPrimary = NULL;
  252. m_pBackBuffer = NULL;
  253.     DDSURFACEDESC2 ddsd;
  254. INITDDSTRUCT(ddsd);
  255.     if(FAILED(m_pDD->GetDisplayMode(&ddsd))
  256. || ddsd.ddpfPixelFormat.dwRGBBitCount <= 8)
  257. return DDERR_INVALIDMODE;
  258. m_ScreenSize.SetSize(ddsd.dwWidth, ddsd.dwHeight);
  259. HRESULT hr;
  260. // m_pPrimary
  261. INITDDSTRUCT(ddsd);
  262.     ddsd.dwFlags = DDSD_CAPS;
  263.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  264.     if(FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pPrimary, NULL)))
  265.         return hr;
  266. CComPtr<IDirectDrawClipper> pcClipper;
  267.     if(FAILED(hr = m_pDD->CreateClipper(0, &pcClipper, NULL)))
  268.         return hr;
  269. pcClipper->SetHWnd(0, m_hWnd);
  270. m_pPrimary->SetClipper(pcClipper);
  271. // m_pBackBuffer
  272. INITDDSTRUCT(ddsd);
  273.     ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  274.     ddsd.ddsCaps.dwCaps = /*DDSCAPS_OFFSCREENPLAIN |*/ DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE;
  275. ddsd.dwWidth = m_ScreenSize.cx;
  276. ddsd.dwHeight = m_ScreenSize.cy;
  277. if(FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pBackBuffer, NULL)))
  278.         return hr;
  279. pcClipper = NULL;
  280.     if(FAILED(hr = m_pDD->CreateClipper(0, &pcClipper, NULL)))
  281. return hr;
  282.     BYTE rgnDataBuffer[1024];
  283. HRGN hrgn = CreateRectRgn(0, 0, ddsd.dwWidth, ddsd.dwHeight);
  284. GetRegionData(hrgn, sizeof(rgnDataBuffer), (RGNDATA*)rgnDataBuffer);
  285. DeleteObject(hrgn);
  286. pcClipper->SetClipList((RGNDATA*)rgnDataBuffer, 0);
  287. m_pBackBuffer->SetClipper(pcClipper);
  288. // m_pD3DDev
  289. if(FAILED(hr = m_pD3D->CreateDevice(IID_IDirect3DHALDevice, m_pBackBuffer, &m_pD3DDev))) // this seems to fail if the desktop size is too large (width or height >2048)
  290. return hr;
  291. //
  292. CComPtr<ISubPicProvider> pSubPicProvider;
  293. if(m_pSubPicQueue) m_pSubPicQueue->GetSubPicProvider(&pSubPicProvider);
  294. CSize size;
  295. switch(AfxGetAppSettings().nSPCMaxRes)
  296. {
  297. case 0: default: size = m_ScreenSize; break;
  298. case 1: size.SetSize(1024, 768); break;
  299. case 2: size.SetSize(800, 600); break;
  300. case 3: size.SetSize(640, 480); break;
  301. case 4: size.SetSize(512, 384); break;
  302. case 5: size.SetSize(384, 288); break;
  303. }
  304. if(m_pAllocator)
  305. {
  306. m_pAllocator->ChangeDevice(m_pD3DDev);
  307. }
  308. else
  309. {
  310. m_pAllocator = new CDX7SubPicAllocator(m_pD3DDev, size, AfxGetAppSettings().fSPCPow2Tex);
  311. if(!m_pAllocator || FAILED(hr))
  312. return E_FAIL;
  313. }
  314. hr = S_OK;
  315. m_pSubPicQueue = AfxGetAppSettings().nSPCSize > 0 
  316. ? (ISubPicQueue*)new CSubPicQueue(AfxGetAppSettings().nSPCSize, m_pAllocator, &hr)
  317. : (ISubPicQueue*)new CSubPicQueueNoThread(m_pAllocator, &hr);
  318. if(!m_pSubPicQueue || FAILED(hr))
  319. return E_FAIL;
  320. if(pSubPicProvider) m_pSubPicQueue->SetSubPicProvider(pSubPicProvider);
  321. return S_OK;
  322. }
  323. HRESULT CDX7AllocatorPresenter::AllocSurfaces()
  324. {
  325.     CAutoLock cAutoLock(this);
  326. AppSettings& s = AfxGetAppSettings();
  327. m_pVideoTexture = NULL;
  328. m_pVideoSurface = NULL;
  329. DDSURFACEDESC2 ddsd;
  330. INITDDSTRUCT(ddsd);
  331. ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
  332. ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
  333. ddsd.dwWidth = m_NativeVideoSize.cx;
  334. ddsd.dwHeight = m_NativeVideoSize.cy;
  335. ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  336. ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  337. ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
  338. ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
  339. ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
  340. ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FF;
  341. if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D || s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
  342. {
  343. ddsd.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
  344. // ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
  345. // ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
  346. }
  347. HRESULT hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurface, NULL);
  348. if(FAILED(hr))
  349. {
  350. // FIXME: eh, dx9 has no problem creating a 32bpp surface under a 16bpp desktop, but dx7 fails here (textures are ok)
  351. DDSURFACEDESC2 ddsd2;
  352. INITDDSTRUCT(ddsd2);
  353. if(!(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D || s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
  354. && SUCCEEDED(m_pDD->GetDisplayMode(&ddsd2))
  355. && ddsd2.ddpfPixelFormat.dwRGBBitCount == 16)
  356. {
  357. ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
  358. ddsd.ddpfPixelFormat.dwRBitMask = 0x0000F800;
  359. ddsd.ddpfPixelFormat.dwGBitMask = 0x000007E0;
  360. ddsd.ddpfPixelFormat.dwBBitMask = 0x0000001F;
  361. hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurface, NULL);
  362. }
  363. if(FAILED(hr))
  364. return hr;
  365. }
  366. if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
  367. m_pVideoTexture = m_pVideoSurface;
  368. DDBLTFX fx;
  369. INITDDSTRUCT(fx);
  370. fx.dwFillColor = 0;
  371. hr = m_pVideoSurface->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  372. return S_OK;
  373. }
  374. void CDX7AllocatorPresenter::DeleteSurfaces()
  375. {
  376.     CAutoLock cAutoLock(this);
  377. m_pVideoTexture = NULL;
  378. m_pVideoSurface = NULL;
  379. }
  380. // ISubPicAllocatorPresenter
  381. STDMETHODIMP CDX7AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
  382. {
  383. return E_NOTIMPL;
  384. }
  385. STDMETHODIMP_(bool) CDX7AllocatorPresenter::Paint(bool fAll)
  386. {
  387. CAutoLock cAutoLock(this);
  388. if(m_WindowRect.right <= m_WindowRect.left || m_WindowRect.bottom <= m_WindowRect.top
  389. || m_NativeVideoSize.cx <= 0 || m_NativeVideoSize.cy <= 0
  390. || !m_pPrimary || !m_pBackBuffer || !m_pVideoSurface)
  391. return(false);
  392. HRESULT hr;
  393. CRect rSrcVid(CPoint(0, 0), m_NativeVideoSize);
  394. CRect rDstVid(m_VideoRect);
  395. CRect rSrcPri(CPoint(0, 0), m_WindowRect.Size());
  396. CRect rDstPri(m_WindowRect);
  397. MapWindowRect(m_hWnd, HWND_DESKTOP, &rDstPri);
  398. if(fAll)
  399. {
  400. // clear the backbuffer
  401. CRect rl(0, 0, rDstVid.left, rSrcPri.bottom);
  402. CRect rr(rDstVid.right, 0, rSrcPri.right, rSrcPri.bottom);
  403. CRect rt(0, 0, rSrcPri.right, rDstVid.top);
  404. CRect rb(0, rDstVid.bottom, rSrcPri.right, rSrcPri.bottom);
  405. DDBLTFX fx;
  406. INITDDSTRUCT(fx);
  407. fx.dwFillColor = 0;
  408. hr = m_pBackBuffer->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  409. // paint the video on the backbuffer
  410. if(!rDstVid.IsRectEmpty())
  411. {
  412. if(m_pVideoTexture)
  413. {
  414. Vector v[4];
  415. Transform(rDstVid, v);
  416. hr = TextureBlt(m_pD3DDev, m_pVideoTexture, v, rSrcVid);
  417. }
  418. else
  419. {
  420. hr = m_pBackBuffer->Blt(rDstVid, m_pVideoSurface, rSrcVid, DDBLT_WAIT, NULL);
  421. }
  422. }
  423. // paint the text on the backbuffer
  424. AlphaBltSubPic(rSrcPri.Size());
  425. }
  426. // wait vsync
  427. m_pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
  428. // blt to the primary surface
  429. hr = m_pPrimary->Blt(rDstPri, m_pBackBuffer, rSrcPri, DDBLT_WAIT, NULL);
  430. if(hr == DDERR_SURFACELOST)
  431. {
  432. HRESULT hr = DDERR_WRONGMODE; // m_pDD->TestCooperativeLevel();
  433. if(hr == DDERR_WRONGMODE) 
  434. {
  435. DeleteSurfaces();
  436. if(SUCCEEDED(CreateDevice()) || FAILED(hr = AllocSurfaces()))
  437. return(true);
  438. }
  439. hr = S_OK;
  440. }
  441. return(true);
  442. }
  443. STDMETHODIMP CDX7AllocatorPresenter::GetDIB(BYTE* lpDib, DWORD* size)
  444. {
  445. CheckPointer(size, E_POINTER);
  446. HRESULT hr;
  447. DDSURFACEDESC2 ddsd;
  448. INITDDSTRUCT(ddsd);
  449. if(FAILED(m_pVideoSurface->GetSurfaceDesc(&ddsd)))
  450. return E_FAIL;
  451. if(ddsd.ddpfPixelFormat.dwRGBBitCount != 16 && ddsd.ddpfPixelFormat.dwRGBBitCount != 32)
  452. return E_FAIL;
  453. DWORD required = sizeof(BITMAPINFOHEADER) + (ddsd.dwWidth*ddsd.dwHeight*32>>3);
  454. if(!lpDib) {*size = required; return S_OK;}
  455. if(*size < required) return E_OUTOFMEMORY;
  456. *size = required;
  457. INITDDSTRUCT(ddsd);
  458. if(FAILED(hr = m_pVideoSurface->Lock(NULL, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY|DDLOCK_NOSYSLOCK, NULL)))
  459. {
  460. // TODO
  461. return hr;
  462. }
  463. BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)lpDib;
  464. memset(bih, 0, sizeof(BITMAPINFOHEADER));
  465. bih->biSize = sizeof(BITMAPINFOHEADER);
  466. bih->biWidth = ddsd.dwWidth;
  467. bih->biHeight = ddsd.dwHeight;
  468. bih->biBitCount = 32;
  469. bih->biPlanes = 1;
  470. bih->biSizeImage = bih->biWidth*bih->biHeight*bih->biBitCount>>3;
  471. BitBltFromRGBToRGB(
  472. bih->biWidth, bih->biHeight, 
  473. (BYTE*)(bih + 1), bih->biWidth*bih->biBitCount>>3, bih->biBitCount,
  474. (BYTE*)ddsd.lpSurface + ddsd.lPitch*(ddsd.dwHeight-1), -(int)ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount);
  475. m_pVideoSurface->Unlock(NULL);
  476. /*
  477. BitBltFromRGBToRGB(
  478. w, h, 
  479. (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount,
  480. (BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmBitsPixel);
  481. m_pVideoSurfaceOff->Unlock(NULL);
  482. fOk = true;
  483. }
  484. */
  485. return S_OK;
  486. }
  487. //
  488. // CVMR7AllocatorPresenter
  489. //
  490. #define MY_USER_ID 0x6ABE51
  491. CVMR7AllocatorPresenter::CVMR7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  492. : CDX7AllocatorPresenter(hWnd, hr)
  493. , m_fUseInternalTimer(true)
  494. {
  495.     if(FAILED(hr))
  496. return;
  497. if(FAILED(hr = m_pSA.CoCreateInstance(CLSID_AllocPresenter)))
  498. {
  499. hr = E_FAIL;
  500. return;
  501. }
  502. }
  503. STDMETHODIMP CVMR7AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  504. {
  505.     CheckPointer(ppv, E_POINTER);
  506. return 
  507. QI(IVMRSurfaceAllocator)
  508. QI(IVMRImagePresenter)
  509. QI(IVMRWindowlessControl)
  510. __super::NonDelegatingQueryInterface(riid, ppv);
  511. }
  512. HRESULT CVMR7AllocatorPresenter::CreateDevice()
  513. {
  514. HRESULT hr = __super::CreateDevice();
  515. if(FAILED(hr)) return hr;
  516. if(m_pIVMRSurfAllocNotify)
  517. {
  518. HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
  519. if(FAILED(hr = m_pIVMRSurfAllocNotify->ChangeDDrawDevice(m_pDD, hMonitor)))
  520. return(false);
  521. }
  522. return hr;
  523. }
  524. void CVMR7AllocatorPresenter::DeleteSurfaces()
  525. {
  526.     CAutoLock cAutoLock(this);
  527. m_pSA->FreeSurface(MY_USER_ID);
  528. __super::DeleteSurfaces();
  529. }
  530. // ISubPicAllocatorPresenter
  531. STDMETHODIMP CVMR7AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
  532. {
  533.     CheckPointer(ppRenderer, E_POINTER);
  534. *ppRenderer = NULL;
  535. HRESULT hr;
  536. do
  537. {
  538. CComPtr<IBaseFilter> pBF;
  539. if(FAILED(hr = pBF.CoCreateInstance(CLSID_VideoMixingRenderer)))
  540. break;
  541. CComQIPtr<IVMRFilterConfig> pConfig = pBF;
  542. if(!pConfig)
  543. break;
  544. if(FAILED(hr = pConfig->SetRenderingMode(VMRMode_Renderless)))
  545. break;
  546. CComQIPtr<IVMRSurfaceAllocatorNotify> pSAN = pBF;
  547. if(!pSAN)
  548. break;
  549. if(FAILED(hr = pSAN->AdviseSurfaceAllocator(MY_USER_ID, static_cast<IVMRSurfaceAllocator*>(this)))
  550. || FAILED(hr = AdviseNotify(pSAN)))
  551. break;
  552. CComPtr<IPin> pPin = GetFirstPin(pBF);
  553. HookNewSegment((IPinC*)(IPin*)pPin);
  554. *ppRenderer = (IUnknown*)pBF.Detach();
  555. return S_OK;
  556. }
  557. while(0);
  558.     return E_FAIL;
  559. }
  560. STDMETHODIMP_(void) CVMR7AllocatorPresenter::SetTime(REFERENCE_TIME rtNow)
  561. {
  562. m_fUseInternalTimer = false;
  563. __super::SetTime(rtNow);
  564. }
  565. // IVMRSurfaceAllocator
  566. STDMETHODIMP CVMR7AllocatorPresenter::AllocateSurface(DWORD_PTR dwUserID, VMRALLOCATIONINFO* lpAllocInfo, DWORD* lpdwBuffer, LPDIRECTDRAWSURFACE7* lplpSurface)
  567. {
  568. if(!lpAllocInfo || !lpdwBuffer || !lplpSurface)
  569. return E_POINTER;
  570. if(!m_pIVMRSurfAllocNotify)
  571. return E_FAIL;
  572. HRESULT hr;
  573.     DeleteSurfaces();
  574. // HACK: yv12 will fail to blt onto the backbuffer anyway, but if we first
  575. // allocate it and then let our FreeSurface callback call m_pSA->FreeSurface,
  576. // then that might stall for about 30 seconds because of some unknown buggy code 
  577. // behind <ddraw surface>->Release()
  578. if(lpAllocInfo->lpHdr->biBitCount < 16)
  579. return E_FAIL;
  580. hr = m_pSA->AllocateSurface(dwUserID, lpAllocInfo, lpdwBuffer, lplpSurface);
  581. if(FAILED(hr))
  582. return hr;
  583. m_NativeVideoSize = CSize(abs(lpAllocInfo->lpHdr->biWidth), abs(lpAllocInfo->lpHdr->biHeight));
  584. m_AspectRatio = m_NativeVideoSize;
  585. int arx = lpAllocInfo->szAspectRatio.cx, ary = lpAllocInfo->szAspectRatio.cy;
  586. if(arx > 0 && ary > 0) m_AspectRatio.SetSize(arx, ary);
  587. if(FAILED(hr = AllocSurfaces()))
  588. return hr;
  589. // test if the colorspace is acceptable
  590. if(FAILED(hr = m_pVideoSurface->Blt(NULL, *lplpSurface, NULL, DDBLT_WAIT, NULL)))
  591. {
  592. DeleteSurfaces();
  593. return hr;
  594. }
  595. DDBLTFX fx;
  596. INITDDSTRUCT(fx);
  597. fx.dwFillColor = 0;
  598. m_pVideoSurface->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  599. return hr;
  600. }
  601. STDMETHODIMP CVMR7AllocatorPresenter::FreeSurface(DWORD_PTR dwUserID)
  602. {
  603.     DeleteSurfaces();
  604. return S_OK;
  605. }
  606. STDMETHODIMP CVMR7AllocatorPresenter::PrepareSurface(DWORD_PTR dwUserID, IDirectDrawSurface7* lpSurface, DWORD dwSurfaceFlags)
  607. {
  608.     if(!lpSurface)
  609. return E_POINTER;
  610. // FIXME: sometimes the msmpeg4/divx3/wmv decoder wants to reuse our 
  611. // surface (expects it to point to the same mem every time), and to avoid 
  612. // problems we can't cal m_pSA->PrepareSurface (flips? clears?).
  613. return S_OK; 
  614. /*
  615. return m_pSA->PrepareSurface(dwUserID, lpSurface, dwSurfaceFlags);
  616. */
  617. }
  618. STDMETHODIMP CVMR7AllocatorPresenter::AdviseNotify(IVMRSurfaceAllocatorNotify* lpIVMRSurfAllocNotify)
  619. {
  620.     CAutoLock cAutoLock(this);
  621. m_pIVMRSurfAllocNotify = lpIVMRSurfAllocNotify;
  622. HRESULT hr;
  623. HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
  624. if(FAILED(hr = m_pIVMRSurfAllocNotify->SetDDrawDevice(m_pDD, hMonitor)))
  625. return hr;
  626. return m_pSA->AdviseNotify(lpIVMRSurfAllocNotify);
  627. }
  628. // IVMRImagePresenter
  629. STDMETHODIMP CVMR7AllocatorPresenter::StartPresenting(DWORD_PTR dwUserID)
  630. {
  631.     CAutoLock cAutoLock(this);
  632.     ASSERT(m_pD3DDev);
  633. return m_pD3DDev ? S_OK : E_FAIL;
  634. }
  635. STDMETHODIMP CVMR7AllocatorPresenter::StopPresenting(DWORD_PTR dwUserID)
  636. {
  637. return S_OK;
  638. }
  639. STDMETHODIMP CVMR7AllocatorPresenter::PresentImage(DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo)
  640. {
  641.     HRESULT hr;
  642. {
  643. if(!lpPresInfo || !lpPresInfo->lpSurf)
  644. return E_POINTER;
  645. CAutoLock cAutoLock(this);
  646. hr = m_pVideoSurface->Blt(NULL, lpPresInfo->lpSurf, NULL, DDBLT_WAIT, NULL);
  647. if(lpPresInfo->rtEnd > lpPresInfo->rtStart)
  648. {
  649. REFERENCE_TIME rtTimePerFrame = lpPresInfo->rtEnd - lpPresInfo->rtStart;
  650. m_fps = 10000000.0 / rtTimePerFrame;
  651. if(m_pSubPicQueue) 
  652. {
  653. m_pSubPicQueue->SetFPS(m_fps);
  654. if(m_fUseInternalTimer) __super::SetTime(g_tSegmentStart + lpPresInfo->rtStart);
  655. }
  656. }
  657. CSize VideoSize = m_NativeVideoSize;
  658. int arx = lpPresInfo->szAspectRatio.cx, ary = lpPresInfo->szAspectRatio.cy;
  659. if(arx > 0 && ary > 0) VideoSize.cx = VideoSize.cy*arx/ary;
  660. if(VideoSize != GetVideoSize())
  661. {
  662. m_AspectRatio.SetSize(arx, ary);
  663. AfxGetApp()->m_pMainWnd->PostMessage(WM_REARRANGERENDERLESS);
  664. }
  665. Paint(true);
  666. hr = S_OK;
  667. }
  668. return S_OK;
  669. }
  670. // IVMRWindowlessControl
  671. //
  672. // It is only implemented (partially) for the dvd navigator's 
  673. // menu handling, which needs to know a few things about the 
  674. // location of our window.
  675. STDMETHODIMP CVMR7AllocatorPresenter::GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
  676. {
  677. CSize vs = m_NativeVideoSize, ar = m_AspectRatio;
  678. // DVD Nav. bug workaround fix
  679. vs.cx = vs.cy * ar.cx / ar.cy;
  680. if(lpWidth) *lpWidth = vs.cx;
  681. if(lpHeight) *lpHeight = vs.cy;
  682. if(lpARWidth) *lpARWidth = ar.cx;
  683. if(lpARHeight) *lpARHeight = ar.cy;
  684. return S_OK;
  685. }
  686. STDMETHODIMP CVMR7AllocatorPresenter::GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
  687. STDMETHODIMP CVMR7AllocatorPresenter::GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
  688. STDMETHODIMP CVMR7AllocatorPresenter::SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;} // we have our own method for this
  689. STDMETHODIMP CVMR7AllocatorPresenter::GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
  690. {
  691. CopyRect(lpSRCRect, CRect(CPoint(0, 0), m_NativeVideoSize));
  692. CopyRect(lpDSTRect, &m_VideoRect);
  693. // DVD Nav. bug workaround fix
  694. GetNativeVideoSize(&lpSRCRect->right, &lpSRCRect->bottom, NULL, NULL);
  695. return S_OK;
  696. }
  697. STDMETHODIMP CVMR7AllocatorPresenter::GetAspectRatioMode(DWORD* lpAspectRatioMode)
  698. {
  699. if(lpAspectRatioMode) *lpAspectRatioMode = AM_ARMODE_STRETCHED;
  700. return S_OK;
  701. }
  702. STDMETHODIMP CVMR7AllocatorPresenter::SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
  703. STDMETHODIMP CVMR7AllocatorPresenter::SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
  704. STDMETHODIMP CVMR7AllocatorPresenter::RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
  705. STDMETHODIMP CVMR7AllocatorPresenter::DisplayModeChanged() {return E_NOTIMPL;}
  706. STDMETHODIMP CVMR7AllocatorPresenter::GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
  707. STDMETHODIMP CVMR7AllocatorPresenter::SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
  708. STDMETHODIMP CVMR7AllocatorPresenter::GetBorderColor(COLORREF* lpClr)
  709. {
  710. if(lpClr) *lpClr = 0;
  711. return S_OK;
  712. }
  713. STDMETHODIMP CVMR7AllocatorPresenter::SetColorKey(COLORREF Clr) {return E_NOTIMPL;}
  714. STDMETHODIMP CVMR7AllocatorPresenter::GetColorKey(COLORREF* lpClr) {return E_NOTIMPL;}
  715. //
  716. static HRESULT AllocDX7Surface(IDirectDraw7* pDD, CSize size, DWORD compression, int bpp, IDirectDrawSurface7** pSurface)
  717. {
  718. if(!pDD || !pSurface || size.cx <= 0 || size.cy <= 0)
  719. return E_POINTER;
  720. *pSurface = NULL;
  721. DDSURFACEDESC2 ddsd;
  722. INITDDSTRUCT(ddsd);
  723. ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
  724. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY;
  725. ddsd.dwWidth = size.cx;
  726. ddsd.dwHeight = size.cy;
  727. ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  728. if(compression >= 0x1000)
  729. {
  730. ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
  731. ddsd.ddpfPixelFormat.dwFourCC = compression;
  732. }
  733. else if((compression == 0 || compression == 3) && (bpp == 15 || bpp == 16 || bpp == 24 || bpp == 32))
  734. {
  735. ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  736. ddsd.ddpfPixelFormat.dwRGBBitCount = max(bpp, 16);
  737. ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = (bpp == 16) ? 0x0000 : (bpp == 15) ? 0x8000 : 0xFF000000;
  738. ddsd.ddpfPixelFormat.dwRBitMask = (bpp == 16) ? 0xf800 : (bpp == 15) ? 0x7c00 : 0x00FF0000;
  739. ddsd.ddpfPixelFormat.dwGBitMask = (bpp == 16) ? 0x07e0 : (bpp == 15) ? 0x03e0 : 0x0000FF00;
  740. ddsd.ddpfPixelFormat.dwBBitMask = (bpp == 16) ? 0x001F : (bpp == 15) ? 0x001F : 0x000000FF;
  741. }
  742. return pDD->CreateSurface(&ddsd, pSurface, NULL);
  743. }
  744. //
  745. // CRM7AllocatorPresenter
  746. //
  747. CRM7AllocatorPresenter::CRM7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  748. : CDX7AllocatorPresenter(hWnd, hr)
  749. {
  750. }
  751. STDMETHODIMP CRM7AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  752. {
  753.     CheckPointer(ppv, E_POINTER);
  754. return 
  755. QI2(IRMAVideoSurface)
  756. __super::NonDelegatingQueryInterface(riid, ppv);
  757. }
  758. HRESULT CRM7AllocatorPresenter::AllocSurfaces()
  759. {
  760.     CAutoLock cAutoLock(this);
  761. m_pVideoSurfaceOff = NULL;
  762. m_pVideoSurfaceYUY2 = NULL;
  763. DDSURFACEDESC2 ddsd;
  764. DDBLTFX fx;
  765. INITDDSTRUCT(ddsd);
  766. ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
  767. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  768. ddsd.dwWidth = m_NativeVideoSize.cx;
  769. ddsd.dwHeight = m_NativeVideoSize.cy;
  770. ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  771. ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  772. ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
  773. ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
  774. ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
  775. ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
  776. ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FF;
  777. HRESULT hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurfaceOff, NULL);
  778. if(FAILED(hr)) return E_FAIL;
  779. INITDDSTRUCT(fx);
  780. fx.dwFillColor = 0;
  781. m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  782. INITDDSTRUCT(ddsd);
  783. ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
  784. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  785. ddsd.dwWidth = m_NativeVideoSize.cx;
  786. ddsd.dwHeight = m_NativeVideoSize.cy;
  787. ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  788. ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
  789. ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
  790. ddsd.ddpfPixelFormat.dwFourCC = '2YUY';
  791. hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurfaceYUY2, NULL);
  792. if(FAILED(m_pVideoSurfaceOff->Blt(NULL, m_pVideoSurfaceYUY2, NULL, DDBLT_WAIT, NULL)))
  793. m_pVideoSurfaceYUY2 = NULL;
  794. if(m_pVideoSurfaceYUY2)
  795. {
  796. INITDDSTRUCT(fx);
  797. fx.dwFillColor = 0x80108010;
  798. m_pVideoSurfaceYUY2->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  799. }
  800. return __super::AllocSurfaces();
  801. }
  802. void CRM7AllocatorPresenter::DeleteSurfaces()
  803. {
  804.     CAutoLock cAutoLock(this);
  805. m_pVideoSurfaceOff = NULL;
  806. m_pVideoSurfaceYUY2 = NULL;
  807. __super::DeleteSurfaces();
  808. }
  809. // IRMAVideoSurface
  810. STDMETHODIMP CRM7AllocatorPresenter::Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect)
  811. {
  812. if(!m_pVideoSurface || !m_pVideoSurfaceOff)
  813. return E_FAIL;
  814. bool fRGB = false;
  815. bool fYUY2 = false;
  816. CRect src((RECT*)&inSrcRect), dst((RECT*)&inDestRect), src2(CPoint(0,0), src.Size());
  817. if(src.Width() > dst.Width() || src.Height() > dst.Height())
  818. return E_FAIL;
  819. DDSURFACEDESC2 ddsd;
  820. if(pBitmapInfo->biCompression == '024I')
  821. {
  822. DWORD pitch = pBitmapInfo->biWidth;
  823. DWORD size = pitch*abs(pBitmapInfo->biHeight);
  824. BYTE* y = pImageData + src.top*pitch + src.left;
  825. BYTE* u = pImageData + size + src.top*(pitch/2) + src.left/2;
  826. BYTE* v = pImageData + size + size/4 + src.top*(pitch/2) + src.left/2;
  827. if(m_pVideoSurfaceYUY2)
  828. {
  829. INITDDSTRUCT(ddsd);
  830. if(SUCCEEDED(m_pVideoSurfaceYUY2->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
  831. {
  832. BitBltFromI420ToYUY2(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, y, u, v, pitch);
  833. m_pVideoSurfaceYUY2->Unlock(src2);
  834. fYUY2 = true;
  835. }
  836. }
  837. else
  838. {
  839. INITDDSTRUCT(ddsd);
  840. if(SUCCEEDED(m_pVideoSurfaceOff->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
  841. {
  842. BitBltFromI420ToRGB(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount, y, u, v, pitch);
  843. m_pVideoSurfaceOff->Unlock(src2);
  844. fRGB = true;
  845. }
  846. }
  847. }
  848. else if(pBitmapInfo->biCompression == '2YUY')
  849. {
  850. DWORD w = pBitmapInfo->biWidth;
  851. DWORD h = abs(pBitmapInfo->biHeight);
  852. DWORD pitch = pBitmapInfo->biWidth*2;
  853. BYTE* yvyu = pImageData + src.top*pitch + src.left*2;
  854. if(m_pVideoSurfaceYUY2)
  855. {
  856. INITDDSTRUCT(ddsd);
  857. if(SUCCEEDED(m_pVideoSurfaceYUY2->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
  858. {
  859. BitBltFromYUY2ToYUY2(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, yvyu, pitch);
  860. m_pVideoSurfaceYUY2->Unlock(src2);
  861. fYUY2 = true;
  862. }
  863. }
  864. else
  865. {
  866. INITDDSTRUCT(ddsd);
  867. if(SUCCEEDED(m_pVideoSurfaceOff->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
  868. {
  869. BitBltFromYUY2ToRGB(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount, yvyu, pitch);
  870. m_pVideoSurfaceOff->Unlock(src2);
  871. fRGB = true;
  872. }
  873. }
  874. }
  875. else if(pBitmapInfo->biCompression == 0 || pBitmapInfo->biCompression == 3
  876.  || pBitmapInfo->biCompression == 'BGRA')
  877. {
  878. DWORD w = pBitmapInfo->biWidth;
  879. DWORD h = abs(pBitmapInfo->biHeight);
  880. DWORD pitch = pBitmapInfo->biWidth*pBitmapInfo->biBitCount>>3;
  881. BYTE* rgb = pImageData + src.top*pitch + src.left*(pBitmapInfo->biBitCount>>3);
  882. INITDDSTRUCT(ddsd);
  883. if(SUCCEEDED(m_pVideoSurfaceOff->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
  884. {
  885. BYTE* lpSurface = (BYTE*)ddsd.lpSurface;
  886. if(pBitmapInfo->biHeight > 0) {lpSurface += ddsd.lPitch*(src.Height()-1); ddsd.lPitch = -ddsd.lPitch;}
  887. BitBltFromRGBToRGB(src.Width(), src.Height(), lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount, rgb, pitch, pBitmapInfo->biBitCount);
  888. fRGB = true;
  889. m_pVideoSurfaceOff->Unlock(src2);
  890. }
  891. }
  892. if(!fRGB && !fYUY2)
  893. {
  894. DDBLTFX fx;
  895. INITDDSTRUCT(fx);
  896. fx.dwFillColor = 0;
  897. m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  898. HDC hDC;
  899. if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
  900. {
  901. CString str;
  902. str.Format(_T("Sorry, this format is not supported"));
  903. SetBkColor(hDC, 0);
  904. SetTextColor(hDC, 0x404040);
  905. TextOut(hDC, 10, 10, str, str.GetLength());
  906. m_pVideoSurfaceOff->ReleaseDC(hDC);
  907. fRGB = true;
  908. }
  909. }
  910. HRESULT hr;
  911. if(fRGB)
  912. hr = m_pVideoSurface->Blt(dst, m_pVideoSurfaceOff, src2, DDBLT_WAIT, NULL);
  913. if(fYUY2)
  914. hr = m_pVideoSurface->Blt(dst, m_pVideoSurfaceYUY2, src2, DDBLT_WAIT, NULL);
  915.     
  916. Paint(true);
  917. return PNR_OK;
  918. }
  919. STDMETHODIMP CRM7AllocatorPresenter::BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo)
  920. {
  921.     CAutoLock cAutoLock(this);
  922. DeleteSurfaces();
  923. m_NativeVideoSize = m_AspectRatio = CSize(pBitmapInfo->biWidth, abs(pBitmapInfo->biHeight));
  924. if(FAILED(AllocSurfaces())) return E_FAIL;
  925. return PNR_NOTIMPL;
  926. }
  927. STDMETHODIMP CRM7AllocatorPresenter::OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect)
  928. {
  929. return PNR_NOTIMPL;
  930. }
  931. STDMETHODIMP CRM7AllocatorPresenter::EndOptimizedBlt()
  932. {
  933. return PNR_NOTIMPL;
  934. }
  935. STDMETHODIMP CRM7AllocatorPresenter::GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType)
  936. {
  937. return PNR_NOTIMPL;
  938. }
  939. STDMETHODIMP CRM7AllocatorPresenter::GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType)
  940. {
  941. ulType = RMA_I420;
  942. return PNR_OK;
  943. }
  944. //
  945. // CQT7AllocatorPresenter
  946. //
  947. CQT7AllocatorPresenter::CQT7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
  948. : CDX7AllocatorPresenter(hWnd, hr)
  949. {
  950. }
  951. STDMETHODIMP CQT7AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  952. {
  953.     CheckPointer(ppv, E_POINTER);
  954. return 
  955. QI(IQTVideoSurface)
  956. __super::NonDelegatingQueryInterface(riid, ppv);
  957. }
  958. HRESULT CQT7AllocatorPresenter::AllocSurfaces()
  959. {
  960.     CAutoLock cAutoLock(this);
  961. m_pVideoSurfaceOff = NULL;
  962. DDSURFACEDESC2 ddsd;
  963. INITDDSTRUCT(ddsd);
  964. ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
  965. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  966. ddsd.dwWidth = m_NativeVideoSize.cx;
  967. ddsd.dwHeight = m_NativeVideoSize.cy;
  968. ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  969. ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  970. ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
  971. ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
  972. ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
  973. ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
  974. ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FF;
  975. HRESULT hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurfaceOff, NULL);
  976. if(FAILED(hr)) return E_FAIL;
  977. DDBLTFX fx;
  978. INITDDSTRUCT(fx);
  979. fx.dwFillColor = 0;
  980. m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  981. return __super::AllocSurfaces();
  982. }
  983. void CQT7AllocatorPresenter::DeleteSurfaces()
  984. {
  985.     CAutoLock cAutoLock(this);
  986. m_pVideoSurfaceOff = NULL;
  987. __super::DeleteSurfaces();
  988. }
  989. // IQTVideoSurface
  990. STDMETHODIMP CQT7AllocatorPresenter::BeginBlt(const BITMAP& bm)
  991. {
  992.     CAutoLock cAutoLock(this);
  993. DeleteSurfaces();
  994. m_NativeVideoSize = m_AspectRatio = CSize(bm.bmWidth, abs(bm.bmHeight));
  995. HRESULT hr;
  996. if(FAILED(hr = AllocSurfaces()))
  997. return hr;
  998. return S_OK;
  999. }
  1000. STDMETHODIMP CQT7AllocatorPresenter::DoBlt(const BITMAP& bm)
  1001. {
  1002. if(!m_pVideoSurface || !m_pVideoSurfaceOff)
  1003. return E_FAIL;
  1004. bool fOk = false;
  1005. DDSURFACEDESC2 ddsd;
  1006. INITDDSTRUCT(ddsd);
  1007. if(FAILED(m_pVideoSurfaceOff->GetSurfaceDesc(&ddsd)))
  1008. return E_FAIL;
  1009. int w = bm.bmWidth;
  1010. int h = abs(bm.bmHeight);
  1011. int bpp = bm.bmBitsPixel;
  1012. if((bpp == 16 || bpp == 24 || bpp == 32) && w == ddsd.dwWidth && h == ddsd.dwHeight)
  1013. {
  1014. INITDDSTRUCT(ddsd);
  1015. if(SUCCEEDED(m_pVideoSurfaceOff->Lock(NULL, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
  1016. {
  1017. BitBltFromRGBToRGB(
  1018. w, h, 
  1019. (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount,
  1020. (BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmBitsPixel);
  1021. m_pVideoSurfaceOff->Unlock(NULL);
  1022. fOk = true;
  1023. }
  1024. }
  1025. if(!fOk)
  1026. {
  1027. DDBLTFX fx;
  1028. INITDDSTRUCT(fx);
  1029. fx.dwFillColor = 0;
  1030. m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
  1031. HDC hDC;
  1032. if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
  1033. {
  1034. CString str;
  1035. str.Format(_T("Sorry, this format is not supported"));
  1036. SetBkColor(hDC, 0);
  1037. SetTextColor(hDC, 0x404040);
  1038. TextOut(hDC, 10, 10, str, str.GetLength());
  1039. m_pVideoSurfaceOff->ReleaseDC(hDC);
  1040. }
  1041. }
  1042. m_pVideoSurface->Blt(NULL, m_pVideoSurfaceOff, NULL, DDBLT_WAIT, NULL);
  1043. Paint(true);
  1044. return S_OK;
  1045. }