1200 lines
46 KiB
C
1200 lines
46 KiB
C
|
//==========================================================================;
|
||
|
// 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_
|