- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }