//==========================================================================; // MSVidVideoRenderer.h : Declaration of the CMSVidVideoRenderer // copyright (c) Microsoft Corp. 1998-1999. //==========================================================================; #ifndef __MSVidVIDEORENDERERIMPL_H_ #define __MSVidVIDEORENDERERIMPL_H_ #pragma once #include #include #include #include #include #include "vidrect.h" #include "vrsegimpl.h" #include "outputimpl.h" #include "seg.h" #include "videorenderercp.h" #include "strmif.h" #include "resource.h" // main symbols //typedef CComQIPtr PQVMRSAlloc; //typedef CComQIPtr PQVMRAlphaBitm; ///////////////////////////////////////////////////////////////////////////// // CMSVidVideoRenderer template class DECLSPEC_NOVTABLE IMSVidVideoRendererImpl : public IMSVidOutputDeviceImpl, public IMSVidVRGraphSegmentImpl { public: IMSVidVideoRendererImpl() { m_opacity = -1; m_rectPosition.top = -1; m_rectPosition.left = -1; m_rectPosition.bottom = -1; m_rectPosition.right = -1; m_SourceSize = sslFullSize; m_lOverScan = 1; } virtual ~IMSVidVideoRendererImpl() { m_PQIPicture.Release(); } protected: typedef IMSVidVRGraphSegmentImpl VRSegbasetype; PQIPic m_PQIPicture; FLOAT m_opacity; NORMALIZEDRECT m_rectPosition; SourceSizeList m_SourceSize; LONG m_lOverScan; CScalingRect m_ClipRect; public: virtual HRESULT SetVRConfig() { HRESULT hr = S_OK; if (m_pVMR) { hr = VRSegbasetype::SetVRConfig(); if (FAILED(hr)) { return hr; } if(m_pVMRWC){ hr = m_pVMRWC->SetColorKey(m_ColorKey); } else{ return ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), E_FAIL); } if (FAILED(hr) && hr != E_NOTIMPL) { return hr; } } return NOERROR; } STDMETHOD(Refresh)() { ReComputeSourceRect(); return VRSegbasetype::Refresh(); } // IMSVidVideoRenderer STDMETHOD(get_OverScan)(LONG * plPercent) { if (!m_fInit) { return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } if (plPercent == NULL) { return E_POINTER; } try { *plPercent = m_lOverScan; return NOERROR; } catch(...) { return E_UNEXPECTED; } } STDMETHOD(put_OverScan)(LONG lPercent) { if (!m_fInit) { return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } try { if(lPercent > 4900 || lPercent < 0){ return ImplReportError(__uuidof(T), IDS_INVALID_OVERSCAN, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } m_lOverScan = lPercent; return ReComputeSourceRect(); } catch(...) { return E_UNEXPECTED; } } STDMETHOD(get_SourceSize)(/*[out, retval]*/ SourceSizeList *pCurrentSize) { if (!m_fInit) { return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } if (!pCurrentSize) { return E_POINTER; } try { *pCurrentSize = m_SourceSize; return NOERROR; } catch(...) { return E_UNEXPECTED; } } // TODO: add checks for input value being null STDMETHOD(get_MaxVidRect)(/*[out, retval]*/ IMSVidRect **ppVidRect){ HRESULT hr = S_OK; CComQIPtrPQIMSVRect; try{ PQIMSVRect = static_cast(new CVidRect(0,0,0,0)); if(!PQIMSVRect){ throw(E_UNEXPECTED); } if(!m_pVMR){ throw(ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED)); } long dwWidth, dwHeight; if(m_pVMRWC){ hr = m_pVMRWC->GetMaxIdealVideoSize(&dwWidth, &dwHeight); if(FAILED(hr)){ throw(hr); } } else{ throw(ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IVMRFilterConfig), E_FAIL)); } PQIMSVRect->put_Height(dwHeight); PQIMSVRect->put_Width(dwWidth); } catch(HRESULT hres){ PQIMSVRect = static_cast(new CVidRect(-1,-1,-1,-1)); *ppVidRect = PQIMSVRect.Detach(); return hres; } *ppVidRect = PQIMSVRect.Detach(); return hr; } STDMETHOD(get_MinVidRect)(/*[out, retval]*/ IMSVidRect **ppVidRect){ HRESULT hr = S_OK; CComQIPtrPQIMSVRect; try{ PQIMSVRect = static_cast(new CVidRect(0,0,0,0)); if(!PQIMSVRect){ throw(E_UNEXPECTED); } if(!m_pVMR){ throw(ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED)); } long dwWidth, dwHeight; if(m_pVMRWC){ hr = m_pVMRWC->GetMinIdealVideoSize(&dwWidth, &dwHeight); if(FAILED(hr)){ throw(hr); } } else{ throw(ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IMSVidVideoRenderer), E_FAIL)); } PQIMSVRect->put_Height(dwHeight); PQIMSVRect->put_Width(dwWidth); } catch(HRESULT hres){ PQIMSVRect = static_cast(new CVidRect(-1,-1,-1,-1)); *ppVidRect = PQIMSVRect.Detach(); return hres; } *ppVidRect = PQIMSVRect.Detach(); return hr; } STDMETHOD(put_SourceSize)(/*[in]*/ SourceSizeList NewSize) { if (!m_fInit) { return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } try { SourceSizeList prev = m_SourceSize; m_SourceSize = NewSize; if (m_SourceSize != prev) { return ReComputeSourceRect(); } return NOERROR; } catch(...) { return E_UNEXPECTED; } } STDMETHOD(get_CustomCompositorClass)(/*[out, retval]*/ BSTR *CompositorCLSID) { try{ if(!CompositorCLSID){ return E_POINTER; } GUID2 gRetVal; HRESULT hr = get__CustomCompositorClass(&gRetVal); if(SUCCEEDED(hr)){ *CompositorCLSID = gRetVal.GetBSTR(); return S_OK; } } catch(...){ return E_UNEXPECTED; } return S_OK; } STDMETHOD(get__CustomCompositorClass)(/*[out, retval]*/ GUID* CompositorCLSID) { HRESULT hr = S_OK; try{ if(!CompositorCLSID){ return E_POINTER; } if(m_compositorGuid != GUID_NULL){ *CompositorCLSID = m_compositorGuid; return S_OK; } PQVMRImageComp pRetVal; hr = get__CustomCompositor(&pRetVal); if(FAILED(hr)){ return hr; } CComQIPtr ipRet(pRetVal); hr = ipRet->GetClassID((CLSID*)CompositorCLSID); if(SUCCEEDED(hr)){ return S_OK; } else{ return E_UNEXPECTED; } } catch(...){ return E_UNEXPECTED; } return S_OK; } STDMETHOD(put_CustomCompositorClass)(/*[in]*/ BSTR CompositorCLSID) { try{ GUID2 inGuid(CompositorCLSID); HRESULT hr = put__CustomCompositorClass(inGuid); if(SUCCEEDED(hr)){ return S_OK; } else{ return hr; } } catch(...){ return E_UNEXPECTED; } return S_OK; } STDMETHOD(put__CustomCompositorClass)(/*[in]*/ REFCLSID CompositorCLSID) { try{ CComQIPtrIVMRICPtr; IVMRICPtr.Release(); HRESULT hr = CoCreateInstance( CompositorCLSID, NULL, CLSCTX_INPROC_SERVER, IID_IVMRImageCompositor, (LPVOID*) &IVMRICPtr); if(FAILED(hr)){ return E_UNEXPECTED; } hr = put__CustomCompositor(IVMRICPtr); if(FAILED(hr)){ return hr; } else{ return S_OK; } } catch(...){ return E_UNEXPECTED; } return S_OK; } STDMETHOD(get__CustomCompositor)(/*[out, retval]*/ IVMRImageCompositor** Compositor) { try{ if(!Compositor){ return E_POINTER; } if(!ImCompositor){ return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED);; } else{ *Compositor = ImCompositor; return S_OK; } } catch(...){ return E_UNEXPECTED; } return S_OK; } STDMETHOD(put__CustomCompositor)(/*[in]*/ IVMRImageCompositor* Compositor) { try{ if(!Compositor){ return E_POINTER; } ImCompositor = Compositor; HRESULT hr = CleanupVMR(); if(FAILED(hr)){ return hr; } } catch(...){ return E_UNEXPECTED; } return S_OK; } STDMETHOD(get_AvailableSourceRect)(IMSVidRect **ppVidRect) { CComQIPtrPQIMSVRect = static_cast(new CVidRect(0,0,0,0)); try{ if(!ppVidRect){ return E_POINTER; } SIZE Size, Ar; HRESULT hr = get_NativeSize(&Size, &Ar); hr = PQIMSVRect->put_Height(Size.cy); if(FAILED(hr)){ throw(hr); } hr = PQIMSVRect->put_Width(Size.cx); if(FAILED(hr)){ throw(hr); } } catch(...){ return E_UNEXPECTED; } *ppVidRect = PQIMSVRect.Detach(); return S_OK; } STDMETHOD(put_ClippedSourceRect)(IMSVidRect *pVidRect) { if (!m_fInit) { return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } if (!pVidRect) { return E_POINTER; } try { m_ClipRect = *(static_cast(static_cast(pVidRect))); return ReComputeSourceRect(); } catch(...) { return E_UNEXPECTED; } } STDMETHOD(get_ClippedSourceRect)(IMSVidRect **ppVidRect) { if (!m_fInit) { return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } if (!ppVidRect) { return E_POINTER; } try { CComQIPtrPQIMSVRect = static_cast(new CVidRect(-1,-1,-1,-1)); PQIMSVRect->put_Left(m_ClipRect.left); PQIMSVRect->put_Height(m_ClipRect.bottom - m_ClipRect.top); PQIMSVRect->put_Top(m_ClipRect.top); PQIMSVRect->put_Width(m_ClipRect.right - m_ClipRect.left); *ppVidRect = PQIMSVRect.Detach(); return S_OK; } catch(...) { return E_UNEXPECTED; } } /*************************************************************************/ /* Function: Capture */ /* Description: Returns the current image on screen */ /*************************************************************************/ STDMETHOD(Capture)(IPictureDisp **currentImage){ HBITMAP hBitmap = 0; HPALETTE hPalette = 0; //VMRALPHABITMAP vmrAlphaBitmapStruct; CComQIPtr retPicture; PICTDESC PictDescStruct; HRESULT hr = S_OK; BYTE *lpDIB = NULL; try{ if(!currentImage){ throw(E_POINTER); } if(!m_pVMR){ throw(E_FAIL); } if(m_pVMRWC){ hr = m_pVMRWC->GetCurrentImage(&lpDIB); } else{ throw(ImplReportError(__uuidof(T), IDS_E_NOTWNDLESS, __uuidof(IMSVidVideoRenderer), E_FAIL)); } if(FAILED(hr)){ throw(hr); } HDC curDC = GetDC(NULL); UINT wUsage = DIB_RGB_COLORS; DWORD dwFlags = CBM_INIT; hBitmap = CreateDIBitmap(curDC, reinterpret_cast(lpDIB), dwFlags, reinterpret_cast((LPBYTE)(lpDIB) + (int)(reinterpret_cast(lpDIB)->biSize)), reinterpret_cast(lpDIB), wUsage); ReleaseDC(NULL,curDC); ZeroMemory(&PictDescStruct, sizeof(PictDescStruct)); PictDescStruct.bmp.hbitmap = hBitmap; PictDescStruct.bmp.hpal = NULL; PictDescStruct.picType = PICTYPE_BITMAP; PictDescStruct.cbSizeofstruct = sizeof(PictDescStruct); hr = OleCreatePictureIndirect(&PictDescStruct, IID_IPicture, TRUE, (void **)&retPicture); if(SUCCEEDED(hr)){ hr = retPicture.QueryInterface(reinterpret_cast(currentImage)); return hr; } else{ throw(hr); } } catch(HRESULT hres){ hr = hres; } catch(...){ hr = E_UNEXPECTED; } if(lpDIB){ CoTaskMemFree(lpDIB); } return hr; } /*************************************************************************/ /* Function: get_MixerBitmap */ /* Description: Returns the current alpha bitmap to script wrapped in a */ /* IPictureDisp. */ /*************************************************************************/ STDMETHOD(get_MixerBitmap)(/*[out,retval]*/ IPictureDisp** ppIPDisp){ #if 0 HDC *pHDC = NULL; HBITMAP hBitmap = 0; HPALETTE hPalette = 0; VMRALPHABITMAP vmrAlphaBitmapStruct; PQIPicDisp retPicture; CComQIPtr PQIVMRMixerBitmap; PICTDESC PictDescStruct; try{ HRESULT hr = get__MixerBitmap(&PQIVMRMixerBitmap); if(FAILED(hr)){ return hr; } hr = PQIVMRMixerBitmap->GetAlphaBitmapParameters(&vmrAlphaBitmapStruct); if(FAILED(hr)){ return hr; } hr = vmrAlphaBitmapStruct.pDDS->GetDC(pHDC); if(FAILED(hr)){ return hr; } hBitmap = static_cast(GetCurrentObject(*pHDC, OBJ_BITMAP)); if(!hBitmap){ return hr; } hPalette = static_cast(GetCurrentObject(*pHDC, OBJ_PAL)); if(!hPalette){ return hr ; } PictDescStruct.bmp.hbitmap = hBitmap; PictDescStruct.bmp.hpal = hPalette; PictDescStruct.picType = PICTYPE_BITMAP; PictDescStruct.cbSizeofstruct = sizeof(PictDescStruct.bmp); hr = OleCreatePictureIndirect(&PictDescStruct, IID_IPictureDisp, true, reinterpret_cast (&retPicture)); if(FAILED(hr)){ return hr; } } catch(HRESULT hr){ return hr; } catch(...){ return E_FAIL; } ppIPDisp = &retPicture.Detach(); return S_OK; #endif // If m_PQIPicture is set, return it try{ if(m_PQIPicture){ CComQIPtr PQIPDisp(m_PQIPicture); *ppIPDisp = PQIPDisp.Detach(); throw S_OK; } else{ throw ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } } catch(HRESULT hres){ return hres; } catch(...){ return E_UNEXPECTED; } } /*************************************************************************/ /* Function: get__MixerBitmap */ /* Description: Returns the IVMRMixerBitmap from the VMR */ /*************************************************************************/ STDMETHOD(get__MixerBitmap)(/*[out, retval]*/ IVMRMixerBitmap ** ppIVMRMBitmap){ try{ if(!ppIVMRMBitmap){ return E_POINTER; } // Make sure there is a VMR filter init'ed if(!m_pVMR){ return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } CComQIPtr PQIVMRMBitmap(m_pVMR); *ppIVMRMBitmap = PQIVMRMBitmap.Detach(); } catch(HRESULT hr){ return hr; } catch(...){ return E_UNEXPECTED; } return S_OK; } /*************************************************************************/ /* Function: put_MixerBitmap */ /* Description: Updates the current VMR Alpha Bitmap */ /* uses SutupMixerBitmap helper function */ /*************************************************************************/ STDMETHOD(put_MixerBitmap)(/*[in*/ IPictureDisp* pIPDisp){ try{ return SetupMixerBitmap(pIPDisp); } catch(HRESULT hr){ return hr; } catch(...){ return E_UNEXPECTED; } } /*************************************************************************/ /* Function: put__MixerBitmap */ /* Description: Updates the current VMR Alpha Bitmap */ /* directly using the VMR fucntions */ /*************************************************************************/ STDMETHOD(put__MixerBitmap)(/*[in]*/ VMRALPHABITMAP * pVMRAlphaBitmapStruct){ //pMixerPicture try{ HRESULT hr = S_OK; if(!pVMRAlphaBitmapStruct){ return E_POINTER; } // Make sure there is a vmr to add the bitmap to if(!m_pVMR){ return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } // Querry the vmr for the MixerBitmap Interface CComQIPtr pVMRMBitmap(m_pVMR); if (!pVMRMBitmap) { return E_UNEXPECTED; } // Set the mixer bitmap to pVMRAlphaBitmapStruct hr = pVMRMBitmap->SetAlphaBitmap(pVMRAlphaBitmapStruct); return hr; } catch(HRESULT hr){ return hr; } catch(...){ return E_UNEXPECTED; } } /**************************************************************************/ /* Function: get_MixerBitmapPositionRect */ /* Description: Lets script folk access the position of the overlay bitmap*/ /* the units are normalized vs the display rect so the values*/ /* should be between 0 and 1 though will be converted if they*/ /* are not */ /**************************************************************************/ STDMETHOD(get_MixerBitmapPositionRect)(/*[out,retval]*/IMSVidRect **ppIMSVRect){ HRESULT hr = S_OK; CComQIPtrPQIMSVRect; try{ CComQIPtr PQIVMRMBitmap; PQIMSVRect = static_cast(new CVidRect(-1,-1,-1,-1)); VMRALPHABITMAP VMRAlphaBitmap; if(!m_pVMR){ hr = S_FALSE; throw(hr); } hr = get__MixerBitmap(&PQIVMRMBitmap); // If the VMRBitmap is not set on the VRM, if it is not make sure that the local one is set if(SUCCEEDED(hr) ){ // QI for the Parameters hr = PQIVMRMBitmap->GetAlphaBitmapParameters(&VMRAlphaBitmap); // if it fails or they are not set make sure that the local copy is if(SUCCEEDED(hr)){ // Make sure that the rDest points are valid top and left : [0,1) // and right and bottom (0,1] if(VMRAlphaBitmap.rDest.top >= 0 && VMRAlphaBitmap.rDest.left >= 0 && VMRAlphaBitmap.rDest.top < 1 && VMRAlphaBitmap.rDest.left < 1 && VMRAlphaBitmap.rDest.right <= 1 && VMRAlphaBitmap.rDest.bottom <= 1 && VMRAlphaBitmap.rDest.right > 0 && VMRAlphaBitmap.rDest.bottom > 0){ // Make sure the local copy of the normalized rect is upto date m_rectPosition = VMRAlphaBitmap.rDest; } } } if( m_rectPosition.left < 0 || m_rectPosition.top < 0 || m_rectPosition.right < 0 || m_rectPosition.bottom < 0 ){ hr = S_FALSE; throw(hr); } else{ // Convert and copy the values in the local copy of the normalized rect to the return rect hr = PQIMSVRect->put_Top(static_cast (m_rectPosition.top * m_rectDest.Height())); if(FAILED(hr)){ hr = ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); throw(hr); } // bottom * height - top hr = PQIMSVRect->put_Height(static_cast((m_rectPosition.bottom * m_rectDest.Height()) - (m_rectPosition.top * m_rectDest.Height()))); if(FAILED(hr)){ hr = ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); throw(hr); } // right * width - left hr = PQIMSVRect->put_Width(static_cast(m_rectPosition.right * m_rectDest.Width() - (m_rectPosition.left * m_rectDest.Width()))); if(FAILED(hr)){ hr = ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); throw(hr); } hr = PQIMSVRect->put_Left(static_cast(m_rectPosition.left * m_rectDest.Width())); if(FAILED(hr)){ hr = ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); throw(hr); } } *ppIMSVRect = PQIMSVRect.Detach(); return S_OK; } catch(HRESULT hres){ if(FAILED(hres)){ return hres; } if(m_rectDest){ PQIMSVRect.Release(); PQIMSVRect = static_cast(new CVidRect(m_rectDest)); } else{ PQIMSVRect.Release(); PQIMSVRect = static_cast(new CVidRect(-1,-1,-1,-1)); } *ppIMSVRect = PQIMSVRect.Detach(); return S_FALSE; } catch(...){ return E_UNEXPECTED; } } /**************************************************************************/ /* Function: put_MixerBitmapPositionRect */ /* Description: Lets script folk change the position of the overlay bitmap*/ /* the units are normalized vs the display rect so the values*/ /* should be between 0 and 1 though will be converted if they*/ /* are not */ /**************************************************************************/ STDMETHOD(put_MixerBitmapPositionRect)(/*[in]*/ IMSVidRect *pIMSVRect){ if(pIMSVRect){ NORMALIZEDRECT NormalizedRectStruct; long lValue; NormalizedRectStruct.left = -1.f; NormalizedRectStruct.top = -1.f; NormalizedRectStruct.right = -1.f; NormalizedRectStruct.bottom = -1.f; if(SUCCEEDED(pIMSVRect->get_Left(&lValue))){ if(m_rectDest.Width() != 0){ // check m_rectDest.Width() for zero if(lValue > 0){ NormalizedRectStruct.left = static_cast(lValue)/static_cast(m_rectDest.Width()); } else{ NormalizedRectStruct.left = static_cast(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Top(&lValue))){ if(m_rectDest.Height() != 0){ if(lValue > 0){ NormalizedRectStruct.top = static_cast(lValue)/static_cast(m_rectDest.Height()); } else{ NormalizedRectStruct.top = static_cast(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Width(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.right = (static_cast(lValue)/static_cast(m_rectDest.Width())) + static_cast(NormalizedRectStruct.left); } } } if(SUCCEEDED(pIMSVRect->get_Height(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.bottom = (static_cast(lValue)/static_cast(m_rectDest.Height())) + static_cast(NormalizedRectStruct.top); } } } if(NormalizedRectStruct.top < 0 || NormalizedRectStruct.left < 0 || NormalizedRectStruct.top > 1 || NormalizedRectStruct.left > 1 || NormalizedRectStruct.right < 0 || NormalizedRectStruct.bottom < 0 || NormalizedRectStruct.right > 1 || NormalizedRectStruct.bottom > 1){ return ImplReportError(__uuidof(T), IDS_E_MIXERSRC, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } m_rectPosition = NormalizedRectStruct; } if(m_PQIPicture == NULL){ return S_OK; } else{ return SetupMixerBitmap(reinterpret_cast(-1)); } } /**************************************************************************/ /* Function: get_MixerBitmapOpacity */ /* Description: lets script access the opacity value */ /* should be between 0 and 100 (%) */ /**************************************************************************/ STDMETHOD(get_MixerBitmapOpacity)(/*[out,retval]*/ int *pwOpacity){ CComQIPtr PQIVMRMBitmap; VMRALPHABITMAP VMRAlphaBitmapStruct; HRESULT hr = get__MixerBitmap(&PQIVMRMBitmap); if(SUCCEEDED(hr)){ hr = PQIVMRMBitmap->GetAlphaBitmapParameters(&VMRAlphaBitmapStruct); if(SUCCEEDED(hr)){ if(m_opacity != VMRAlphaBitmapStruct.fAlpha){ m_opacity = VMRAlphaBitmapStruct.fAlpha; } } } if(m_opacity == -1){ return ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED); } if(m_opacity > 1 || m_opacity < 0){ return E_UNEXPECTED; } *pwOpacity = static_cast(m_opacity*100); return S_OK; } /**************************************************************************/ /* Function: put_MixerBitmapOpacity */ /* Description: lets script set the value opacity */ /* should be between 0 and 100 (%) */ /**************************************************************************/ STDMETHOD(put_MixerBitmapOpacity)(/*[in]*/ int wOpacity){ // make sure the value is between 0 and 100 if(wOpacity >=0 && wOpacity <= 100){ if(wOpacity == 0){ //if it is 0 set it by hand instead of deviding by 0 m_opacity = static_cast(wOpacity); } m_opacity = static_cast(wOpacity)/100.f; } else{ return ImplReportError(__uuidof(T), IDS_E_OPACITY, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } if(!m_PQIPicture){ return S_OK; } else{ HRESULT hr = SetupMixerBitmap(reinterpret_cast(-1)); return hr; } } /**************************************************************************/ /* Function: SetupMixerBitmap */ /* Description: big nasty function to set bitmap, opacity and the position*/ /* rect. It wraps everyting up in a mixer bitmap struct and */ /* then passes it off to put__MixerBitmap */ /* It is both a helper function and a automation method so */ /* that script people can make sure that transparent overlays*/ /* dont show up opaque for a few frames */ /* for reference the vmralphabitmap struct */ /* typedef struct _VMRALPHABITMAP { */ /* DWORD dwFlags;// flags word = VMRBITMAP_HDC */ /* HDC hdc; // DC for the bitmap to copy */ /* LPDIRECTDRAWSURFACE7 pDDS; // DirectDraw surface to copy IGNORED */ /* RECT rSrc; // rectangle to copy from the sourceR */ /* NORMALIZEDRECT rDest; // output rectangle in composition space*/ /* FLOAT fAlpha; // opacity of the bitmap */ /* } VMRALPHABITMAP, *PVMRALPHABITMAP; */ /**************************************************************************/ STDMETHOD(SetupMixerBitmap)(/*[in]*/ IPictureDisp* pIPDisp = NULL, /*[in]*/ long wOpacity = -1, /*[in]*/ IMSVidRect *pIMSVRect = NULL){ VMRALPHABITMAP VMRAlphaBitmapStruct; ZeroMemory(&VMRAlphaBitmapStruct, sizeof(VMRALPHABITMAP)); RECT rSource; ZeroMemory(&rSource, sizeof(RECT)); long lPicHeight, lPicWidth; HRESULT hr = S_OK; try{ if(!pIPDisp){ if(m_PQIPicture){ m_PQIPicture.Release(); } VMRAlphaBitmapStruct.dwFlags = VMRBITMAP_DISABLE; return hr = put__MixerBitmap(&VMRAlphaBitmapStruct); } // Our input is a IPictureDisp which we need to massage into a VMRALPHABITMAP // Problem is that it does not quite all go in but what does we will keep and pass on up if(pIPDisp == reinterpret_cast(-1)){ CComQIPtrPQIPicture(m_PQIPicture); if(!PQIPicture){ return S_OK; } } else if(pIPDisp){ // QI for a IPicture CComQIPtrPQIPicture(pIPDisp); if(!PQIPicture){ return E_NOINTERFACE; } // Save the IPicture for possible use later m_PQIPicture = PQIPicture; } // Get the source rect size (and for some reason ole returns the size // in tenths of a millimeter so I need to convert it) short shortType; m_PQIPicture->get_Type(&shortType); if(shortType != PICTYPE_BITMAP){ return ImplReportError(__uuidof(T), IDS_E_MIXERBADFORMAT, __uuidof(IMSVidVideoRenderer), E_INVALIDARG); // Need to add a the is not a valid picture string } hr = m_PQIPicture->get_Height(&lPicHeight); if(FAILED(hr)){ return ImplReportError(__uuidof(T), IDS_E_IPICTURE, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } hr = m_PQIPicture->get_Width(&lPicWidth); if(FAILED(hr)){ return ImplReportError(__uuidof(T), IDS_E_IPICTURE, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } SIZEL x, y; AtlHiMetricToPixel((const SIZEL*)&lPicWidth, &(x)); AtlHiMetricToPixel((const SIZEL*)&lPicHeight, &(y)); // The AtlHiMetricToPixel function returns a size with the cx value set (no idea why) rSource.right = x.cx; rSource.bottom = y.cx; // create a hdc to store the bitmap HDC memHDC = CreateCompatibleDC(NULL); // create a bitmap to store in the hdc HBITMAP memHBIT = 0; // pull out the bitmap from the IlPicture hr = m_PQIPicture->get_Handle(reinterpret_cast(&memHBIT)); if(FAILED(hr)){ return ImplReportError(__uuidof(T), IDS_E_IPICTURE, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } // Stuff the bitmap into a hdc and keep handle to delete bitmap later HBITMAP delHBIT = static_cast(SelectObject(memHDC, memHBIT)); // Put all of the collected info into a VMRBITMAP stuct and pass it on VMRAlphaBitmapStruct.rSrc = rSource; VMRAlphaBitmapStruct.hdc = memHDC; VMRAlphaBitmapStruct.dwFlags = VMRBITMAP_HDC; // If the wOpacity value is valid use it if(wOpacity >=0 && wOpacity <= 100){ if(wOpacity == 0){ m_opacity = wOpacity; } m_opacity = static_cast(wOpacity/100.f); VMRAlphaBitmapStruct.fAlpha = static_cast(m_opacity); } // wOpacity is not set so check other values // if m_opacity is set use it, if not default to 50% (.5) else if (wOpacity == -1){ if(m_opacity < 0){ VMRAlphaBitmapStruct.fAlpha = .5f; } else{ VMRAlphaBitmapStruct.fAlpha = m_opacity; } } // Bad wOpacity value give them an error else{ return ImplReportError(__uuidof(T), IDS_E_OPACITY, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } // If the m_rectPostion is set use it, else default to full screen if(pIMSVRect){ NORMALIZEDRECT NormalizedRectStruct; long lValue; NormalizedRectStruct.left = -1.f; NormalizedRectStruct.top = -1.f; NormalizedRectStruct.right = -1.f; NormalizedRectStruct.bottom = -1.f; if(SUCCEEDED(pIMSVRect->get_Left(&lValue))){ if(m_rectDest.Width() != 0){ // check m_rectDest.Width() for zero if(lValue > 0){ NormalizedRectStruct.left = static_cast(lValue)/static_cast(m_rectDest.Width()); } else{ NormalizedRectStruct.left = static_cast(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Top(&lValue))){ if(m_rectDest.Height() != 0){ if(lValue > 0){ NormalizedRectStruct.top = static_cast(lValue)/static_cast(m_rectDest.Height()); } else{ NormalizedRectStruct.top = static_cast(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Width(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.right = (static_cast(lValue)/static_cast(m_rectDest.Width())) + static_cast(NormalizedRectStruct.left); } } } if(SUCCEEDED(pIMSVRect->get_Height(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.bottom = (static_cast(lValue)/static_cast(m_rectDest.Height())) + static_cast(NormalizedRectStruct.top); } } } if(NormalizedRectStruct.top < 0 || NormalizedRectStruct.left < 0 || NormalizedRectStruct.top > 1 || NormalizedRectStruct.left > 1 || NormalizedRectStruct.right < 0 || NormalizedRectStruct.bottom < 0 || NormalizedRectStruct.right > 1 || NormalizedRectStruct.bottom > 1){ return ImplReportError(__uuidof(T), IDS_E_MIXERSRC, __uuidof(IMSVidVideoRenderer), CO_E_ERRORINAPP); } m_rectPosition = NormalizedRectStruct; VMRAlphaBitmapStruct.rDest = m_rectPosition; } else{ if( m_rectPosition.left < 0 || m_rectPosition.top < 0 || m_rectPosition.right < 0 || m_rectPosition.bottom < 0 ){ VMRAlphaBitmapStruct.rDest.left = 0.f; VMRAlphaBitmapStruct.rDest.top = 0.f; VMRAlphaBitmapStruct.rDest.right = 1.f; VMRAlphaBitmapStruct.rDest.bottom = 1.f; } else{ VMRAlphaBitmapStruct.rDest = m_rectPosition; } } // If it is all valid then this is all good hr = put__MixerBitmap(&VMRAlphaBitmapStruct); if(!DeleteDC(memHDC)){ return ImplReportError(__uuidof(T), IDS_E_CANT_DELETE, __uuidof(IMSVidVideoRenderer), ERROR_DS_CANT_DELETE); } if(SUCCEEDED(hr)){ return S_OK; } else{ return hr; } } catch(...){ return E_UNEXPECTED; } } STDMETHOD(get_UsingOverlay)(/*[out, retval]*/ VARIANT_BOOL *pfUseOverlay) { return get_UseOverlay(pfUseOverlay); } STDMETHOD(put_UsingOverlay)(/*[in]*/ VARIANT_BOOL fUseOverlayVal) { return put_UseOverlay(fUseOverlayVal); } STDMETHOD(get_FramesPerSecond)(/*[out, retval]*/ long *pVal){ try{ if(pVal){ if(!m_pVMR){ throw(ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED)); } IQualProp *IQProp = NULL; HRESULT hr = m_pVMR->QueryInterface(IID_IQualProp, reinterpret_cast(&IQProp)); if(FAILED(hr)){ return hr; } if(!IQProp){ return E_NOINTERFACE; } hr = IQProp->get_AvgFrameRate(reinterpret_cast(pVal)); IQProp->Release(); return hr; } else{ return E_POINTER; } } catch(...){ return E_UNEXPECTED; } } STDMETHOD(put_DecimateInput)(/*[in]*/ VARIANT_BOOL bDeci){ try{ if(bDeci != VARIANT_TRUE && bDeci != VARIANT_FALSE){ return E_INVALIDARG; } m_Decimate = (bDeci == VARIANT_TRUE); if(!m_pVMR){ return S_OK; } DWORD curPrefs; DWORD deci; CComQIPtrPQIVMRMixer(m_pVMR); if(!PQIVMRMixer){ return E_UNEXPECTED; } HRESULT hr = PQIVMRMixer->GetMixingPrefs(&curPrefs); if(FAILED(hr)){ return hr; } deci = (m_Decimate?MixerPref_DecimateOutput:MixerPref_NoDecimation); if(!(curPrefs&deci)){ hr = CleanupVMR(); if(FAILED(hr)){ return hr; } } return NOERROR; } catch(...){ return E_UNEXPECTED; } } STDMETHOD(get_DecimateInput)(/*[out,retval]*/ VARIANT_BOOL *pDeci){ try{ if(!pDeci){ return E_POINTER; } if(!m_pVMR){ throw(ImplReportError(__uuidof(T), IDS_OBJ_NO_INIT, __uuidof(IMSVidVideoRenderer), CO_E_NOTINITIALIZED)); } DWORD curPrefs; CComQIPtrPQIVMRMixer(m_pVMR); if(!PQIVMRMixer){ return E_UNEXPECTED; } HRESULT hr = PQIVMRMixer->GetMixingPrefs(&curPrefs); if(FAILED(hr)){ return hr; } *pDeci = ((curPrefs&MixerPref_DecimateMask)==MixerPref_DecimateOutput)? VARIANT_TRUE : VARIANT_FALSE; return NOERROR; } catch(...){ return E_UNEXPECTED; } } STDMETHOD(ReComputeSourceRect)() { switch (m_SourceSize) { case sslFullSize: { CSize sz; CSize ar; if(m_pVMRWC){ HRESULT hr = m_pVMRWC->GetNativeVideoSize(&sz.cx, &sz.cy, &ar.cx, &ar.cy); if (FAILED(hr)) { return hr; } TRACELSM(TRACE_PAINT, (dbgDump << "CMSVidVideoRenderer::ReComputeSourceRect() sslFullSize vmr sz = " << sz), ""); } CRect r(0, 0, sz.cx, sz.cy); TRACELSM(TRACE_DETAIL, (dbgDump << "CMSVidVideoRenderer::ReComputeSource() full = " << r), ""); return put_Source(r); } break; case sslClipByOverScan: { CSize sz; CSize ar; if(m_pVMRWC){ HRESULT hr = m_pVMRWC->GetNativeVideoSize(&sz.cx, &sz.cy, &ar.cx, &ar.cy); if (FAILED(hr)) { return hr; } TRACELSM(TRACE_PAINT, (dbgDump << "CMSVidVideoRenderer::ReComputeSourceRect() sslClipByOverScan vmr sz = " << sz), ""); } CRect r(0, 0, sz.cx, sz.cy); CRect r2; float fpct = m_lOverScan / 10000.0; // overscan is in hundredths of pct, i.e 1.75% == 175 long wcrop = (long)(r.Width() * fpct + 0.5); long hcrop = (long)(r.Height() * fpct + 0.5); r2.left = 0 + wcrop; r2.top = 0 + hcrop; r2.right = r2.left + r.Width() - (2.0 * wcrop); r2.bottom = r2.top + r.Height() - (2.0 * hcrop); TRACELSM(TRACE_DETAIL, (dbgDump << "CMSVidVideoRenderer::ReComputeSource() over = " << m_lOverScan << " w " << wcrop << " h " << hcrop), ""); TRACELSM(TRACE_DETAIL, (dbgDump << "CMSVidVideoRenderer::ReComputeSource() full = " << r << " clip = " << r2), ""); return put_Source(r2); } break; case sslClipByClipRect: { TRACELSM(TRACE_DETAIL, (dbgDump << "CMSVidVideoRenderer::ReComputeSource() cliprect = " << m_ClipRect), ""); if(m_ClipRect.Width() == 0 && m_ClipRect.Height() == 0){ CSize sz; CSize ar; if(m_pVMRWC){ HRESULT hr = m_pVMRWC->GetNativeVideoSize(&sz.cx, &sz.cy, &ar.cx, &ar.cy); if (FAILED(hr)) { return hr; } TRACELSM(TRACE_PAINT, (dbgDump << "CMSVidVideoRenderer::ReComputeSourceRect() sslClipByClipRect vmr sz = " << sz), ""); } CRect r(0, 0, sz.cx, sz.cy); TRACELSM(TRACE_DETAIL, (dbgDump << "CMSVidVideoRenderer::ReComputeSource() full = " << r), ""); return put_Source(r); } else{ TRACELSM(TRACE_PAINT, (dbgDump << "CMSVidVideoRenderer::ReComputeSourceRect() sslClipByClipRect cliprect = " << m_ClipRect), ""); return put_Source(m_ClipRect); } } break; default:{ return E_INVALIDARG; } break; } return NOERROR; } }; #endif //__MSVidVIDEORENDERER_H_