|
|
//==========================================================================;
// MSVidVideoRenderer.h : Declaration of the CMSVidVideoRenderer
// copyright (c) Microsoft Corp. 1998-1999.
//==========================================================================;
#ifndef __MSVidVIDEORENDERERIMPL_H_
#define __MSVidVIDEORENDERERIMPL_H_
#pragma once
#include <algorithm>
#include <evcode.h>
#include <uuids.h>
#include <amvideo.h>
#include <strmif.h>
#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<IVMRSurfaceAllocator> PQVMRSAlloc;
//typedef CComQIPtr<IVMRAlphaBitmap> PQVMRAlphaBitm;
/////////////////////////////////////////////////////////////////////////////
// CMSVidVideoRenderer
template<class T, LPCGUID LibID, LPCGUID Category, class MostDerivedClass = IMSVidVideoRenderer> class DECLSPEC_NOVTABLE IMSVidVideoRendererImpl : public IMSVidOutputDeviceImpl<T, LibID, Category, MostDerivedClass>, public IMSVidVRGraphSegmentImpl<T> { 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<T> 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; CComQIPtr<IMSVidRect>PQIMSVRect; try{ PQIMSVRect = static_cast<IMSVidRect *>(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<IMSVidRect *>(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; CComQIPtr<IMSVidRect>PQIMSVRect; try{ PQIMSVRect = static_cast<IMSVidRect *>(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<IMSVidRect *>(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<IPersist> 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{ CComQIPtr<IVMRImageCompositor>IVMRICPtr; 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) { CComQIPtr<IMSVidRect>PQIMSVRect = static_cast<IMSVidRect *>(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<CScalingRect*>(static_cast<CVidRect*>(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 { CComQIPtr<IMSVidRect>PQIMSVRect = static_cast<IMSVidRect *>(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<IPicture> 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<BITMAPINFOHEADER*>(lpDIB), dwFlags, reinterpret_cast<void *>((LPBYTE)(lpDIB) + (int)(reinterpret_cast<BITMAPINFOHEADER*>(lpDIB)->biSize)), reinterpret_cast<BITMAPINFO*>(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<IPictureDisp**>(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<IVMRMixerBitmap> 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<HBITMAP>(GetCurrentObject(*pHDC, OBJ_BITMAP)); if(!hBitmap){ return hr; } hPalette = static_cast<HPALETTE>(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<void**> (&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<IPictureDisp> 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<IVMRMixerBitmap> 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<IVMRMixerBitmap> 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; CComQIPtr<IMSVidRect>PQIMSVRect; try{ CComQIPtr<IVMRMixerBitmap> PQIVMRMBitmap; PQIMSVRect = static_cast<IMSVidRect *>(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<long> (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<long>((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<long>(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<long>(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<IMSVidRect *>(new CVidRect(m_rectDest)); } else{ PQIMSVRect.Release(); PQIMSVRect = static_cast<IMSVidRect *>(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<float>(lValue)/static_cast<float>(m_rectDest.Width()); } else{ NormalizedRectStruct.left = static_cast<float>(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Top(&lValue))){ if(m_rectDest.Height() != 0){ if(lValue > 0){ NormalizedRectStruct.top = static_cast<float>(lValue)/static_cast<float>(m_rectDest.Height()); } else{ NormalizedRectStruct.top = static_cast<float>(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Width(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.right = (static_cast<float>(lValue)/static_cast<float>(m_rectDest.Width())) + static_cast<float>(NormalizedRectStruct.left); } } } if(SUCCEEDED(pIMSVRect->get_Height(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.bottom = (static_cast<float>(lValue)/static_cast<float>(m_rectDest.Height())) + static_cast<float>(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<IPictureDisp*>(-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<IVMRMixerBitmap> 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<int>(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<float>(wOpacity); } m_opacity = static_cast<float>(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<IPictureDisp*>(-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<IPictureDisp*>(-1)){ CComQIPtr<IPicture>PQIPicture(m_PQIPicture); if(!PQIPicture){ return S_OK; } } else if(pIPDisp){ // QI for a IPicture
CComQIPtr<IPicture>PQIPicture(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<OLE_HANDLE*>(&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<HBITMAP>(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<float>(wOpacity/100.f); VMRAlphaBitmapStruct.fAlpha = static_cast<float>(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<float>(lValue)/static_cast<float>(m_rectDest.Width()); } else{ NormalizedRectStruct.left = static_cast<float>(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Top(&lValue))){ if(m_rectDest.Height() != 0){ if(lValue > 0){ NormalizedRectStruct.top = static_cast<float>(lValue)/static_cast<float>(m_rectDest.Height()); } else{ NormalizedRectStruct.top = static_cast<float>(lValue); } } } if(SUCCEEDED(pIMSVRect->get_Width(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.right = (static_cast<float>(lValue)/static_cast<float>(m_rectDest.Width())) + static_cast<float>(NormalizedRectStruct.left); } } } if(SUCCEEDED(pIMSVRect->get_Height(&lValue))){ if(m_rectDest.Width() != 0){ if(lValue > 0){ NormalizedRectStruct.bottom = (static_cast<float>(lValue)/static_cast<float>(m_rectDest.Height())) + static_cast<float>(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<void**>(&IQProp)); if(FAILED(hr)){ return hr; } if(!IQProp){ return E_NOINTERFACE; } hr = IQProp->get_AvgFrameRate(reinterpret_cast<int*>(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; CComQIPtr<IVMRMixerControl>PQIVMRMixer(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; CComQIPtr<IVMRMixerControl>PQIVMRMixer(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_
|