DX7AllocatorPresenter.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
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 <initguid.h>
00029 #include "DX7AllocatorPresenter.h"
00030 #include <ddraw.h>
00031 #include <d3d.h>
00032 #include "..\..\SubPic\DX7SubPic.h"
00033 #include "..\..\..\include\RealMedia\pntypes.h"
00034 #include "..\..\..\include\RealMedia\pnwintyp.h"
00035 #include "..\..\..\include\RealMedia\pncom.h"
00036 #include "..\..\..\include\RealMedia\rmavsurf.h"
00037 #include "IQTVideoSurface.h"
00038 
00039 #include "IPinHook.h"
00040 
00041 bool IsVMR7InGraph(IFilterGraph* pFG)
00042 {
00043         BeginEnumFilters(pFG, pEF, pBF)
00044                 if(CComQIPtr<IVMRWindowlessControl>(pBF)) return(true);
00045         EndEnumFilters
00046         return(false);
00047 }
00048 
00049 namespace DSObjects
00050 {
00051 
00052 class CDX7AllocatorPresenter
00053         : public ISubPicAllocatorPresenterImpl
00054 {
00055 protected:
00056         CSize m_ScreenSize;
00057 
00058         CComPtr<IDirectDraw7> m_pDD;
00059         CComQIPtr<IDirect3D7, &IID_IDirect3D7> m_pD3D;
00060     CComPtr<IDirect3DDevice7> m_pD3DDev;
00061 
00062         CComPtr<IDirectDrawSurface7> m_pPrimary, m_pBackBuffer;
00063         CComPtr<IDirectDrawSurface7> m_pVideoTexture, m_pVideoSurface;
00064 
00065     virtual HRESULT CreateDevice();
00066         virtual HRESULT AllocSurfaces();
00067         virtual void DeleteSurfaces();
00068 
00069 public:
00070         CDX7AllocatorPresenter(HWND hWnd, HRESULT& hr);
00071 
00072         // ISubPicAllocatorPresenter
00073         STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
00074         STDMETHODIMP_(bool) Paint(bool fAll);
00075         STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size);
00076 };
00077 
00078 class CVMR7AllocatorPresenter
00079         : public CDX7AllocatorPresenter
00080         , public IVMRSurfaceAllocator
00081         , public IVMRImagePresenter
00082         , public IVMRWindowlessControl
00083 {
00084         CComPtr<IVMRSurfaceAllocatorNotify> m_pIVMRSurfAllocNotify;
00085         CComPtr<IVMRSurfaceAllocator> m_pSA;
00086 
00087         HRESULT CreateDevice();
00088         void DeleteSurfaces();
00089 
00090         bool m_fUseInternalTimer;
00091 
00092 public:
00093         CVMR7AllocatorPresenter(HWND hWnd, HRESULT& hr);
00094 
00095         DECLARE_IUNKNOWN
00096     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00097 
00098         // ISubPicAllocatorPresenter
00099         STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
00100         STDMETHODIMP_(void) SetTime(REFERENCE_TIME rtNow);
00101 
00102         // IVMRSurfaceAllocator
00103     STDMETHODIMP AllocateSurface(DWORD_PTR dwUserID, VMRALLOCATIONINFO* lpAllocInfo, DWORD* lpdwBuffer, LPDIRECTDRAWSURFACE7* lplpSurface);
00104     STDMETHODIMP FreeSurface(DWORD_PTR dwUserID);
00105     STDMETHODIMP PrepareSurface(DWORD_PTR dwUserID, IDirectDrawSurface7* lpSurface, DWORD dwSurfaceFlags);
00106     STDMETHODIMP AdviseNotify(IVMRSurfaceAllocatorNotify* lpIVMRSurfAllocNotify);
00107 
00108         // IVMRImagePresenter
00109     STDMETHODIMP StartPresenting(DWORD_PTR dwUserID);
00110     STDMETHODIMP StopPresenting(DWORD_PTR dwUserID);
00111     STDMETHODIMP PresentImage(DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo);
00112 
00113         // IVMRWindowlessControl
00114         STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight);
00115         STDMETHODIMP GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
00116         STDMETHODIMP GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight);
00117         STDMETHODIMP SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect);
00118     STDMETHODIMP GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect);
00119         STDMETHODIMP GetAspectRatioMode(DWORD* lpAspectRatioMode);
00120         STDMETHODIMP SetAspectRatioMode(DWORD AspectRatioMode);
00121         STDMETHODIMP SetVideoClippingWindow(HWND hwnd);
00122         STDMETHODIMP RepaintVideo(HWND hwnd, HDC hdc);
00123         STDMETHODIMP DisplayModeChanged();
00124         STDMETHODIMP GetCurrentImage(BYTE** lpDib);
00125         STDMETHODIMP SetBorderColor(COLORREF Clr);
00126         STDMETHODIMP GetBorderColor(COLORREF* lpClr);
00127         STDMETHODIMP SetColorKey(COLORREF Clr);
00128         STDMETHODIMP GetColorKey(COLORREF* lpClr);
00129 };
00130 
00131 class CRM7AllocatorPresenter
00132         : public CDX7AllocatorPresenter
00133         , public IRMAVideoSurface
00134 {
00135         CComPtr<IDirectDrawSurface7> m_pVideoSurfaceOff;
00136         CComPtr<IDirectDrawSurface7> m_pVideoSurfaceYUY2;
00137 
00138     RMABitmapInfoHeader m_bitmapInfo;
00139     RMABitmapInfoHeader m_lastBitmapInfo;
00140 
00141 protected:
00142         HRESULT AllocSurfaces();
00143         void DeleteSurfaces();
00144 
00145 public:
00146         CRM7AllocatorPresenter(HWND hWnd, HRESULT& hr);
00147 
00148         DECLARE_IUNKNOWN
00149     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00150 
00151         // IRMAVideoSurface
00152     STDMETHODIMP Blt(UCHAR*     pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect);
00153         STDMETHODIMP BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo);
00154         STDMETHODIMP OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect);
00155         STDMETHODIMP EndOptimizedBlt();
00156         STDMETHODIMP GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType);
00157     STDMETHODIMP GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType);
00158 };
00159 
00160 class CQT7AllocatorPresenter
00161         : public CDX7AllocatorPresenter
00162         , public IQTVideoSurface
00163 {
00164         CComPtr<IDirectDrawSurface7> m_pVideoSurfaceOff;
00165 
00166 protected:
00167         HRESULT AllocSurfaces();
00168         void DeleteSurfaces();
00169 
00170 public:
00171         CQT7AllocatorPresenter(HWND hWnd, HRESULT& hr);
00172 
00173         DECLARE_IUNKNOWN
00174     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
00175 
00176         // IQTVideoSurface
00177         STDMETHODIMP BeginBlt(const BITMAP& bm);
00178         STDMETHODIMP DoBlt(const BITMAP& bm);
00179 };
00180 
00181 }
00182 using namespace DSObjects;
00183 
00184 //
00185 
00186 HRESULT CreateAP7(const CLSID& clsid, HWND hWnd, ISubPicAllocatorPresenter** ppAP)
00187 {
00188         CheckPointer(ppAP, E_POINTER);
00189 
00190         *ppAP = NULL;
00191 
00192         HRESULT hr;
00193         if(clsid == CLSID_VMR7AllocatorPresenter && !(*ppAP = new CVMR7AllocatorPresenter(hWnd, hr))
00194         || clsid == CLSID_RM7AllocatorPresenter && !(*ppAP = new CRM7AllocatorPresenter(hWnd, hr))
00195         || clsid == CLSID_QT7AllocatorPresenter && !(*ppAP = new CQT7AllocatorPresenter(hWnd, hr)))
00196                 return E_OUTOFMEMORY;
00197 
00198         if(*ppAP == NULL)
00199                 return E_FAIL;
00200 
00201         (*ppAP)->AddRef();
00202 
00203         if(FAILED(hr))
00204         {
00205                 (*ppAP)->Release();
00206                 *ppAP = NULL;
00207         }
00208 
00209         return hr;
00210 }
00211 
00212 //
00213 
00214 static HRESULT TextureBlt(CComPtr<IDirect3DDevice7> pD3DDev, CComPtr<IDirectDrawSurface7> pTexture, Vector dst[4], CRect src)
00215 {
00216         if(!pTexture)
00217                 return E_POINTER;
00218 
00219         HRESULT hr;
00220 
00221     do
00222         {
00223                 DDSURFACEDESC2 ddsd;
00224                 INITDDSTRUCT(ddsd);
00225                 if(FAILED(hr = pTexture->GetSurfaceDesc(&ddsd)))
00226                         break;
00227 
00228         float w = (float)ddsd.dwWidth;
00229         float h = (float)ddsd.dwHeight;
00230 
00231                 struct
00232                 {
00233                         float x, y, z, rhw;
00234                         float tu, tv;
00235                 }
00236                 pVertices[] =
00237                 {
00238                         {(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},
00239                         {(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},
00240                         {(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},
00241                         {(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},
00242                 };
00243 
00244                 for(int i = 0; i < countof(pVertices); i++)
00245                 {
00246                         pVertices[i].x -= 0.5;
00247                         pVertices[i].y -= 0.5;
00248                 }
00249 
00250         hr = pD3DDev->SetTexture(0, pTexture);
00251 
00252         pD3DDev->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
00253         pD3DDev->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
00254         pD3DDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, FALSE);
00255                 pD3DDev->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, FALSE); 
00256 
00257         pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
00258         pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
00259         pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
00260 
00261         pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
00262 
00263                 //
00264 
00265         if(FAILED(hr = pD3DDev->BeginScene()))
00266                         break;
00267 
00268                 hr = pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP,
00269                                                                         D3DFVF_XYZRHW | D3DFVF_TEX1,
00270                                                                         pVertices, 4, D3DDP_WAIT);
00271                 pD3DDev->EndScene();
00272 
00273         //
00274 
00275                 pD3DDev->SetTexture(0, NULL);
00276 
00277                 return S_OK;
00278     }
00279         while(0);
00280 
00281     return E_FAIL;
00282 }
00283 
00284 //
00285 // CDX7AllocatorPresenter
00286 //
00287 
00288 CDX7AllocatorPresenter::CDX7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
00289         : ISubPicAllocatorPresenterImpl(hWnd)
00290         , m_ScreenSize(0, 0)
00291 {
00292     if(!IsWindow(m_hWnd))
00293     {
00294         hr = E_INVALIDARG;
00295         return;
00296     }
00297 
00298         if(FAILED(hr = DirectDrawCreateEx(NULL, (VOID**)&m_pDD, IID_IDirectDraw7, NULL))
00299         || FAILED(hr = m_pDD->SetCooperativeLevel(AfxGetMainWnd()->GetSafeHwnd(), DDSCL_NORMAL)))
00300                 return;
00301 
00302         if(!(m_pD3D = m_pDD))
00303         {
00304                 hr = E_NOINTERFACE;
00305                 return;
00306         }
00307 
00308         GetWindowRect(m_hWnd, &m_WindowRect);
00309 
00310         hr = CreateDevice();
00311 }
00312 
00313 HRESULT CDX7AllocatorPresenter::CreateDevice()
00314 {
00315     m_pD3DDev = NULL;
00316 
00317         m_pPrimary = NULL;
00318         m_pBackBuffer = NULL;
00319 
00320     DDSURFACEDESC2 ddsd;
00321         INITDDSTRUCT(ddsd);
00322     if(FAILED(m_pDD->GetDisplayMode(&ddsd))
00323         || ddsd.ddpfPixelFormat.dwRGBBitCount <= 8)
00324                 return DDERR_INVALIDMODE;
00325 
00326         m_ScreenSize.SetSize(ddsd.dwWidth, ddsd.dwHeight);
00327 
00328         HRESULT hr;
00329 
00330         // m_pPrimary
00331 
00332         INITDDSTRUCT(ddsd);
00333     ddsd.dwFlags = DDSD_CAPS;
00334     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
00335     if(FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pPrimary, NULL)))
00336         return hr;
00337 
00338         CComPtr<IDirectDrawClipper> pcClipper;
00339     if(FAILED(hr = m_pDD->CreateClipper(0, &pcClipper, NULL)))
00340         return hr;
00341         pcClipper->SetHWnd(0, m_hWnd);
00342         m_pPrimary->SetClipper(pcClipper);
00343 
00344         // m_pBackBuffer
00345 
00346         INITDDSTRUCT(ddsd);
00347     ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
00348     ddsd.ddsCaps.dwCaps = /*DDSCAPS_OFFSCREENPLAIN |*/ DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE;
00349         ddsd.dwWidth = m_ScreenSize.cx;
00350         ddsd.dwHeight = m_ScreenSize.cy;
00351         if(FAILED(hr = m_pDD->CreateSurface(&ddsd, &m_pBackBuffer, NULL)))
00352         return hr;
00353 
00354         pcClipper = NULL;
00355     if(FAILED(hr = m_pDD->CreateClipper(0, &pcClipper, NULL)))
00356                 return hr;
00357     BYTE rgnDataBuffer[1024];
00358         HRGN hrgn = CreateRectRgn(0, 0, ddsd.dwWidth, ddsd.dwHeight);
00359         GetRegionData(hrgn, sizeof(rgnDataBuffer), (RGNDATA*)rgnDataBuffer);
00360         DeleteObject(hrgn);
00361         pcClipper->SetClipList((RGNDATA*)rgnDataBuffer, 0);
00362         m_pBackBuffer->SetClipper(pcClipper);
00363 
00364         // m_pD3DDev
00365 
00366         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)
00367                 return hr;
00368 
00369         //
00370 
00371         CComPtr<ISubPicProvider> pSubPicProvider;
00372         if(m_pSubPicQueue) m_pSubPicQueue->GetSubPicProvider(&pSubPicProvider);
00373 
00374         CSize size;
00375         switch(AfxGetAppSettings().nSPCMaxRes)
00376         {
00377         case 0: default: size = m_ScreenSize; break;
00378         case 1: size.SetSize(1024, 768); break;
00379         case 2: size.SetSize(800, 600); break;
00380         case 3: size.SetSize(640, 480); break;
00381         case 4: size.SetSize(512, 384); break;
00382         case 5: size.SetSize(384, 288); break;
00383         }
00384 
00385         if(m_pAllocator)
00386         {
00387                 m_pAllocator->ChangeDevice(m_pD3DDev);
00388         }
00389         else
00390         {
00391                 m_pAllocator = new CDX7SubPicAllocator(m_pD3DDev, size, AfxGetAppSettings().fSPCPow2Tex);
00392                 if(!m_pAllocator || FAILED(hr))
00393                         return E_FAIL;
00394         }
00395 
00396         hr = S_OK;
00397         m_pSubPicQueue = AfxGetAppSettings().nSPCSize > 0 
00398                 ? (ISubPicQueue*)new CSubPicQueue(AfxGetAppSettings().nSPCSize, m_pAllocator, &hr)
00399                 : (ISubPicQueue*)new CSubPicQueueNoThread(m_pAllocator, &hr);
00400         if(!m_pSubPicQueue || FAILED(hr))
00401                 return E_FAIL;
00402 
00403         if(pSubPicProvider) m_pSubPicQueue->SetSubPicProvider(pSubPicProvider);
00404 
00405         return S_OK;
00406 }
00407 
00408 HRESULT CDX7AllocatorPresenter::AllocSurfaces()
00409 {
00410     CAutoLock cAutoLock(this);
00411 
00412         AppSettings& s = AfxGetAppSettings();
00413 
00414         m_pVideoTexture = NULL;
00415         m_pVideoSurface = NULL;
00416 
00417         DDSURFACEDESC2 ddsd;
00418         INITDDSTRUCT(ddsd);
00419         ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
00420         ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
00421         ddsd.dwWidth = m_NativeVideoSize.cx;
00422         ddsd.dwHeight = m_NativeVideoSize.cy;
00423         ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
00424         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
00425         ddsd.ddpfPixelFormat.dwRGBBitCount      = 32;
00426         ddsd.ddpfPixelFormat.dwRBitMask         = 0x00FF0000;
00427         ddsd.ddpfPixelFormat.dwGBitMask         = 0x0000FF00;
00428         ddsd.ddpfPixelFormat.dwBBitMask         = 0x000000FF;
00429 
00430         if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D || s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
00431         {
00432                 ddsd.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
00433 //              ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
00434 //              ddsd.ddpfPixelFormat.dwRGBAlphaBitMask  = 0xFF000000;
00435         }
00436 
00437         HRESULT hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurface, NULL);
00438         if(FAILED(hr))
00439         {
00440                 // FIXME: eh, dx9 has no problem creating a 32bpp surface under a 16bpp desktop, but dx7 fails here (textures are ok)
00441                 DDSURFACEDESC2 ddsd2;
00442                 INITDDSTRUCT(ddsd2);
00443                 if(!(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE2D || s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
00444                 && SUCCEEDED(m_pDD->GetDisplayMode(&ddsd2))
00445                 && ddsd2.ddpfPixelFormat.dwRGBBitCount == 16)
00446                 {
00447                         ddsd.ddpfPixelFormat.dwRGBBitCount      = 16;
00448                         ddsd.ddpfPixelFormat.dwRBitMask         = 0x0000F800;
00449                         ddsd.ddpfPixelFormat.dwGBitMask         = 0x000007E0;
00450                         ddsd.ddpfPixelFormat.dwBBitMask         = 0x0000001F;
00451                         hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurface, NULL);
00452                 }
00453 
00454                 if(FAILED(hr))
00455                         return hr;
00456         }
00457 
00458         if(s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
00459                 m_pVideoTexture = m_pVideoSurface;
00460 
00461         DDBLTFX fx;
00462         INITDDSTRUCT(fx);
00463         fx.dwFillColor = 0;
00464         hr = m_pVideoSurface->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
00465 
00466         return S_OK;
00467 }
00468 
00469 void CDX7AllocatorPresenter::DeleteSurfaces()
00470 {
00471     CAutoLock cAutoLock(this);
00472 
00473         m_pVideoTexture = NULL;
00474         m_pVideoSurface = NULL;
00475 }
00476 
00477 // ISubPicAllocatorPresenter
00478 
00479 STDMETHODIMP CDX7AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
00480 {
00481         return E_NOTIMPL;
00482 }
00483 
00484 STDMETHODIMP_(bool) CDX7AllocatorPresenter::Paint(bool fAll)
00485 {
00486         CAutoLock cAutoLock(this);
00487 
00488         if(m_WindowRect.right <= m_WindowRect.left || m_WindowRect.bottom <= m_WindowRect.top
00489         || m_NativeVideoSize.cx <= 0 || m_NativeVideoSize.cy <= 0
00490         || !m_pPrimary || !m_pBackBuffer || !m_pVideoSurface)
00491                 return(false);
00492 
00493         HRESULT hr;
00494 
00495         CRect rSrcVid(CPoint(0, 0), m_NativeVideoSize);
00496         CRect rDstVid(m_VideoRect);
00497 
00498         CRect rSrcPri(CPoint(0, 0), m_WindowRect.Size());
00499         CRect rDstPri(m_WindowRect);
00500         MapWindowRect(m_hWnd, HWND_DESKTOP, &rDstPri);
00501 
00502         if(fAll)
00503         {
00504                 // clear the backbuffer
00505 
00506                 CRect rl(0, 0, rDstVid.left, rSrcPri.bottom);
00507                 CRect rr(rDstVid.right, 0, rSrcPri.right, rSrcPri.bottom);
00508                 CRect rt(0, 0, rSrcPri.right, rDstVid.top);
00509                 CRect rb(0, rDstVid.bottom, rSrcPri.right, rSrcPri.bottom);
00510 
00511                 DDBLTFX fx;
00512                 INITDDSTRUCT(fx);
00513                 fx.dwFillColor = 0;
00514                 hr = m_pBackBuffer->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
00515 
00516                 // paint the video on the backbuffer
00517 
00518                 if(!rDstVid.IsRectEmpty())
00519                 {
00520                         if(m_pVideoTexture)
00521                         {
00522                                 Vector v[4];
00523                                 Transform(rDstVid, v);
00524                                 hr = TextureBlt(m_pD3DDev, m_pVideoTexture, v, rSrcVid);
00525                         }
00526                         else
00527                         {
00528                                 hr = m_pBackBuffer->Blt(rDstVid, m_pVideoSurface, rSrcVid, DDBLT_WAIT, NULL);
00529                         }
00530                 }
00531 
00532                 // paint the text on the backbuffer
00533 
00534                 AlphaBltSubPic(rSrcPri.Size());
00535         }
00536 
00537         // wait vsync
00538 
00539         m_pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
00540 
00541         // blt to the primary surface
00542 
00543         hr = m_pPrimary->Blt(rDstPri, m_pBackBuffer, rSrcPri, DDBLT_WAIT, NULL);
00544 
00545         if(hr == DDERR_SURFACELOST)
00546         {
00547                 HRESULT hr = DDERR_WRONGMODE; // m_pDD->TestCooperativeLevel();
00548 
00549                 if(hr == DDERR_WRONGMODE) 
00550                 {
00551                         DeleteSurfaces();
00552                         if(SUCCEEDED(CreateDevice()) || FAILED(hr = AllocSurfaces()))
00553                                 return(true);
00554                 }
00555 
00556                 hr = S_OK;
00557         }
00558 
00559         return(true);
00560 }
00561 
00562 STDMETHODIMP CDX7AllocatorPresenter::GetDIB(BYTE* lpDib, DWORD* size)
00563 {
00564         CheckPointer(size, E_POINTER);
00565 
00566         HRESULT hr;
00567 
00568         DDSURFACEDESC2 ddsd;
00569         INITDDSTRUCT(ddsd);
00570         if(FAILED(m_pVideoSurface->GetSurfaceDesc(&ddsd)))
00571                 return E_FAIL;
00572 
00573         if(ddsd.ddpfPixelFormat.dwRGBBitCount != 16 && ddsd.ddpfPixelFormat.dwRGBBitCount != 32)
00574                 return E_FAIL;
00575 
00576         DWORD required = sizeof(BITMAPINFOHEADER) + (ddsd.dwWidth*ddsd.dwHeight*32>>3);
00577         if(!lpDib) {*size = required; return S_OK;}
00578         if(*size < required) return E_OUTOFMEMORY;
00579         *size = required;
00580 
00581         INITDDSTRUCT(ddsd);
00582         if(FAILED(hr = m_pVideoSurface->Lock(NULL, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY|DDLOCK_NOSYSLOCK, NULL)))
00583         {
00584                 // TODO
00585                 return hr;
00586         }
00587 
00588         BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)lpDib;
00589         memset(bih, 0, sizeof(BITMAPINFOHEADER));
00590         bih->biSize = sizeof(BITMAPINFOHEADER);
00591         bih->biWidth = ddsd.dwWidth;
00592         bih->biHeight = ddsd.dwHeight;
00593         bih->biBitCount = 32;
00594         bih->biPlanes = 1;
00595         bih->biSizeImage = bih->biWidth*bih->biHeight*bih->biBitCount>>3;
00596 
00597         BitBltFromRGBToRGB(
00598                 bih->biWidth, bih->biHeight, 
00599                 (BYTE*)(bih + 1), bih->biWidth*bih->biBitCount>>3, bih->biBitCount,
00600                 (BYTE*)ddsd.lpSurface + ddsd.lPitch*(ddsd.dwHeight-1), -(int)ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount);
00601 
00602         m_pVideoSurface->Unlock(NULL);
00603 
00604 /*
00605                         BitBltFromRGBToRGB(
00606                                 w, h, 
00607                                 (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount,
00608                                 (BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmBitsPixel);
00609                         m_pVideoSurfaceOff->Unlock(NULL);
00610                         fOk = true;
00611                 }
00612 */
00613 
00614         return S_OK;
00615 }
00616 
00617 //
00618 // CVMR7AllocatorPresenter
00619 //
00620 
00621 #define MY_USER_ID 0x6ABE51
00622 
00623 CVMR7AllocatorPresenter::CVMR7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
00624         : CDX7AllocatorPresenter(hWnd, hr)
00625         , m_fUseInternalTimer(true)
00626 {
00627     if(FAILED(hr))
00628                 return;
00629 
00630         if(FAILED(hr = m_pSA.CoCreateInstance(CLSID_AllocPresenter)))
00631         {
00632                 hr = E_FAIL;
00633                 return;
00634         }
00635 }
00636 
00637 STDMETHODIMP CVMR7AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00638 {
00639     CheckPointer(ppv, E_POINTER);
00640 
00641         return 
00642                 QI(IVMRSurfaceAllocator)
00643                 QI(IVMRImagePresenter)
00644                 QI(IVMRWindowlessControl)
00645                 __super::NonDelegatingQueryInterface(riid, ppv);
00646 }
00647 
00648 HRESULT CVMR7AllocatorPresenter::CreateDevice()
00649 {
00650         HRESULT hr = __super::CreateDevice();
00651         if(FAILED(hr)) return hr;
00652 
00653         if(m_pIVMRSurfAllocNotify)
00654         {
00655                 HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
00656                 if(FAILED(hr = m_pIVMRSurfAllocNotify->ChangeDDrawDevice(m_pDD, hMonitor)))
00657                         return(false);
00658         }
00659 
00660         return hr;
00661 }
00662 
00663 void CVMR7AllocatorPresenter::DeleteSurfaces()
00664 {
00665     CAutoLock cAutoLock(this);
00666 
00667         m_pSA->FreeSurface(MY_USER_ID);
00668 
00669         __super::DeleteSurfaces();
00670 }
00671 
00672 // ISubPicAllocatorPresenter
00673 
00674 STDMETHODIMP CVMR7AllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
00675 {
00676     CheckPointer(ppRenderer, E_POINTER);
00677 
00678         *ppRenderer = NULL;
00679 
00680         HRESULT hr;
00681 
00682         do
00683         {
00684                 CComPtr<IBaseFilter> pBF;
00685 
00686                 if(FAILED(hr = pBF.CoCreateInstance(CLSID_VideoMixingRenderer)))
00687                         break;
00688 
00689                 CComQIPtr<IVMRFilterConfig> pConfig = pBF;
00690                 if(!pConfig)
00691                         break;
00692 
00693                 if(FAILED(hr = pConfig->SetRenderingMode(VMRMode_Renderless)))
00694                         break;
00695 
00696                 CComQIPtr<IVMRSurfaceAllocatorNotify> pSAN = pBF;
00697                 if(!pSAN)
00698                         break;
00699 
00700                 if(FAILED(hr = pSAN->AdviseSurfaceAllocator(MY_USER_ID, static_cast<IVMRSurfaceAllocator*>(this)))
00701                 || FAILED(hr = AdviseNotify(pSAN)))
00702                         break;
00703 
00704                 CComPtr<IPin> pPin = GetFirstPin(pBF);
00705                 HookNewSegment((IPinC*)(IPin*)pPin);
00706 
00707                 *ppRenderer = (IUnknown*)pBF.Detach();
00708 
00709                 return S_OK;
00710         }
00711         while(0);
00712 
00713     return E_FAIL;
00714 }
00715 
00716 STDMETHODIMP_(void) CVMR7AllocatorPresenter::SetTime(REFERENCE_TIME rtNow)
00717 {
00718         m_fUseInternalTimer = false;
00719         __super::SetTime(rtNow);
00720 }
00721 
00722 // IVMRSurfaceAllocator
00723 
00724 STDMETHODIMP CVMR7AllocatorPresenter::AllocateSurface(DWORD_PTR dwUserID, VMRALLOCATIONINFO* lpAllocInfo, DWORD* lpdwBuffer, LPDIRECTDRAWSURFACE7* lplpSurface)
00725 {
00726         if(!lpAllocInfo || !lpdwBuffer || !lplpSurface)
00727                 return E_POINTER;
00728 
00729         if(!m_pIVMRSurfAllocNotify)
00730                 return E_FAIL;
00731 
00732         HRESULT hr;
00733 
00734     DeleteSurfaces();
00735 
00736         // HACK: yv12 will fail to blt onto the backbuffer anyway, but if we first
00737         // allocate it and then let our FreeSurface callback call m_pSA->FreeSurface,
00738         // then that might stall for about 30 seconds because of some unknown buggy code 
00739         // behind <ddraw surface>->Release()
00740 
00741         if(lpAllocInfo->lpHdr->biBitCount < 16)
00742                 return E_FAIL;
00743 
00744         hr = m_pSA->AllocateSurface(dwUserID, lpAllocInfo, lpdwBuffer, lplpSurface);
00745         if(FAILED(hr))
00746                 return hr;
00747 
00748         m_NativeVideoSize = CSize(abs(lpAllocInfo->lpHdr->biWidth), abs(lpAllocInfo->lpHdr->biHeight));
00749         m_AspectRatio = m_NativeVideoSize;
00750         int arx = lpAllocInfo->szAspectRatio.cx, ary = lpAllocInfo->szAspectRatio.cy;
00751         if(arx > 0 && ary > 0) m_AspectRatio.SetSize(arx, ary);
00752 
00753         if(FAILED(hr = AllocSurfaces()))
00754                 return hr;
00755 
00756         // test if the colorspace is acceptable
00757         if(FAILED(hr = m_pVideoSurface->Blt(NULL, *lplpSurface, NULL, DDBLT_WAIT, NULL)))
00758         {
00759                 DeleteSurfaces();
00760                 return hr;
00761         }
00762 
00763         DDBLTFX fx;
00764         INITDDSTRUCT(fx);
00765         fx.dwFillColor = 0;
00766         m_pVideoSurface->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
00767 
00768         return hr;
00769 }
00770 
00771 STDMETHODIMP CVMR7AllocatorPresenter::FreeSurface(DWORD_PTR dwUserID)
00772 {
00773     DeleteSurfaces();
00774         return S_OK;
00775 }
00776 
00777 STDMETHODIMP CVMR7AllocatorPresenter::PrepareSurface(DWORD_PTR dwUserID, IDirectDrawSurface7* lpSurface, DWORD dwSurfaceFlags)
00778 {
00779     if(!lpSurface)
00780                 return E_POINTER;
00781 
00782         // FIXME: sometimes the msmpeg4/divx3/wmv decoder wants to reuse our 
00783         // surface (expects it to point to the same mem every time), and to avoid 
00784         // problems we can't cal m_pSA->PrepareSurface (flips? clears?).
00785         return S_OK; 
00786 /*
00787         return m_pSA->PrepareSurface(dwUserID, lpSurface, dwSurfaceFlags);
00788 */
00789 }
00790 
00791 STDMETHODIMP CVMR7AllocatorPresenter::AdviseNotify(IVMRSurfaceAllocatorNotify* lpIVMRSurfAllocNotify)
00792 {
00793     CAutoLock cAutoLock(this);
00794         
00795         m_pIVMRSurfAllocNotify = lpIVMRSurfAllocNotify;
00796 
00797         HRESULT hr;
00798         HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
00799         if(FAILED(hr = m_pIVMRSurfAllocNotify->SetDDrawDevice(m_pDD, hMonitor)))
00800                 return hr;
00801 
00802         return m_pSA->AdviseNotify(lpIVMRSurfAllocNotify);
00803 }
00804 
00805 // IVMRImagePresenter
00806 
00807 STDMETHODIMP CVMR7AllocatorPresenter::StartPresenting(DWORD_PTR dwUserID)
00808 {
00809     CAutoLock cAutoLock(this);
00810 
00811     ASSERT(m_pD3DDev);
00812 
00813         return m_pD3DDev ? S_OK : E_FAIL;
00814 }
00815 
00816 STDMETHODIMP CVMR7AllocatorPresenter::StopPresenting(DWORD_PTR dwUserID)
00817 {
00818         return S_OK;
00819 }
00820 
00821 STDMETHODIMP CVMR7AllocatorPresenter::PresentImage(DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo)
00822 {
00823     HRESULT hr;
00824 
00825         {
00826                 if(!lpPresInfo || !lpPresInfo->lpSurf)
00827                         return E_POINTER;
00828 
00829                 CAutoLock cAutoLock(this);
00830 
00831                 hr = m_pVideoSurface->Blt(NULL, lpPresInfo->lpSurf, NULL, DDBLT_WAIT, NULL);
00832 
00833                 if(lpPresInfo->rtEnd > lpPresInfo->rtStart)
00834                 {
00835                         REFERENCE_TIME rtTimePerFrame = lpPresInfo->rtEnd - lpPresInfo->rtStart;
00836                         m_fps = 10000000.0 / rtTimePerFrame;
00837                         if(m_pSubPicQueue) 
00838                         {
00839                                 m_pSubPicQueue->SetFPS(m_fps);
00840                                 if(m_fUseInternalTimer) __super::SetTime(g_tSegmentStart + lpPresInfo->rtStart);
00841                         }
00842                 }
00843 
00844                 CSize VideoSize = m_NativeVideoSize;
00845                 int arx = lpPresInfo->szAspectRatio.cx, ary = lpPresInfo->szAspectRatio.cy;
00846                 if(arx > 0 && ary > 0) VideoSize.cx = VideoSize.cy*arx/ary;
00847                 if(VideoSize != GetVideoSize())
00848                 {
00849                         m_AspectRatio.SetSize(arx, ary);
00850                         AfxGetApp()->m_pMainWnd->PostMessage(WM_REARRANGERENDERLESS);
00851                 }
00852 
00853                 Paint(true);
00854 
00855                 hr = S_OK;
00856         }
00857 
00858         return S_OK;
00859 }
00860 
00861 // IVMRWindowlessControl
00862 //
00863 // It is only implemented (partially) for the dvd navigator's 
00864 // menu handling, which needs to know a few things about the 
00865 // location of our window.
00866 
00867 STDMETHODIMP CVMR7AllocatorPresenter::GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight)
00868 {
00869         CSize vs = m_NativeVideoSize, ar = m_AspectRatio;
00870         // DVD Nav. bug workaround fix
00871         vs.cx = vs.cy * ar.cx / ar.cy;
00872         if(lpWidth) *lpWidth = vs.cx;
00873         if(lpHeight) *lpHeight = vs.cy;
00874         if(lpARWidth) *lpARWidth = ar.cx;
00875         if(lpARHeight) *lpARHeight = ar.cy;
00876         return S_OK;
00877 }
00878 
00879 STDMETHODIMP CVMR7AllocatorPresenter::GetMinIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
00880 STDMETHODIMP CVMR7AllocatorPresenter::GetMaxIdealVideoSize(LONG* lpWidth, LONG* lpHeight) {return E_NOTIMPL;}
00881 STDMETHODIMP CVMR7AllocatorPresenter::SetVideoPosition(const LPRECT lpSRCRect, const LPRECT lpDSTRect) {return E_NOTIMPL;} // we have our own method for this
00882 
00883 STDMETHODIMP CVMR7AllocatorPresenter::GetVideoPosition(LPRECT lpSRCRect, LPRECT lpDSTRect)
00884 {
00885         CopyRect(lpSRCRect, CRect(CPoint(0, 0), m_NativeVideoSize));
00886         CopyRect(lpDSTRect, &m_VideoRect);
00887         // DVD Nav. bug workaround fix
00888         GetNativeVideoSize(&lpSRCRect->right, &lpSRCRect->bottom, NULL, NULL);
00889         return S_OK;
00890 }
00891 
00892 STDMETHODIMP CVMR7AllocatorPresenter::GetAspectRatioMode(DWORD* lpAspectRatioMode)
00893 {
00894         if(lpAspectRatioMode) *lpAspectRatioMode = AM_ARMODE_STRETCHED;
00895         return S_OK;
00896 }
00897 
00898 STDMETHODIMP CVMR7AllocatorPresenter::SetAspectRatioMode(DWORD AspectRatioMode) {return E_NOTIMPL;}
00899 STDMETHODIMP CVMR7AllocatorPresenter::SetVideoClippingWindow(HWND hwnd) {return E_NOTIMPL;}
00900 STDMETHODIMP CVMR7AllocatorPresenter::RepaintVideo(HWND hwnd, HDC hdc) {return E_NOTIMPL;}
00901 STDMETHODIMP CVMR7AllocatorPresenter::DisplayModeChanged() {return E_NOTIMPL;}
00902 STDMETHODIMP CVMR7AllocatorPresenter::GetCurrentImage(BYTE** lpDib) {return E_NOTIMPL;}
00903 STDMETHODIMP CVMR7AllocatorPresenter::SetBorderColor(COLORREF Clr) {return E_NOTIMPL;}
00904 
00905 STDMETHODIMP CVMR7AllocatorPresenter::GetBorderColor(COLORREF* lpClr)
00906 {
00907         if(lpClr) *lpClr = 0;
00908         return S_OK;
00909 }
00910 
00911 STDMETHODIMP CVMR7AllocatorPresenter::SetColorKey(COLORREF Clr) {return E_NOTIMPL;}
00912 STDMETHODIMP CVMR7AllocatorPresenter::GetColorKey(COLORREF* lpClr) {return E_NOTIMPL;}
00913 
00914 //
00915 
00916 static HRESULT AllocDX7Surface(IDirectDraw7* pDD, CSize size, DWORD compression, int bpp, IDirectDrawSurface7** pSurface)
00917 {
00918         if(!pDD || !pSurface || size.cx <= 0 || size.cy <= 0)
00919                 return E_POINTER;
00920 
00921         *pSurface = NULL;
00922 
00923         DDSURFACEDESC2 ddsd;
00924         INITDDSTRUCT(ddsd);
00925         ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
00926         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY;
00927         ddsd.dwWidth = size.cx;
00928         ddsd.dwHeight = size.cy;
00929         ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
00930 
00931         if(compression >= 0x1000)
00932         {
00933                 ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
00934                 ddsd.ddpfPixelFormat.dwFourCC = compression;
00935         }
00936         else if((compression == 0 || compression == 3) && (bpp == 15 || bpp == 16 || bpp == 24 || bpp == 32))
00937         {
00938                 ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
00939                 ddsd.ddpfPixelFormat.dwRGBBitCount = max(bpp, 16);
00940                 ddsd.ddpfPixelFormat.dwRGBAlphaBitMask  = (bpp == 16) ? 0x0000 : (bpp == 15) ? 0x8000 : 0xFF000000;
00941                 ddsd.ddpfPixelFormat.dwRBitMask                 = (bpp == 16) ? 0xf800 : (bpp == 15) ? 0x7c00 : 0x00FF0000;
00942                 ddsd.ddpfPixelFormat.dwGBitMask                 = (bpp == 16) ? 0x07e0 : (bpp == 15) ? 0x03e0 : 0x0000FF00;
00943                 ddsd.ddpfPixelFormat.dwBBitMask                 = (bpp == 16) ? 0x001F : (bpp == 15) ? 0x001F : 0x000000FF;
00944         }
00945 
00946         return pDD->CreateSurface(&ddsd, pSurface, NULL);
00947 }
00948 
00949 //
00950 // CRM7AllocatorPresenter
00951 //
00952 
00953 CRM7AllocatorPresenter::CRM7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
00954         : CDX7AllocatorPresenter(hWnd, hr)
00955 {
00956 }
00957 
00958 STDMETHODIMP CRM7AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00959 {
00960     CheckPointer(ppv, E_POINTER);
00961 
00962         return 
00963                 QI2(IRMAVideoSurface)
00964                 __super::NonDelegatingQueryInterface(riid, ppv);
00965 }
00966 
00967 HRESULT CRM7AllocatorPresenter::AllocSurfaces()
00968 {
00969     CAutoLock cAutoLock(this);
00970 
00971         m_pVideoSurfaceOff = NULL;
00972         m_pVideoSurfaceYUY2 = NULL;
00973 
00974         DDSURFACEDESC2 ddsd;
00975         DDBLTFX fx;
00976 
00977         INITDDSTRUCT(ddsd);
00978         ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
00979         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
00980         ddsd.dwWidth = m_NativeVideoSize.cx;
00981         ddsd.dwHeight = m_NativeVideoSize.cy;
00982         ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
00983         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
00984         ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
00985         ddsd.ddpfPixelFormat.dwRGBAlphaBitMask  = 0xFF000000;
00986         ddsd.ddpfPixelFormat.dwRBitMask                 = 0x00FF0000;
00987         ddsd.ddpfPixelFormat.dwGBitMask                 = 0x0000FF00;
00988         ddsd.ddpfPixelFormat.dwBBitMask                 = 0x000000FF;
00989 
00990         HRESULT hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurfaceOff, NULL);
00991         if(FAILED(hr)) return E_FAIL;
00992 
00993         INITDDSTRUCT(fx);
00994         fx.dwFillColor = 0;
00995         m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
00996 
00997         INITDDSTRUCT(ddsd);
00998         ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
00999         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
01000         ddsd.dwWidth = m_NativeVideoSize.cx;
01001         ddsd.dwHeight = m_NativeVideoSize.cy;
01002         ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
01003         ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
01004         ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
01005         ddsd.ddpfPixelFormat.dwFourCC = '2YUY';
01006 
01007         hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurfaceYUY2, NULL);
01008 
01009         if(FAILED(m_pVideoSurfaceOff->Blt(NULL, m_pVideoSurfaceYUY2, NULL, DDBLT_WAIT, NULL)))
01010                 m_pVideoSurfaceYUY2 = NULL;
01011 
01012         if(m_pVideoSurfaceYUY2)
01013         {
01014                 INITDDSTRUCT(fx);
01015                 fx.dwFillColor = 0x80108010;
01016                 m_pVideoSurfaceYUY2->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
01017         }
01018 
01019         return __super::AllocSurfaces();
01020 }
01021 
01022 void CRM7AllocatorPresenter::DeleteSurfaces()
01023 {
01024     CAutoLock cAutoLock(this);
01025 
01026         m_pVideoSurfaceOff = NULL;
01027         m_pVideoSurfaceYUY2 = NULL;
01028 
01029         __super::DeleteSurfaces();
01030 }
01031 
01032 // IRMAVideoSurface
01033 
01034 STDMETHODIMP CRM7AllocatorPresenter::Blt(UCHAR* pImageData, RMABitmapInfoHeader* pBitmapInfo, REF(PNxRect) inDestRect, REF(PNxRect) inSrcRect)
01035 {
01036         if(!m_pVideoSurface || !m_pVideoSurfaceOff)
01037                 return E_FAIL;
01038 
01039         bool fRGB = false;
01040         bool fYUY2 = false;
01041 
01042         CRect src((RECT*)&inSrcRect), dst((RECT*)&inDestRect), src2(CPoint(0,0), src.Size());
01043         if(src.Width() > dst.Width() || src.Height() > dst.Height())
01044                 return E_FAIL;
01045 
01046         DDSURFACEDESC2 ddsd;
01047 
01048         if(pBitmapInfo->biCompression == '024I')
01049         {
01050                 DWORD pitch = pBitmapInfo->biWidth;
01051                 DWORD size = pitch*abs(pBitmapInfo->biHeight);
01052 
01053                 BYTE* y = pImageData                                    + src.top*pitch + src.left;
01054                 BYTE* u = pImageData + size                             + src.top*(pitch/2) + src.left/2;
01055                 BYTE* v = pImageData + size + size/4    + src.top*(pitch/2) + src.left/2;
01056 
01057                 if(m_pVideoSurfaceYUY2)
01058                 {
01059                         INITDDSTRUCT(ddsd);
01060                         if(SUCCEEDED(m_pVideoSurfaceYUY2->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
01061                         {
01062                                 BitBltFromI420ToYUY2(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, y, u, v, pitch);
01063                                 m_pVideoSurfaceYUY2->Unlock(src2);
01064                                 fYUY2 = true;
01065                         }
01066                 }
01067                 else
01068                 {
01069                         INITDDSTRUCT(ddsd);
01070                         if(SUCCEEDED(m_pVideoSurfaceOff->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
01071                         {
01072                                 BitBltFromI420ToRGB(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount, y, u, v, pitch);
01073                                 m_pVideoSurfaceOff->Unlock(src2);
01074                                 fRGB = true;
01075                         }
01076                 }
01077         }
01078         else if(pBitmapInfo->biCompression == '2YUY')
01079         {
01080                 DWORD w = pBitmapInfo->biWidth;
01081                 DWORD h = abs(pBitmapInfo->biHeight);
01082                 DWORD pitch = pBitmapInfo->biWidth*2;
01083 
01084                 BYTE* yvyu = pImageData + src.top*pitch + src.left*2;
01085 
01086                 if(m_pVideoSurfaceYUY2)
01087                 {
01088                         INITDDSTRUCT(ddsd);
01089                         if(SUCCEEDED(m_pVideoSurfaceYUY2->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
01090                         {
01091                                 BitBltFromYUY2ToYUY2(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, yvyu, pitch);
01092                                 m_pVideoSurfaceYUY2->Unlock(src2);
01093                                 fYUY2 = true;
01094                         }
01095                 }
01096                 else
01097                 {
01098                         INITDDSTRUCT(ddsd);
01099                         if(SUCCEEDED(m_pVideoSurfaceOff->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
01100                         {
01101                                 BitBltFromYUY2ToRGB(src.Width(), src.Height(), (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount, yvyu, pitch);
01102                                 m_pVideoSurfaceOff->Unlock(src2);
01103                                 fRGB = true;
01104                         }
01105                 }
01106         }
01107         else if(pBitmapInfo->biCompression == 0 || pBitmapInfo->biCompression == 3
01108                  || pBitmapInfo->biCompression == 'BGRA')
01109         {
01110                 DWORD w = pBitmapInfo->biWidth;
01111                 DWORD h = abs(pBitmapInfo->biHeight);
01112                 DWORD pitch = pBitmapInfo->biWidth*pBitmapInfo->biBitCount>>3;
01113 
01114                 BYTE* rgb = pImageData + src.top*pitch + src.left*(pBitmapInfo->biBitCount>>3);
01115 
01116                 INITDDSTRUCT(ddsd);
01117                 if(SUCCEEDED(m_pVideoSurfaceOff->Lock(src2, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
01118                 {
01119                         BYTE* lpSurface = (BYTE*)ddsd.lpSurface;
01120                         if(pBitmapInfo->biHeight > 0) {lpSurface += ddsd.lPitch*(src.Height()-1); ddsd.lPitch = -ddsd.lPitch;}
01121                         BitBltFromRGBToRGB(src.Width(), src.Height(), lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount, rgb, pitch, pBitmapInfo->biBitCount);
01122                         fRGB = true;
01123                         m_pVideoSurfaceOff->Unlock(src2);
01124                 }
01125         }
01126 
01127         if(!fRGB && !fYUY2)
01128         {
01129                 DDBLTFX fx;
01130                 INITDDSTRUCT(fx);
01131                 fx.dwFillColor = 0;
01132                 m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
01133 
01134                 HDC hDC;
01135                 if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
01136                 {
01137                         CString str;
01138                         str.Format(_T("Sorry, this format is not supported"));
01139 
01140                         SetBkColor(hDC, 0);
01141                         SetTextColor(hDC, 0x404040);
01142                         TextOut(hDC, 10, 10, str, str.GetLength());
01143 
01144                         m_pVideoSurfaceOff->ReleaseDC(hDC);
01145 
01146                         fRGB = true;
01147                 }
01148         }
01149 
01150 
01151         HRESULT hr;
01152         
01153         if(fRGB)
01154                 hr = m_pVideoSurface->Blt(dst, m_pVideoSurfaceOff, src2, DDBLT_WAIT, NULL);
01155         if(fYUY2)
01156                 hr = m_pVideoSurface->Blt(dst, m_pVideoSurfaceYUY2, src2, DDBLT_WAIT, NULL);
01157     
01158         Paint(true);
01159 
01160         return PNR_OK;
01161 }
01162 
01163 STDMETHODIMP CRM7AllocatorPresenter::BeginOptimizedBlt(RMABitmapInfoHeader* pBitmapInfo)
01164 {
01165     CAutoLock cAutoLock(this);
01166         DeleteSurfaces();
01167         m_NativeVideoSize = m_AspectRatio = CSize(pBitmapInfo->biWidth, abs(pBitmapInfo->biHeight));
01168         if(FAILED(AllocSurfaces())) return E_FAIL;
01169         return PNR_NOTIMPL;
01170 }
01171 
01172 STDMETHODIMP CRM7AllocatorPresenter::OptimizedBlt(UCHAR* pImageBits, REF(PNxRect) rDestRect, REF(PNxRect) rSrcRect)
01173 {
01174         return PNR_NOTIMPL;
01175 }
01176 
01177 STDMETHODIMP CRM7AllocatorPresenter::EndOptimizedBlt()
01178 {
01179         return PNR_NOTIMPL;
01180 }
01181 
01182 STDMETHODIMP CRM7AllocatorPresenter::GetOptimizedFormat(REF(RMA_COMPRESSION_TYPE) ulType)
01183 {
01184         return PNR_NOTIMPL;
01185 }
01186 
01187 STDMETHODIMP CRM7AllocatorPresenter::GetPreferredFormat(REF(RMA_COMPRESSION_TYPE) ulType)
01188 {
01189         ulType = RMA_I420;
01190         return PNR_OK;
01191 }
01192 
01193 //
01194 // CQT7AllocatorPresenter
01195 //
01196 
01197 CQT7AllocatorPresenter::CQT7AllocatorPresenter(HWND hWnd, HRESULT& hr) 
01198         : CDX7AllocatorPresenter(hWnd, hr)
01199 {
01200 }
01201 
01202 STDMETHODIMP CQT7AllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
01203 {
01204     CheckPointer(ppv, E_POINTER);
01205 
01206         return 
01207                 QI(IQTVideoSurface)
01208                 __super::NonDelegatingQueryInterface(riid, ppv);
01209 }
01210 
01211 HRESULT CQT7AllocatorPresenter::AllocSurfaces()
01212 {
01213     CAutoLock cAutoLock(this);
01214 
01215         m_pVideoSurfaceOff = NULL;
01216 
01217         DDSURFACEDESC2 ddsd;
01218         INITDDSTRUCT(ddsd);
01219         ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
01220         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
01221         ddsd.dwWidth = m_NativeVideoSize.cx;
01222         ddsd.dwHeight = m_NativeVideoSize.cy;
01223         ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
01224         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
01225         ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
01226         ddsd.ddpfPixelFormat.dwRGBAlphaBitMask  = 0xFF000000;
01227         ddsd.ddpfPixelFormat.dwRBitMask                 = 0x00FF0000;
01228         ddsd.ddpfPixelFormat.dwGBitMask                 = 0x0000FF00;
01229         ddsd.ddpfPixelFormat.dwBBitMask                 = 0x000000FF;
01230 
01231         HRESULT hr = m_pDD->CreateSurface(&ddsd, &m_pVideoSurfaceOff, NULL);
01232         if(FAILED(hr)) return E_FAIL;
01233 
01234         DDBLTFX fx;
01235         INITDDSTRUCT(fx);
01236         fx.dwFillColor = 0;
01237         m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
01238 
01239         return __super::AllocSurfaces();
01240 }
01241 
01242 void CQT7AllocatorPresenter::DeleteSurfaces()
01243 {
01244     CAutoLock cAutoLock(this);
01245 
01246         m_pVideoSurfaceOff = NULL;
01247 
01248         __super::DeleteSurfaces();
01249 }
01250 
01251 // IQTVideoSurface
01252 
01253 STDMETHODIMP CQT7AllocatorPresenter::BeginBlt(const BITMAP& bm)
01254 {
01255     CAutoLock cAutoLock(this);
01256 
01257         DeleteSurfaces();
01258 
01259         m_NativeVideoSize = m_AspectRatio = CSize(bm.bmWidth, abs(bm.bmHeight));
01260 
01261         HRESULT hr;
01262         if(FAILED(hr = AllocSurfaces()))
01263                 return hr;
01264 
01265         return S_OK;
01266 }
01267 
01268 STDMETHODIMP CQT7AllocatorPresenter::DoBlt(const BITMAP& bm)
01269 {
01270         if(!m_pVideoSurface || !m_pVideoSurfaceOff)
01271                 return E_FAIL;
01272 
01273         bool fOk = false;
01274 
01275         DDSURFACEDESC2 ddsd;
01276         INITDDSTRUCT(ddsd);
01277         if(FAILED(m_pVideoSurfaceOff->GetSurfaceDesc(&ddsd)))
01278                 return E_FAIL;
01279 
01280         int w = bm.bmWidth;
01281         int h = abs(bm.bmHeight);
01282         int bpp = bm.bmBitsPixel;
01283 
01284         if((bpp == 16 || bpp == 24 || bpp == 32) && w == ddsd.dwWidth && h == ddsd.dwHeight)
01285         {
01286                 INITDDSTRUCT(ddsd);
01287                 if(SUCCEEDED(m_pVideoSurfaceOff->Lock(NULL, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY, NULL)))
01288                 {
01289                         BitBltFromRGBToRGB(
01290                                 w, h, 
01291                                 (BYTE*)ddsd.lpSurface, ddsd.lPitch, ddsd.ddpfPixelFormat.dwRGBBitCount,
01292                                 (BYTE*)bm.bmBits, bm.bmWidthBytes, bm.bmBitsPixel);
01293                         m_pVideoSurfaceOff->Unlock(NULL);
01294                         fOk = true;
01295                 }
01296         }
01297 
01298         if(!fOk)
01299         {
01300                 DDBLTFX fx;
01301                 INITDDSTRUCT(fx);
01302                 fx.dwFillColor = 0;
01303                 m_pVideoSurfaceOff->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &fx);
01304 
01305                 HDC hDC;
01306                 if(SUCCEEDED(m_pVideoSurfaceOff->GetDC(&hDC)))
01307                 {
01308                         CString str;
01309                         str.Format(_T("Sorry, this format is not supported"));
01310 
01311                         SetBkColor(hDC, 0);
01312                         SetTextColor(hDC, 0x404040);
01313                         TextOut(hDC, 10, 10, str, str.GetLength());
01314 
01315                         m_pVideoSurfaceOff->ReleaseDC(hDC);
01316                         
01317                 }
01318         }
01319 
01320         m_pVideoSurface->Blt(NULL, m_pVideoSurfaceOff, NULL, DDBLT_WAIT, NULL);
01321 
01322         Paint(true);
01323 
01324         return S_OK;
01325 }

Generated on Tue Dec 13 14:46:49 2005 for guliverkli by  doxygen 1.4.5