You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4702 lines
117 KiB
4702 lines
117 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: VMRFilter.cpp
|
|
*
|
|
*
|
|
*
|
|
*
|
|
* Created: Tue 02/15/2000
|
|
* Author: Stephen Estrop [StEstrop]
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
\**************************************************************************/
|
|
#include <streams.h>
|
|
#include <windowsx.h>
|
|
#include <limits.h>
|
|
|
|
#ifdef FILTER_DLL
|
|
#include <initguid.h>
|
|
#endif
|
|
|
|
#include <d3d.h>
|
|
#include "VMRenderer.h"
|
|
#include "dvdmedia.h" // for MacroVision prop set, id
|
|
|
|
#if defined(CHECK_FOR_LEAKS)
|
|
#include "ifleak.h"
|
|
#endif
|
|
|
|
#ifndef DECLSPEC_SELECTANY
|
|
#if (_MSC_VER >= 1100)
|
|
#define DECLSPEC_SELECTANY __declspec(selectany)
|
|
#else
|
|
#define DECLSPEC_SELECTANY
|
|
#endif
|
|
#endif
|
|
|
|
EXTERN_C const GUID DECLSPEC_SELECTANY IID_IDirectDraw7 =
|
|
{
|
|
0x15e65ec0, 0x3b9c, 0x11d2,
|
|
{
|
|
0xb9, 0x2f, 0x00, 0x60, 0x97, 0x97, 0xea, 0x5b
|
|
}
|
|
};
|
|
|
|
#ifndef FILTER_DLL
|
|
#include <initguid.h>
|
|
#endif
|
|
|
|
// {565DCEF2-AFC5-11d2-8853-0000F80883E3}
|
|
DEFINE_GUID(CLSID_COMQualityProperties,
|
|
0x565dcef2, 0xafc5, 0x11d2, 0x88, 0x53, 0x0, 0x0, 0xf8, 0x8, 0x83, 0xe3);
|
|
|
|
// {A2CA6D57-BE10-45e0-9B81-7523681EC278}
|
|
DEFINE_GUID(CLSID_VMRFilterConfigProp,
|
|
0xa2ca6d57, 0xbe10, 0x45e0, 0x9b, 0x81, 0x75, 0x23, 0x68, 0x1e, 0xc2, 0x78);
|
|
|
|
// {DEE51F07-DDFF-4e34-8FA9-1BF49179DB8D}
|
|
DEFINE_GUID(CLSID_VMRDeinterlaceProp,
|
|
0xdee51f07, 0xddff, 0x4e34, 0x8f, 0xa9, 0x1b, 0xf4, 0x91, 0x79, 0xdb, 0x8d);
|
|
|
|
// Setup data
|
|
|
|
const AMOVIESETUP_MEDIATYPE
|
|
sudVMRPinTypes =
|
|
{
|
|
&MEDIATYPE_Video, // Major type
|
|
&MEDIASUBTYPE_NULL // And subtype
|
|
};
|
|
|
|
const AMOVIESETUP_PIN
|
|
sudVMRPin =
|
|
{
|
|
L"Input", // Name of the pin
|
|
TRUE, // Is pin rendered
|
|
FALSE, // Is an Output pin
|
|
FALSE, // Ok for no pins
|
|
FALSE, // Can we have many
|
|
&CLSID_NULL, // Connects to filter
|
|
NULL, // Name of pin connect
|
|
1, // Number of pin types
|
|
&sudVMRPinTypes // Details for pins
|
|
};
|
|
|
|
// The video renderer should be called "Video Renderer" for
|
|
// compatibility with applications using FindFilterByName (e.g., Shock
|
|
// to the System 2)
|
|
|
|
const AMOVIESETUP_FILTER
|
|
sudVMRFilter =
|
|
{
|
|
&CLSID_VideoRendererDefault, // Filter CLSID
|
|
L"Video Renderer", // Filter name
|
|
MERIT_PREFERRED + 1,
|
|
1, // Number pins
|
|
&sudVMRPin // Pin details
|
|
};
|
|
|
|
#ifdef FILTER_DLL
|
|
const AMOVIESETUP_FILTER
|
|
sudVMRFilter2 =
|
|
{
|
|
&CLSID_VideoMixingRenderer,
|
|
L"Video Mixing Renderer", // Filter name
|
|
MERIT_PREFERRED + 2,
|
|
1, // Number pins
|
|
&sudVMRPin // Pin details
|
|
};
|
|
|
|
STDAPI DllRegisterServer()
|
|
{
|
|
AMTRACE((TEXT("DllRegisterServer")));
|
|
return AMovieDllRegisterServer2( TRUE );
|
|
}
|
|
|
|
STDAPI DllUnregisterServer()
|
|
{
|
|
AMTRACE((TEXT("DllUnregisterServer")));
|
|
return AMovieDllRegisterServer2( FALSE );
|
|
}
|
|
|
|
CFactoryTemplate g_Templates[] = {
|
|
{
|
|
L"",
|
|
&CLSID_VideoMixingRenderer,
|
|
CVMRFilter::CreateInstance,
|
|
CVMRFilter::InitClass,
|
|
&sudVMRFilter2
|
|
},
|
|
{
|
|
L"",
|
|
&CLSID_VideoRendererDefault,
|
|
CVMRFilter::CreateInstance2,
|
|
NULL,
|
|
&sudVMRFilter
|
|
}
|
|
};
|
|
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
|
|
|
|
#endif
|
|
|
|
// This goes in the factory template table to create new filter instances
|
|
|
|
CUnknown* CVMRFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CreateInstance")));
|
|
|
|
//
|
|
// The VMR is being created explictly via a call to CoCreateInstance
|
|
// with the VMR's class ID. We don't create the Allocator-Presenter object
|
|
// during the VMR's constructor when in this mode. This is because the
|
|
// application may have already entered DDraw Exclusive mode. The
|
|
// default Allocator-Presenter won't work in this DDraw mode which would
|
|
// cause the VMR's constructor to fail.
|
|
//
|
|
CUnknown* pk = new CVMRFilter(NAME("Video Mixing Renderer"),
|
|
pUnk, phr, FALSE);
|
|
|
|
return pk;
|
|
}
|
|
|
|
// create the VMR or the VR if VMR fails due to 8bpp screen mode. what
|
|
// about ddraw.dll failing to load?
|
|
//
|
|
CUnknown* CVMRFilter::CreateInstance2(LPUNKNOWN pUnk, HRESULT *phr)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CreateInstance2")));
|
|
|
|
//
|
|
// Create the VMR as the default renderer, in this mode we
|
|
// create the Allocator-Presenter object in the VMR's constructor.
|
|
// Doing this provides early feedback as to whether the VMR can be used
|
|
// in this graphics mode.
|
|
//
|
|
CUnknown* pk = new CVMRFilter(NAME("Video Mixing Renderer"),
|
|
pUnk, phr, TRUE);
|
|
|
|
if(*phr == VFW_E_DDRAW_CAPS_NOT_SUITABLE) {
|
|
|
|
#ifndef FILTER_DLL
|
|
delete pk;
|
|
*phr = S_OK;
|
|
CUnknown* CRenderer_CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
|
|
return CRenderer_CreateInstance(pUnk, phr);
|
|
#else
|
|
DbgBreak("8bpp unsupported with separate dlls");
|
|
#endif
|
|
}
|
|
|
|
return pk;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* InitClass
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 12/14/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
#if defined(CHECK_FOR_LEAKS)
|
|
// the one and only g_IFLeak object.
|
|
CInterfaceLeak g_IFLeak;
|
|
|
|
void
|
|
CVMRFilter::InitClass(
|
|
BOOL bLoading,
|
|
const CLSID *clsid
|
|
)
|
|
{
|
|
if (bLoading) {
|
|
DbgLog(( LOG_TRACE, 0, TEXT("VMR Thunks: Loaded") ));
|
|
g_IFLeak.Init();
|
|
}
|
|
else {
|
|
DbgLog(( LOG_TRACE, 0, TEXT("VMR Thunks: Unloaded") ));
|
|
g_IFLeak.Term();
|
|
}
|
|
}
|
|
#else
|
|
void
|
|
CVMRFilter::InitClass(
|
|
BOOL bLoading,
|
|
const CLSID *clsid
|
|
)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* GetMediaPositionInterface
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 03/28/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::GetMediaPositionInterface(
|
|
REFIID riid,
|
|
void ** ppv
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetMediaPositionInterface")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (m_pPosition) {
|
|
return m_pPosition->NonDelegatingQueryInterface(riid, ppv);
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
m_pPosition = new CRendererPosPassThru(NAME("Renderer CPosPassThru"),
|
|
CBaseFilter::GetOwner(),
|
|
&hr,
|
|
GetPin(0));
|
|
if (m_pPosition == NULL) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("CreatePosPassThru failed - no memory") ));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
delete m_pPosition;
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("CreatePosPassThru failed, hr = 0x%x"), hr));
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
return GetMediaPositionInterface(riid,ppv);
|
|
}
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* ModeChangeAllowed
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 04/07/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
CVMRFilter::ModeChangeAllowed()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::ModeChangeAllowed")));
|
|
|
|
BOOL fRet = ((m_VMRMode & VMRMode_Windowed) &&
|
|
0 == NumInputPinsConnected() && m_bModeChangeAllowed);
|
|
|
|
DbgLog((LOG_TRACE, 2, TEXT("Allowed = %d"), fRet));
|
|
|
|
return fRet;
|
|
}
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* SetVMRMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 04/07/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
CVMRFilter::SetVMRMode(
|
|
DWORD mode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetVMRMode")));
|
|
|
|
DbgLog((LOG_TRACE, 2, TEXT("Mode = %d"), mode));
|
|
|
|
if (m_bModeChangeAllowed) {
|
|
|
|
m_bModeChangeAllowed = FALSE;
|
|
m_VMRMode = mode;
|
|
|
|
//
|
|
// If we are going renderless get rid of the default
|
|
// allocator-presenter.
|
|
//
|
|
if (mode == VMRMode_Renderless ) {
|
|
m_pIVMRSurfaceAllocatorNotify.AdviseSurfaceAllocator(0, NULL);
|
|
}
|
|
|
|
ASSERT(m_pVideoWindow);
|
|
|
|
if (m_VMRMode != VMRMode_Windowed && m_pVideoWindow) {
|
|
m_pVideoWindow->InactivateWindow();
|
|
m_pVideoWindow->DoneWithWindow();
|
|
delete m_pVideoWindow;
|
|
m_pVideoWindow = NULL;
|
|
}
|
|
}
|
|
else {
|
|
|
|
ASSERT(m_VMRMode == mode);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NonDelegatingQueryInterface
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::NonDelegatingQueryInterface(
|
|
REFIID riid,
|
|
void ** ppv
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::NonDelegatingQueryInterface")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
//
|
|
// The following 3 interfaces control the rendering mode that
|
|
// the video renderer adopts
|
|
//
|
|
HRESULT hr = E_NOINTERFACE;
|
|
*ppv = NULL;
|
|
|
|
if (riid == IID_IVMRSurfaceAllocatorNotify) {
|
|
|
|
if (m_VMRMode == VMRMode_Renderless ) {
|
|
hr = GetInterface(&m_pIVMRSurfaceAllocatorNotify, ppv);
|
|
}
|
|
}
|
|
else if (riid == IID_IBasicVideo || riid == IID_IBasicVideo2 ||
|
|
riid == IID_IVideoWindow) {
|
|
|
|
if (m_VMRMode == VMRMode_Windowed) {
|
|
hr = m_pVideoWindow->NonDelegatingQueryInterface(riid,ppv);
|
|
}
|
|
}
|
|
else if (riid == IID_IVMRWindowlessControl) {
|
|
|
|
if (m_VMRMode == VMRMode_Windowless ) {
|
|
hr = GetInterface((IVMRWindowlessControl *) this, ppv);
|
|
}
|
|
else if (m_VMRMode == VMRMode_Renderless ) {
|
|
if (ValidateIVRWindowlessControlState() == S_OK) {
|
|
hr = GetInterface((IVMRWindowlessControl *) this, ppv);
|
|
}
|
|
}
|
|
}
|
|
else if (riid == IID_IVMRMixerControl) {
|
|
|
|
if (!m_VMRModePassThru && m_lpMixControl) {
|
|
hr = GetInterface((IVMRMixerControl *) this, ppv);
|
|
}
|
|
}
|
|
|
|
else if (riid == IID_IVMRDeinterlaceControl) {
|
|
|
|
hr = GetInterface((IVMRDeinterlaceControl *)(this), ppv);
|
|
}
|
|
|
|
//
|
|
// Need to sort out how to seek when we have multiple input streams
|
|
// feeding us. Seeking should only be allowed if all the input streams
|
|
// are "seekable"
|
|
//
|
|
|
|
else if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {
|
|
|
|
return GetMediaPositionInterface(riid,ppv);
|
|
}
|
|
|
|
else if (riid == IID_IKsPropertySet) {
|
|
|
|
hr = GetInterface((IKsPropertySet *)this, ppv);
|
|
}
|
|
|
|
else if (riid == IID_IAMFilterMiscFlags) {
|
|
|
|
hr = GetInterface((IAMFilterMiscFlags *)this, ppv);
|
|
}
|
|
|
|
else if (riid == IID_IQualProp) {
|
|
|
|
hr = GetInterface(static_cast<IQualProp *>(this), ppv);
|
|
}
|
|
|
|
else if (riid == IID_IQualityControl) {
|
|
|
|
hr = GetInterface(static_cast<IQualityControl *>(this), ppv);
|
|
}
|
|
|
|
else if (riid == IID_IVMRFilterConfig) {
|
|
hr = GetInterface(static_cast<IVMRFilterConfig *>(this), ppv);
|
|
}
|
|
|
|
else if (riid == IID_IVMRFilterConfigInternal) {
|
|
hr = GetInterface(static_cast<IVMRFilterConfigInternal *>(this), ppv);
|
|
}
|
|
|
|
else if (riid == IID_IVMRMonitorConfig) {
|
|
|
|
if ((m_VMRMode & VMRMode_Windowless) ||
|
|
(m_VMRMode & VMRMode_Windowed)) {
|
|
|
|
if (ValidateIVRWindowlessControlState() == S_OK) {
|
|
hr = GetInterface(static_cast<IVMRMonitorConfig *>(this), ppv);
|
|
}
|
|
}
|
|
}
|
|
|
|
else if (riid == IID_IVMRMixerBitmap) {
|
|
hr = GetInterface(static_cast<IVMRMixerBitmap *>(this), ppv);
|
|
}
|
|
|
|
else if (riid == IID_ISpecifyPropertyPages) {
|
|
hr = GetInterface(static_cast<ISpecifyPropertyPages *>(this), ppv);
|
|
}
|
|
|
|
else if (riid == IID_IPersistStream) {
|
|
hr = GetInterface(static_cast<IPersistStream *>(this), ppv);
|
|
}
|
|
|
|
else {
|
|
hr = CBaseFilter::NonDelegatingQueryInterface(riid,ppv);
|
|
|
|
}
|
|
|
|
#if defined(CHECK_FOR_LEAKS)
|
|
if (hr == S_OK) {
|
|
_pIFLeak->AddThunk((IUnknown **)ppv, "VMR Filter Object", riid);
|
|
}
|
|
#endif
|
|
|
|
return hr;
|
|
}
|
|
|
|
struct VMRHardWareCaps {
|
|
HRESULT hr2D;
|
|
HRESULT hr3D;
|
|
DWORD dwBitDepth;
|
|
};
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* D3DEnumDevicesCallback7
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 01/16/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CALLBACK
|
|
VMRD3DEnumDevicesCallback7(
|
|
LPSTR lpDeviceDescription,
|
|
LPSTR lpDeviceName,
|
|
LPD3DDEVICEDESC7 lpD3DDeviceDesc,
|
|
LPVOID lpContext
|
|
)
|
|
{
|
|
AMTRACE((TEXT("VMRD3DEnumDevicesCallback7")));
|
|
VMRHardWareCaps* pHW = (VMRHardWareCaps*)lpContext;
|
|
if (lpD3DDeviceDesc->deviceGUID == IID_IDirect3DHALDevice) {
|
|
|
|
switch (pHW->dwBitDepth) {
|
|
case 16:
|
|
if (lpD3DDeviceDesc->dwDeviceRenderBitDepth & DDBD_16) {
|
|
pHW->hr3D = DD_OK;
|
|
}
|
|
break;
|
|
|
|
case 24:
|
|
if (lpD3DDeviceDesc->dwDeviceRenderBitDepth & DDBD_24) {
|
|
pHW->hr3D = DD_OK;
|
|
}
|
|
break;
|
|
|
|
case 32:
|
|
if (lpD3DDeviceDesc->dwDeviceRenderBitDepth & DDBD_32) {
|
|
pHW->hr3D = DD_OK;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (HRESULT)D3DENUMRET_OK;
|
|
}
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* VMRDDEnumCallbackExA
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 01/12/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
BOOL WINAPI
|
|
VMRDDEnumCallbackExA(
|
|
GUID *pGUID,
|
|
LPSTR lpDriverDesc,
|
|
LPSTR lpDriverName,
|
|
LPVOID lpContext,
|
|
HMONITOR hm
|
|
)
|
|
{
|
|
AMTRACE((TEXT("VMRDDEnumCallbackExA")));
|
|
LPDIRECTDRAW7 pDD = NULL;
|
|
LPDIRECT3D7 pD3D = NULL;
|
|
|
|
VMRHardWareCaps* pHW = (VMRHardWareCaps*)lpContext;
|
|
|
|
__try {
|
|
HRESULT hRet;
|
|
CHECK_HR( hRet = DirectDrawCreateEx(pGUID, (LPVOID *)&pDD,
|
|
IID_IDirectDraw7, NULL) );
|
|
DDCAPS ddHWCaps;
|
|
INITDDSTRUCT(ddHWCaps);
|
|
CHECK_HR(hRet = pDD->GetCaps(&ddHWCaps, NULL));
|
|
|
|
DDSURFACEDESC2 ddsd = {sizeof(DDSURFACEDESC2)};
|
|
CHECK_HR(hRet = pDD->GetDisplayMode(&ddsd));
|
|
|
|
//
|
|
// h/w rules
|
|
// 2D is OK provided the bit depth is greater than
|
|
// RGB8, even if we don't have any display h/w acceleration.
|
|
// 3D requires > RGB8 and hardware acceleration.
|
|
//
|
|
|
|
if (ddsd.ddpfPixelFormat.dwRGBBitCount > 8) {
|
|
|
|
pHW->hr2D = DD_OK;
|
|
|
|
if (!(ddHWCaps.dwCaps & DDCAPS_NOHARDWARE)) {
|
|
|
|
pHW->dwBitDepth = ddsd.ddpfPixelFormat.dwRGBBitCount;
|
|
CHECK_HR(hRet = pDD->QueryInterface(IID_IDirect3D7, (LPVOID *)&pD3D));
|
|
pD3D->EnumDevices(VMRD3DEnumDevicesCallback7, lpContext);
|
|
}
|
|
}
|
|
}
|
|
__finally {
|
|
RELEASE(pD3D);
|
|
RELEASE(pDD);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* BasicHWCheck
|
|
*
|
|
* In order for the VMR to operate we need some DDraw h/w and a graphics
|
|
* display mode greater than 8bits per pixel.
|
|
*
|
|
* History:
|
|
* Fri 01/12/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
VMRHardWareCaps
|
|
BasicHWCheck()
|
|
{
|
|
AMTRACE((TEXT("BasicHWCheck")));
|
|
VMRHardWareCaps hrDDraw = {VFW_E_DDRAW_CAPS_NOT_SUITABLE,
|
|
VFW_E_DDRAW_CAPS_NOT_SUITABLE};
|
|
|
|
HRESULT hr = DirectDrawEnumerateExA(VMRDDEnumCallbackExA, (LPVOID)&hrDDraw,
|
|
DDENUM_ATTACHEDSECONDARYDEVICES);
|
|
if (FAILED(hr)) {
|
|
hrDDraw.hr2D = VFW_E_DDRAW_CAPS_NOT_SUITABLE;
|
|
hrDDraw.hr3D = VFW_E_DDRAW_CAPS_NOT_SUITABLE;
|
|
}
|
|
|
|
return hrDDraw;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::CVMRFilter
|
|
*
|
|
*
|
|
* Turn off "warning C4355: 'this' : used in base member initializer list"
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
#pragma warning(disable:4355)
|
|
CVMRFilter::CVMRFilter(
|
|
TCHAR *pName,
|
|
LPUNKNOWN pUnk,
|
|
HRESULT *phr,
|
|
BOOL fDefault
|
|
) :
|
|
CBaseFilter(pName, pUnk, &m_InterfaceLock, CLSID_VideoMixingRenderer),
|
|
CPersistStream(pUnk, phr),
|
|
m_pIVMRSurfaceAllocatorNotify(this),
|
|
m_pIVMRImagePresenter(this),
|
|
m_pIImageSyncNotifyEvent(this),
|
|
m_VMRMode(VMRMode_Windowed),
|
|
m_VMRModePassThru(true),
|
|
m_fInputPinCountSet(false),
|
|
m_dwNumPins(0),
|
|
m_bModeChangeAllowed(TRUE),
|
|
m_lpRLNotify(NULL),
|
|
m_lpWLControl(NULL),
|
|
m_lpIS(NULL),
|
|
m_lpISControl(NULL),
|
|
m_lpMixControl(NULL),
|
|
m_lpMixBitmap(NULL),
|
|
m_lpMixStream(NULL),
|
|
m_lpPresenter(NULL),
|
|
m_pPresenterConfig(NULL),
|
|
m_pPresenterMonitorConfig(NULL),
|
|
m_lpISQualProp(NULL),
|
|
m_lpDirectDraw(NULL),
|
|
m_hMonitor(NULL),
|
|
m_pPosition(NULL),
|
|
m_pVideoWindow(NULL),
|
|
m_pDeinterlace(NULL),
|
|
m_TexCaps(0),
|
|
m_dwDisplayChangeMask(0),
|
|
m_dwEndOfStreamMask(0),
|
|
m_ARMode(VMR_ARMODE_NONE), // please update CompleteConnect if you change this
|
|
m_bARModeDefaultSet(FALSE),
|
|
m_hr3D(DD_OK),
|
|
m_dwRenderPrefs(0),
|
|
m_dwDeinterlacePrefs(DeinterlacePref_NextBest),
|
|
m_VMRCreateAsDefaultRenderer(fDefault)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CVMRFilter")));
|
|
HRESULT hr = S_OK;
|
|
|
|
ZeroMemory(m_pInputPins, sizeof(m_pInputPins));
|
|
ZeroMemory(&m_ddHWCaps, sizeof(m_ddHWCaps));
|
|
ZeroMemory(&m_ddpfMonitor, sizeof(m_ddpfMonitor));
|
|
|
|
#ifdef DEBUG
|
|
if (GetProfileIntA("VMR", "LetterBox", 0) == 1) {
|
|
m_ARMode = VMR_ARMODE_LETTER_BOX;
|
|
}
|
|
|
|
if (GetProfileIntA("VMR", "APGMemFirst", 0) == 1) {
|
|
m_dwRenderPrefs = RenderPrefs_PreferAGPMemWhenMixing;
|
|
}
|
|
#endif
|
|
|
|
__try
|
|
{
|
|
VMRHardWareCaps hrDDraw = BasicHWCheck();
|
|
m_hr3D = hrDDraw.hr3D;
|
|
if (FAILED(hrDDraw.hr2D)) {
|
|
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("The machine does not have the necessary h/w to run the VMR!!")));
|
|
*phr = hrDDraw.hr2D;
|
|
__leave;
|
|
}
|
|
|
|
hr = ImageSyncInit();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Image Synchronization initialization FAILED!!")));
|
|
*phr = hr;
|
|
__leave;
|
|
}
|
|
|
|
hr = CreateInputPin();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Pin initialization FAILED!!")));
|
|
*phr = hr;
|
|
__leave;
|
|
}
|
|
|
|
m_pVideoWindow = new CVMRVideoWindow(this, &m_InterfaceLock, GetOwner(), phr);
|
|
if (FAILED(*phr) || m_pVideoWindow == NULL) {
|
|
|
|
DbgLog((LOG_ERROR, 1, TEXT("Can't create Video Window!!")));
|
|
if (m_pVideoWindow == NULL) {
|
|
*phr = E_OUTOFMEMORY;
|
|
}
|
|
__leave;
|
|
}
|
|
hr = m_pVideoWindow->PrepareWindow();
|
|
if (FAILED(hr)) {
|
|
*phr = hr;
|
|
__leave;
|
|
}
|
|
|
|
if (m_VMRCreateAsDefaultRenderer) {
|
|
hr = ValidateIVRWindowlessControlState();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR,1,TEXT("Unloading VMR because default AP creation failed")));
|
|
*phr = VFW_E_DDRAW_CAPS_NOT_SUITABLE;
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (GetProfileIntA("VMR", "FrameRate", 0) == 1) {
|
|
m_pVideoWindow->StartFrameRateTimer();
|
|
}
|
|
#endif
|
|
|
|
}
|
|
__finally
|
|
{
|
|
if ( FAILED(hr) )
|
|
{
|
|
VMRCleanUp();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* VMRCleanUp
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 04/05/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
CVMRFilter::VMRCleanUp()
|
|
{
|
|
// Release passthru
|
|
delete m_pPosition;
|
|
|
|
// Release the Window Manager (if we have one)
|
|
if (m_pVideoWindow) {
|
|
m_pVideoWindow->InactivateWindow();
|
|
m_pVideoWindow->DoneWithWindow();
|
|
delete m_pVideoWindow;
|
|
m_pVideoWindow = NULL;
|
|
}
|
|
|
|
RELEASE(m_lpMixBitmap);
|
|
RELEASE(m_lpMixControl);
|
|
RELEASE(m_lpMixStream);
|
|
RELEASE(m_lpRLNotify);
|
|
RELEASE(m_lpPresenter);
|
|
RELEASE(m_pPresenterConfig);
|
|
RELEASE(m_pPresenterMonitorConfig);
|
|
RELEASE(m_lpWLControl);
|
|
RELEASE(m_lpIS);
|
|
|
|
if (m_lpISControl) {
|
|
m_lpISControl->SetEventNotify(NULL);
|
|
m_lpISControl->SetImagePresenter(NULL, 0);
|
|
m_lpISControl->SetReferenceClock(NULL);
|
|
RELEASE(m_lpISControl);
|
|
}
|
|
|
|
RELEASE(m_lpISQualProp);
|
|
|
|
DWORD i;
|
|
for (i = 0; i < m_dwNumPins; i++) {
|
|
delete m_pInputPins[i];
|
|
m_pInputPins[i] = NULL;
|
|
}
|
|
|
|
for (i = m_dwNumPins; i < MAX_MIXER_PINS; i++) {
|
|
ASSERT(m_pInputPins[i] == NULL);
|
|
}
|
|
|
|
SetDDrawDeviceWorker(NULL, NULL);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::~CVMRFilter
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
CVMRFilter::~CVMRFilter()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::~CVMRFilter")));
|
|
VMRCleanUp();
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* MixerInit
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 03/09/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::MixerInit(
|
|
DWORD dwNumStreams
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::MixerInit")));
|
|
|
|
// A reference leak will occur if this function is called and m_lpMixControl, m_lpMixBitmap
|
|
// or m_lpMixStream is not NULL.
|
|
ASSERT((NULL == m_lpMixControl) && (NULL == m_lpMixBitmap) && (NULL == m_lpMixStream));
|
|
|
|
HRESULT hr;
|
|
|
|
__try {
|
|
|
|
CHECK_HR(hr = CoCreateInstance(CLSID_VideoMixer,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IVMRMixerControlInternal,
|
|
(LPVOID*)&m_lpMixControl));
|
|
|
|
CHECK_HR(hr = m_lpMixControl->QueryInterface(IID_IVMRMixerBitmap,
|
|
(LPVOID *)&m_lpMixBitmap));
|
|
|
|
CHECK_HR(hr = m_lpMixControl->SetNumberOfStreams(dwNumStreams));
|
|
CHECK_HR(hr = m_lpMixControl->SetBackEndImageSync(m_lpIS));
|
|
|
|
if (m_lpRLNotify) {
|
|
CHECK_HR(hr = m_lpMixControl->SetBackEndAllocator(m_lpRLNotify, m_dwUserID));
|
|
}
|
|
|
|
CHECK_HR(hr = m_lpMixControl->QueryInterface(IID_IVMRMixerStream,
|
|
(LPVOID*)&m_lpMixStream));
|
|
}
|
|
__finally {
|
|
|
|
if (FAILED(hr)) {
|
|
RELEASE(m_lpMixControl);
|
|
RELEASE(m_lpMixBitmap);
|
|
RELEASE(m_lpMixStream);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* ImageSyncInit()
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 03/09/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::ImageSyncInit()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::ImageSyncInit")));
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CoCreateInstance(CLSID_ImageSynchronization, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IImageSync,
|
|
(LPVOID*)&m_lpIS);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Can't create a Core Video Renderer object!!")));
|
|
return hr;
|
|
}
|
|
|
|
|
|
hr = m_lpIS->QueryInterface(IID_IImageSyncControl, (LPVOID*)&m_lpISControl);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Can't get an IID_IImageSyncControl!!")));
|
|
return hr;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpISControl->SetImagePresenter(&m_pIVMRImagePresenter, m_dwUserID);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpISControl->SetEventNotify(&m_pIImageSyncNotifyEvent);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpIS->QueryInterface(IID_IQualProp, (LPVOID*)&m_lpISQualProp);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Can't get an IID_IQualProp from the Image Sync!!")));
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* CreateInputPin
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 03/09/2000 - StEstrop - Created
|
|
* Wed 08/22/2001 - BEllett - Changed function name.
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::CreateInputPin()
|
|
{
|
|
// Make sure that we can create another input pin.
|
|
ASSERT(m_dwNumPins < MAX_MIXER_PINS);
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwInputPinNum = m_dwNumPins;
|
|
|
|
WCHAR wszPinName[32];
|
|
wsprintfW(wszPinName, L"VMR Input%d", dwInputPinNum);
|
|
m_pInputPins[dwInputPinNum] = new CVMRInputPin(dwInputPinNum, this, &m_InterfaceLock,
|
|
&hr, wszPinName);
|
|
if (m_pInputPins[dwInputPinNum] == NULL) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Ran out of memory creating input pin!!")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Unknown error occurred creating input pin!!")));
|
|
delete m_pInputPins[dwInputPinNum];
|
|
m_pInputPins[dwInputPinNum] = NULL;
|
|
return hr;
|
|
}
|
|
|
|
m_dwNumPins++;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* CreateExtraInputPins
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 03/09/2000 - StEstrop - Created
|
|
* Wed 08/22/2001 - BEllett - Changed function name, removed redundant code,
|
|
* and fixed a minor memory leak.
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::CreateExtraInputPins(
|
|
DWORD dwNumPins
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
for (DWORD i = 0; i < dwNumPins; i++) {
|
|
hr = CreateInputPin();
|
|
if (FAILED(hr)) {
|
|
DestroyExtraInputPins();
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* DestroyExtraInputPins
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 08/22/2001 - BEllett - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
CVMRFilter::DestroyExtraInputPins()
|
|
{
|
|
for (DWORD i = 1; i < m_dwNumPins; i++) {
|
|
delete m_pInputPins[i];
|
|
m_pInputPins[i] = NULL;
|
|
}
|
|
|
|
m_dwNumPins = 1;
|
|
|
|
#ifdef DEBUG
|
|
for (i = m_dwNumPins; i < MAX_MIXER_PINS; i++) {
|
|
ASSERT(m_pInputPins[i] == NULL);
|
|
}
|
|
#endif DEBUG
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetPin
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
CBasePin*
|
|
CVMRFilter::GetPin(
|
|
int n
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetPin")));
|
|
ASSERT(n < (int)m_dwNumPins);
|
|
return m_pInputPins[n];
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetPinCount()
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
int
|
|
CVMRFilter::GetPinCount()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetPinCount")));
|
|
return m_dwNumPins;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CBaseMediaFilter
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetSyncSource(
|
|
IReferenceClock *pClock
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetSyncSource")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = CBaseFilter::SetSyncSource(pClock);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpISControl->SetReferenceClock(pClock);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::Stop()
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::Stop()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Stop")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = CBaseFilter::Stop();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpISControl->EndImageSequence();
|
|
}
|
|
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
m_lpMixControl->WaitForMixerIdle(INFINITE);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::Pause()
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::Pause()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Pause")));
|
|
|
|
HRESULT hr = S_OK;
|
|
{
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
int PinsConnected = NumInputPinsConnected();
|
|
|
|
if (PinsConnected == 0) {
|
|
|
|
m_State = State_Paused;
|
|
return S_OK;
|
|
}
|
|
|
|
hr = CBaseFilter::Pause();
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = m_lpISControl->CueImageSequence();
|
|
}
|
|
}
|
|
|
|
//
|
|
// DON'T hold the lock while doing these window operations
|
|
// If we do then we can hang if the window thread ever grabs it
|
|
// because some of these operation do SendMessage to our window
|
|
// (it's that simple - think about it)
|
|
// This should be safe because all this stuff really only references
|
|
// m_hwnd which doesn't change for the lifetime of this object
|
|
//
|
|
|
|
AutoShowWindow();
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::Run
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::Run(
|
|
REFERENCE_TIME StartTime
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Run")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (m_State == State_Running) {
|
|
NOTE("State set");
|
|
return S_OK;
|
|
}
|
|
|
|
// Send EC_COMPLETE if we're not connected
|
|
|
|
if (NumInputPinsConnected() == 0) {
|
|
DbgLog((LOG_TRACE, 2, TEXT("No pin connection")));
|
|
m_State = State_Running;
|
|
NotifyEvent(EC_COMPLETE, S_OK, 0);
|
|
return S_OK;
|
|
}
|
|
|
|
DbgLog((LOG_TRACE, 2, TEXT("Changing state to running")));
|
|
HRESULT hr = CBaseFilter::Run(StartTime);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpISControl->BeginImageSequence(&StartTime);
|
|
}
|
|
|
|
AutoShowWindow();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetState
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetState(
|
|
DWORD dwMSecs,
|
|
FILTER_STATE *State
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetState")));
|
|
|
|
if (NumInputPinsConnected() == 0) {
|
|
*State = m_State;
|
|
return S_OK;
|
|
}
|
|
|
|
DWORD dwState;
|
|
HRESULT hr = m_lpISControl->GetImageSequenceState(dwMSecs, &dwState);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
*State = (FILTER_STATE)dwState;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* AutoShowWindow
|
|
*
|
|
* The auto show flag is used to have the window shown automatically when we
|
|
* change state. We do this only when moving to paused or running, when there
|
|
* is no outstanding EC_USERABORT set and when the window is not already up
|
|
* This can be changed through the IVideoWindow interface AutoShow property.
|
|
* If the window is not currently visible then we are showing it because of
|
|
* a state change to paused or running, in which case there is no point in
|
|
* the video window sending an EC_REPAINT as we're getting an image anyway
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 04/21/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
CVMRFilter::AutoShowWindow()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::AutoShowWindow")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (m_pVideoWindow) {
|
|
|
|
ASSERT(m_VMRMode == VMRMode_Windowed);
|
|
if( m_VMRMode & VMRMode_Windowed ) {
|
|
HWND hwnd = m_pVideoWindow->GetWindowHWND();
|
|
|
|
if (m_pVideoWindow->IsAutoShowEnabled() == TRUE) {
|
|
BOOL bAbort;
|
|
m_lpISControl->GetAbortSignal(&bAbort);
|
|
if (bAbort == FALSE) {
|
|
|
|
if (IsWindowVisible(hwnd) == FALSE) {
|
|
|
|
NOTE("ExecutingAutoShowWindow");
|
|
// SetRepaintStatus(FALSE);
|
|
m_pVideoWindow->PerformanceAlignWindow();
|
|
m_pVideoWindow->DoShowWindow(SW_SHOWNORMAL);
|
|
m_pVideoWindow->DoSetWindowForeground(TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::Receive
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::Receive(
|
|
DWORD dwPinID,
|
|
IMediaSample *pMediaSample
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Receive")));
|
|
|
|
if (dwPinID == 0) {
|
|
|
|
//
|
|
// Store the media times from this sample
|
|
//
|
|
|
|
if (m_pPosition) {
|
|
m_pPosition->RegisterMediaTime(pMediaSample);
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::Active
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::Active(
|
|
DWORD dwPinID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Active")));
|
|
|
|
const DWORD dwPinBit = (1 << dwPinID);
|
|
m_dwEndOfStreamMask |= dwPinBit;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::Inactive
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::Inactive(
|
|
DWORD dwPinID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Inactive")));
|
|
|
|
if (dwPinID == 0) {
|
|
if (m_pPosition) {
|
|
m_pPosition->ResetMediaTime();
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::BeginFlush
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::BeginFlush(
|
|
DWORD dwPinID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::BeginFlush")));
|
|
|
|
HRESULT hr = m_lpISControl->BeginFlush();
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::EndFlush
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::EndFlush(
|
|
DWORD dwPinID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::EndFlush")));
|
|
|
|
if (dwPinID == 0) {
|
|
if (m_pPosition) {
|
|
m_pPosition->ResetMediaTime();
|
|
}
|
|
}
|
|
|
|
HRESULT hr = m_lpISControl->EndFlush();
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::EndOfStream
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::EndOfStream(
|
|
DWORD dwPinID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::EndofStream")));
|
|
return m_lpISControl->EndOfStream();
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
** deal with connections
|
|
** -------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::BreakConnect
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::BreakConnect(
|
|
DWORD dwPinID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::BreakConnect")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = S_OK;
|
|
if (NumInputPinsConnected() == 1) {
|
|
|
|
// Now deactivate Macrovision, if it was activated
|
|
if (m_MacroVision.GetCPHMonitor())
|
|
{
|
|
// clear MV from display
|
|
m_MacroVision.SetMacroVision(m_hMonitor, 0);
|
|
|
|
// reset CP key
|
|
m_MacroVision.StopMacroVision();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::CheckMediaType
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::CheckMediaType(
|
|
const CMediaType* pmt
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CheckMediaType")));
|
|
|
|
if (pmt->majortype != MEDIATYPE_Video) {
|
|
|
|
DbgLog((LOG_ERROR, 1, TEXT("CheckMediaType failed: Major Type not Video")));
|
|
return VFW_E_TYPE_NOT_ACCEPTED;
|
|
}
|
|
|
|
if (pmt->subtype == MEDIASUBTYPE_RGB8) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("CheckMediaType failed: Minor Type is RGB8")));
|
|
return VFW_E_TYPE_NOT_ACCEPTED;
|
|
}
|
|
|
|
if (*pmt->FormatType() != FORMAT_VideoInfo &&
|
|
*pmt->FormatType() != FORMAT_VideoInfo2) {
|
|
|
|
DbgLog((LOG_ERROR, 1, TEXT("CheckMediaType failed: Format Type is not ")
|
|
TEXT("FORMAT_VideoInfo | FORMAT_VideoInfo2") ));
|
|
|
|
return VFW_E_TYPE_NOT_ACCEPTED;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::RuntimeAbortPlayback
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::RuntimeAbortPlayback(
|
|
HRESULT hr
|
|
)
|
|
{
|
|
HRESULT hrRet = S_FALSE;
|
|
AMTRACE((TEXT("CVMRFilter::RuntimeAbortPlayback")));
|
|
|
|
// A deadlock could occur if the caller holds the renderer lock and
|
|
// attempts to acquire the interface lock.
|
|
ASSERT(CritCheckOut(&m_RendererLock));
|
|
|
|
|
|
// The interface lock must be held when the filter is calling
|
|
// IsStopped().
|
|
CAutoLock cRendererLock(&m_InterfaceLock);
|
|
|
|
|
|
// We do not report errors which occur while the filter is stopping,
|
|
// flushing or if the m_bAbort flag is set . Errors are expected to
|
|
// occur during these operations and the streaming thread correctly
|
|
// handles the errors.
|
|
|
|
BOOL bAbort;
|
|
m_lpISControl->GetAbortSignal(&bAbort);
|
|
|
|
if (!IsStopped() && !bAbort) {
|
|
|
|
// EC_ERRORABORT's first parameter is the error which caused
|
|
// the event and its' last parameter is 0. See the Direct
|
|
// Show SDK documentation for more information.
|
|
|
|
NotifyEvent(EC_ERRORABORT, hr, 0);
|
|
|
|
CAutoLock alRendererLock(&m_RendererLock);
|
|
|
|
hrRet = m_lpISControl->RuntimeAbortPlayback();
|
|
}
|
|
|
|
return hrRet;
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::OnSetProperties
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::OnSetProperties(
|
|
CVMRInputPin *pReceivePin
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::OnSetProperties")));
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
//
|
|
// if we are processing a display change clear this pins bit in
|
|
// the display change mask
|
|
//
|
|
const DWORD dwPinBit = (1 << pReceivePin->m_dwPinID);
|
|
if (m_dwDisplayChangeMask & dwPinBit) {
|
|
m_dwDisplayChangeMask &= ~dwPinBit;
|
|
}
|
|
else if (m_pVideoWindow) {
|
|
|
|
ASSERT(m_VMRMode & VMRMode_Windowed);
|
|
if( m_VMRMode & VMRMode_Windowed ) {
|
|
m_pVideoWindow->SetDefaultSourceRect();
|
|
m_pVideoWindow->SetDefaultTargetRect();
|
|
m_pVideoWindow->OnVideoSizeChange();
|
|
|
|
// Notify the video window of the CompleteConnect
|
|
m_pVideoWindow->CompleteConnect();
|
|
if (pReceivePin->m_fInDFC) {
|
|
m_pVideoWindow->ActivateWindowAsync(TRUE);
|
|
}
|
|
else {
|
|
m_pVideoWindow->ActivateWindow();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
** IVMRSurfaceAllocatorNotify
|
|
** -------------------------------------------------------------------------
|
|
*/
|
|
|
|
CVMRFilter::CIVMRSurfaceAllocatorNotify::~CIVMRSurfaceAllocatorNotify()
|
|
{
|
|
// All of the references to this object should have been
|
|
// released before the VMR is destroyed.
|
|
ASSERT(0 == m_cRef);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::AdviseSurfaceAllocator
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRSurfaceAllocatorNotify::AdviseSurfaceAllocator(
|
|
DWORD_PTR dwUserID,
|
|
IVMRSurfaceAllocator* lpIVRMSurfaceAllocator
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIVMRSurfaceAllocatorNotify::AdviseSurfaceAllocator")));
|
|
CAutoLock cInterfaceLock(&m_pObj->m_InterfaceLock);
|
|
|
|
FILTER_STATE State;
|
|
|
|
//
|
|
// If the caller hasn't set the VMR's mode yet - fail.
|
|
// The mode has to renderless, we can't have any pins connected,
|
|
// and SetVMRMode has to have called.
|
|
//
|
|
BOOL fOK = ((m_pObj->m_VMRMode & VMRMode_Renderless) &&
|
|
0 == m_pObj->NumInputPinsConnected() &&
|
|
!m_pObj->m_bModeChangeAllowed);
|
|
if (!fOK) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("SetVMRMode has not been called")));
|
|
return VFW_E_WRONG_STATE;
|
|
}
|
|
|
|
// Make sure we are in a stopped state
|
|
|
|
m_pObj->GetState(0, &State);
|
|
if (State != State_Stopped) {
|
|
return VFW_E_NOT_STOPPED;
|
|
}
|
|
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (lpIVRMSurfaceAllocator) {
|
|
lpIVRMSurfaceAllocator->AddRef();
|
|
}
|
|
|
|
RELEASE(m_pObj->m_lpWLControl);
|
|
RELEASE(m_pObj->m_lpRLNotify);
|
|
RELEASE(m_pObj->m_lpPresenter);
|
|
RELEASE(m_pObj->m_pPresenterConfig);
|
|
RELEASE(m_pObj->m_pPresenterMonitorConfig);
|
|
|
|
m_pObj->m_lpRLNotify = lpIVRMSurfaceAllocator;
|
|
m_pObj->m_dwUserID = dwUserID;
|
|
|
|
if (m_pObj->m_lpRLNotify) {
|
|
|
|
if (m_pObj->m_lpMixControl) {
|
|
ASSERT(!m_pObj->m_VMRModePassThru);
|
|
hr = m_pObj->m_lpMixControl->SetBackEndAllocator(
|
|
m_pObj->m_lpRLNotify,
|
|
m_pObj->m_dwUserID);
|
|
}
|
|
|
|
hr = m_pObj->m_lpRLNotify->QueryInterface(
|
|
IID_IVMRImagePresenter,
|
|
(LPVOID*)&m_pObj->m_lpPresenter);
|
|
if( SUCCEEDED( hr )) {
|
|
m_pObj->m_lpPresenter->QueryInterface(
|
|
IID_IVMRImagePresenterConfig,
|
|
(LPVOID*)&m_pObj->m_pPresenterConfig);
|
|
|
|
m_pObj->m_lpPresenter->QueryInterface(
|
|
IID_IVMRMonitorConfig,
|
|
(LPVOID*)&m_pObj->m_pPresenterMonitorConfig);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetDDrawDevice
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRSurfaceAllocatorNotify::SetDDrawDevice(
|
|
LPDIRECTDRAW7 lpDDrawDevice,
|
|
HMONITOR hMonitor
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIVMRSurfaceAllocatorNotify::SetDDrawDevice")));
|
|
CAutoLock cInterfaceLock(&m_pObj->m_InterfaceLock);
|
|
if ( ( NULL == lpDDrawDevice ) || ( NULL == hMonitor ) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("NULL device or monitor") ));
|
|
return E_POINTER;
|
|
}
|
|
HRESULT hr = S_OK;
|
|
hr = m_pObj->SetDDrawDeviceWorker(lpDDrawDevice, hMonitor);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::ChangeDDrawDevice
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRSurfaceAllocatorNotify::ChangeDDrawDevice(
|
|
LPDIRECTDRAW7 lpDDrawDevice,
|
|
HMONITOR hMonitor
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIVMRSurfaceAllocatorNotify::ChangeDDrawDevice")));
|
|
CAutoLock cInterfaceLock(&m_pObj->m_InterfaceLock);
|
|
|
|
HRESULT hr = S_OK;
|
|
hr = m_pObj->SetDDrawDeviceWorker(lpDDrawDevice, hMonitor);
|
|
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
// The VMR can have at most MAX_MIXER_PINS input pins.
|
|
ASSERT(MAX_MIXER_PINS == NUMELMS(m_pObj->m_pInputPins));
|
|
IPin* apPinLocal[MAX_MIXER_PINS];
|
|
IPin** ppPin = NULL;
|
|
int i, iPinCount;
|
|
const int iPinsCreated = m_pObj->GetPinCount();
|
|
ULONG AllocSize = sizeof(IPin*) * iPinsCreated;
|
|
ppPin = (IPin**)CoTaskMemAlloc(AllocSize);
|
|
|
|
if (ppPin) {
|
|
|
|
ZeroMemory(ppPin, AllocSize);
|
|
|
|
//
|
|
// now tell each input pin to reconnect
|
|
//
|
|
|
|
for (iPinCount = 0, i = 0; i < iPinsCreated; i++) {
|
|
|
|
//
|
|
// get IPin interface
|
|
//
|
|
|
|
if (hr == S_OK && m_pObj->m_pInputPins[i]->IsConnected()) {
|
|
|
|
hr = m_pObj->m_pInputPins[i]->QueryInterface(
|
|
IID_IPin, (void**)&ppPin[iPinCount]);
|
|
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(ppPin[iPinCount]);
|
|
|
|
apPinLocal[iPinCount] = ppPin[iPinCount];
|
|
|
|
iPinCount++;
|
|
m_pObj->m_dwDisplayChangeMask |=
|
|
(1 << m_pObj->m_pInputPins[i]->GetPinID());
|
|
}
|
|
}
|
|
|
|
//
|
|
// Pass our input pin array as parameter on the event, we don't free
|
|
// the allocated memory - this is done by the event processing
|
|
// code in the FilterGraph
|
|
//
|
|
|
|
if (iPinCount > 0) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("EC_DISPLAY_CHANGED sent %d pins to re-connect"),
|
|
iPinCount));
|
|
|
|
// The VMR cannot access the ppPin array after it calls
|
|
// IMediaEventSink::Notify(). It cannot access the
|
|
// array because IMediaEventSink::Notify() can free the
|
|
// array at any time.
|
|
m_pObj->NotifyEvent(EC_DISPLAY_CHANGED, (LONG_PTR)ppPin,
|
|
(LONG_PTR)iPinCount);
|
|
}
|
|
|
|
//
|
|
// Release the IPin interfaces
|
|
//
|
|
|
|
for (i = 0; i < iPinCount; i++) {
|
|
apPinLocal[i]->Release();
|
|
}
|
|
|
|
|
|
//
|
|
// Tell the mixer about the display mode change.
|
|
//
|
|
|
|
if (SUCCEEDED(hr) && m_pObj->m_lpMixControl) {
|
|
ASSERT(!m_pObj->m_VMRModePassThru);
|
|
hr = m_pObj->m_lpMixControl->DisplayModeChanged();
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* SetDDrawDeviceWorker
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 03/09/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::SetDDrawDeviceWorker(
|
|
LPDIRECTDRAW7 lpDDrawDevice,
|
|
HMONITOR hMonitor
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetDDrawDeviceWorker")));
|
|
CVMRDeinterlaceContainer* pDeinterlace = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (hMonitor != NULL) {
|
|
|
|
MONITORINFO mi;
|
|
mi.cbSize = sizeof(mi);
|
|
if (!GetMonitorInfo(hMonitor, &mi)) {
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
if (lpDDrawDevice) {
|
|
|
|
INITDDSTRUCT(m_ddHWCaps);
|
|
hr = lpDDrawDevice->GetCaps((LPDDCAPS)&m_ddHWCaps, NULL);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
DDSURFACEDESC2 ddsd; // A surface description structure
|
|
INITDDSTRUCT(ddsd);
|
|
|
|
hr = lpDDrawDevice->GetDisplayMode(&ddsd);
|
|
if (SUCCEEDED(hr)) {
|
|
CopyMemory(&m_ddpfMonitor, &ddsd.ddpfPixelFormat,
|
|
sizeof(m_ddpfMonitor));
|
|
}
|
|
}
|
|
|
|
m_TexCaps = 0;
|
|
GetTextureCaps(lpDDrawDevice, &m_TexCaps);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
lpDDrawDevice->AddRef();
|
|
|
|
//
|
|
// we now try to create the deinterlace container DX-VA
|
|
// device. We continue on failure (including out of memory
|
|
// failures).
|
|
//
|
|
|
|
HRESULT hrT = S_OK;
|
|
pDeinterlace = new CVMRDeinterlaceContainer(lpDDrawDevice, &hrT);
|
|
if (FAILED(hrT) && pDeinterlace) {
|
|
delete pDeinterlace;
|
|
pDeinterlace = NULL;
|
|
}
|
|
}
|
|
else {
|
|
lpDDrawDevice = NULL;
|
|
}
|
|
}
|
|
|
|
if (m_lpDirectDraw) {
|
|
m_lpDirectDraw->Release();
|
|
}
|
|
|
|
if (m_pDeinterlace) {
|
|
delete m_pDeinterlace;
|
|
}
|
|
|
|
m_lpDirectDraw = lpDDrawDevice;
|
|
m_hMonitor = hMonitor;
|
|
m_pDeinterlace = pDeinterlace;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetBorderColor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 11/02/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRSurfaceAllocatorNotify::SetBorderColor(
|
|
COLORREF clr
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIVMRImagePresenter::SetBorderColor")));
|
|
|
|
/** this interface is not needed anymore - set SetBackgroundColor below
|
|
**/
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::RestoreDDrawSurfaces
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRSurfaceAllocatorNotify::RestoreDDrawSurfaces()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIVMRImagePresenter::RestoreDDrawSurface")));
|
|
|
|
//
|
|
// Don't generate EC_NEED_RESTART during a display mode change !
|
|
//
|
|
{
|
|
CAutoLock cInterfaceLock(&m_pObj->m_InterfaceLock);
|
|
if (m_pObj->m_dwDisplayChangeMask) {
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
m_pObj->NotifyEvent(EC_NEED_RESTART, 0, 0);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::NotifyEvent
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRSurfaceAllocatorNotify::NotifyEvent(
|
|
LONG EventCode,
|
|
LONG_PTR lp1,
|
|
LONG_PTR lp2
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIVMRImagePresenter::NotifyEvent")));
|
|
|
|
switch (EventCode) {
|
|
case EC_VMR_SURFACE_FLIPPED:
|
|
m_pObj->m_hrSurfaceFlipped = (HRESULT)lp1;
|
|
break;
|
|
|
|
default:
|
|
m_pObj->NotifyEvent(EventCode, lp1, lp2);
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
** IImageSyncPresenter
|
|
** -------------------------------------------------------------------------
|
|
*/
|
|
|
|
/******************************Public*Routine******************************\
|
|
* StartPresenting
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRImagePresenter::StartPresenting(
|
|
DWORD_PTR dwUserID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIVMRImagePresenter::StartPresenting")));
|
|
ASSERT(m_pObj->m_lpRLNotify);
|
|
HRESULT hr = S_OK;
|
|
hr = m_pObj->m_lpPresenter->StartPresenting(m_pObj->m_dwUserID);
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* StopPresenting
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRImagePresenter::StopPresenting(
|
|
DWORD_PTR dwUserID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::StopPresenting")));
|
|
ASSERT(m_pObj->m_lpRLNotify);
|
|
HRESULT hr = S_OK;
|
|
hr = m_pObj->m_lpPresenter->StopPresenting(m_pObj->m_dwUserID);
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::PresentImage
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIVMRImagePresenter::PresentImage(
|
|
DWORD_PTR dwUserID,
|
|
VMRPRESENTATIONINFO* lpPresInfo
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::PresentImage")));
|
|
ASSERT(m_pObj->m_lpRLNotify);
|
|
|
|
ASSERT(lpPresInfo);
|
|
ASSERT(lpPresInfo->lpSurf);
|
|
|
|
HRESULT hr = S_OK;
|
|
if (lpPresInfo && lpPresInfo->lpSurf) {
|
|
hr = m_pObj->m_lpPresenter->PresentImage(m_pObj->m_dwUserID, lpPresInfo);
|
|
}
|
|
else {
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
** IImageSyncNotifyEvent
|
|
** -------------------------------------------------------------------------
|
|
*/
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NotifyEvent
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::CIImageSyncNotifyEvent::NotifyEvent(
|
|
long lEventCode,
|
|
LONG_PTR lp1,
|
|
LONG_PTR lp2
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CIImageSyncNotifyEvent::NotifyEvent")));
|
|
HRESULT hr = S_OK;
|
|
|
|
switch (lEventCode) {
|
|
|
|
case EC_COMPLETE:
|
|
if (m_pObj->m_pPosition) {
|
|
m_pObj->m_pPosition->EOS();
|
|
}
|
|
|
|
// fall thru
|
|
|
|
case EC_STEP_COMPLETE:
|
|
hr = m_pObj->NotifyEvent(lEventCode, lp1, lp2);
|
|
break;
|
|
|
|
default:
|
|
DbgLog((LOG_ERROR, 0,
|
|
TEXT("Unkown event notified from the image sync object !!")));
|
|
ASSERT(0);
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
** IVRWindowlessControl
|
|
** -------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* CVMRFilter::CreateDefaultAllocatorPresenter
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/03/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::CreateDefaultAllocatorPresenter()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CoCreateInstance(CLSID_AllocPresenter, NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IVMRSurfaceAllocator,
|
|
(LPVOID*)&m_lpRLNotify);
|
|
|
|
if (SUCCEEDED(hr) && m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
hr = m_lpMixControl->SetBackEndAllocator(m_lpRLNotify, m_dwUserID);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
m_lpRLNotify->AdviseNotify(&m_pIVMRSurfaceAllocatorNotify);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpRLNotify->QueryInterface(IID_IVMRImagePresenter,
|
|
(LPVOID*)&m_lpPresenter);
|
|
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
m_lpRLNotify->QueryInterface(IID_IVMRImagePresenterConfig,
|
|
(LPVOID*)&m_pPresenterConfig);
|
|
|
|
m_lpRLNotify->QueryInterface(IID_IVMRMonitorConfig,
|
|
(LPVOID*)&m_pPresenterMonitorConfig);
|
|
}
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
m_lpMixControl->SetBackEndAllocator(NULL, m_dwUserID);
|
|
}
|
|
|
|
RELEASE(m_lpRLNotify);
|
|
RELEASE(m_lpPresenter);
|
|
RELEASE(m_pPresenterConfig);
|
|
RELEASE(m_pPresenterMonitorConfig);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* ValidateIVRWindowlessControlState
|
|
*
|
|
* Checks that the filter is in the correct state to process commands via
|
|
* the WindowlessControl interface.
|
|
*
|
|
* History:
|
|
* Tue 02/29/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::ValidateIVRWindowlessControlState()
|
|
{
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
AMTRACE((TEXT("CVMRFilter::ValidateIVRWindowlessControlState")));
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
|
|
if (m_VMRMode & (VMRMode_Windowed | VMRMode_Windowless) ) {
|
|
|
|
hr = S_OK;
|
|
if (!m_lpWLControl) {
|
|
|
|
if (!m_lpRLNotify) {
|
|
|
|
ASSERT(NumInputPinsConnected() == 0);
|
|
hr = CreateDefaultAllocatorPresenter();
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpRLNotify->QueryInterface(IID_IVMRWindowlessControl,
|
|
(LPVOID*)&m_lpWLControl);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
m_lpWLControl->SetAspectRatioMode(m_ARMode);
|
|
|
|
if (m_pVideoWindow) {
|
|
HWND hwnd = m_pVideoWindow->GetWindowHWND();
|
|
m_lpWLControl->SetVideoClippingWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Can't get a WindowLess control interface !!")));
|
|
// ASSERT(!"Can't get a WindowLess control interface !!");
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
ASSERT((m_VMRMode & VMRMode_Renderless) == VMRMode_Renderless);
|
|
|
|
//
|
|
// We are in renderless mode, the app should have plugged in an
|
|
// allocator-presenter. If it has lets see if this allocator-presenter
|
|
// supports the IVMRWindowlessControl interface ?
|
|
//
|
|
|
|
if (!m_lpWLControl) {
|
|
|
|
if (m_lpRLNotify) {
|
|
|
|
hr = m_lpRLNotify->QueryInterface(IID_IVMRWindowlessControl,
|
|
(LPVOID*)&m_lpWLControl);
|
|
if (SUCCEEDED(hr)) {
|
|
m_lpWLControl->SetAspectRatioMode(m_ARMode);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetNativeVideoSize
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetNativeVideoSize(
|
|
LONG* lWidth,
|
|
LONG* lHeight,
|
|
LONG* lARWidth,
|
|
LONG* lARHeight
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetNativeVideoSize")));
|
|
|
|
if ( ISBADWRITEPTR(lWidth) || ISBADWRITEPTR(lHeight) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetNativeVideoSize(lWidth, lHeight,
|
|
lARWidth, lARHeight);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetMinIdealVideoSize
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetMinIdealVideoSize(
|
|
LONG* lWidth,
|
|
LONG* lHeight
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetMinIdealVideoSize")));
|
|
|
|
if ( ISBADWRITEPTR(lWidth) || ISBADWRITEPTR(lHeight) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetMinIdealVideoSize(lWidth, lHeight);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetMaxIdealVideoSize
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetMaxIdealVideoSize(
|
|
LONG* lWidth,
|
|
LONG* lHeight
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetMaxIdealVideoSize")));
|
|
|
|
if ( ISBADWRITEPTR(lWidth) || ISBADWRITEPTR(lHeight) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetMaxIdealVideoSize(lWidth, lHeight);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetVideoPosition
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetVideoPosition(
|
|
const LPRECT lpSRCRect,
|
|
const LPRECT lpDSTRect
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetVideoPosition")));
|
|
|
|
if ( ISBADREADPTR(lpSRCRect) && ISBADREADPTR(lpDSTRect) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->SetVideoPosition(lpSRCRect, lpDSTRect);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetVideoPosition
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetVideoPosition(
|
|
LPRECT lpSRCRect,
|
|
LPRECT lpDSTRect
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetVideoPosition")));
|
|
|
|
if ( ISBADWRITEPTR(lpSRCRect) && ISBADWRITEPTR(lpDSTRect) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetVideoPosition(lpSRCRect, lpDSTRect);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetAspectRatioMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 02/29/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetAspectRatioMode(
|
|
DWORD* lpAspectRatioMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetAspectRationMode")));
|
|
|
|
if ( ISBADWRITEPTR(lpAspectRatioMode) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetAspectRatioMode(lpAspectRatioMode);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetAspectRatioMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 02/29/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetAspectRatioMode(
|
|
DWORD AspectRatioMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetAspectRationMode")));
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->SetAspectRatioMode(AspectRatioMode);
|
|
}
|
|
|
|
if( SUCCEEDED(hr )) {
|
|
m_bARModeDefaultSet = TRUE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetVideoClippingWindow
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetVideoClippingWindow(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetWindowHandle")));
|
|
|
|
if (!IsWindow(hwnd) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid HWND")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->SetVideoClippingWindow(hwnd);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::RepaintVideo
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::RepaintVideo(
|
|
HWND hwnd,
|
|
HDC hdc
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::RepaintVideo")));
|
|
|
|
if (!IsWindow(hwnd) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid HWND")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!hdc) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid HDC")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->RepaintVideo(hwnd, hdc);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::DisplayModeChanged
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 02/29/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::DisplayModeChanged()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::DisplayModeChanged")));
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->DisplayModeChanged();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetCurrentImage
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 06/23/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetCurrentImage(
|
|
BYTE** lpDib
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetCurrentImage")));
|
|
|
|
if (ISBADWRITEPTR(lpDib)) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetCurrentImage(lpDib);
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetBorderColor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetBorderColor(
|
|
COLORREF Clr
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetBorderColor")));
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->SetBorderColor(Clr);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetBorderColor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetBorderColor(
|
|
COLORREF* lpClr
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetBorderColor")));
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetBorderColor(lpClr);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetColorKey
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetColorKey(
|
|
COLORREF Clr
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetColorKey")));
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->SetColorKey(Clr);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetColorKey
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 02/25/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetColorKey(
|
|
COLORREF* lpClr
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetColorKey")));
|
|
|
|
HRESULT hr = ValidateIVRWindowlessControlState();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->GetColorKey(lpClr);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetAlpha
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/24/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::SetAlpha(
|
|
DWORD dwStreamID,
|
|
float Alpha
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetAlpha")));
|
|
|
|
CAutoLock lck(m_pLock);
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
return m_lpMixStream->SetStreamAlpha(dwStreamID, Alpha);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetAlpha
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/24/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::GetAlpha(
|
|
DWORD dwStreamID,
|
|
float* pAlpha
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetAlpha")));
|
|
|
|
CAutoLock lck(m_pLock);
|
|
|
|
if (ISBADWRITEPTR(pAlpha))
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
return m_lpMixStream->GetStreamAlpha(dwStreamID, pAlpha);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetZOrder
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/24/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::SetZOrder(
|
|
DWORD dwStreamID,
|
|
DWORD ZOrder
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetZOrder")));
|
|
|
|
CAutoLock lck(m_pLock);
|
|
HRESULT hr = VFW_E_NOT_CONNECTED;
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
return m_lpMixStream->SetStreamZOrder(dwStreamID, ZOrder);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetZOrder
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/24/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::GetZOrder(
|
|
DWORD dwStreamID,
|
|
DWORD* pdwZOrder
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetZOrder")));
|
|
|
|
CAutoLock lck(m_pLock);
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (ISBADWRITEPTR(pdwZOrder))
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("GetZOrder: Invalid pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
return m_lpMixStream->GetStreamZOrder(dwStreamID, pdwZOrder);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::SetRelativeOutputRect
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/24/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::SetOutputRect(
|
|
DWORD dwStreamID,
|
|
const NORMALIZEDRECT *prDest
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetOutputRect")));
|
|
|
|
CAutoLock lck(m_pLock);
|
|
|
|
if (ISBADREADPTR(prDest))
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("SetOutputRect: Invalid pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
return m_lpMixStream->SetStreamOutputRect(dwStreamID, prDest);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CVMRFilter::GetOutputRect
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/24/2000 - GlennE - Created
|
|
* Tue 05/16/2000 - nwilt - renamed to GetOutputRect
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::GetOutputRect(
|
|
DWORD dwStreamID,
|
|
NORMALIZEDRECT* pOut
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetOutputRect")));
|
|
|
|
CAutoLock lck(m_pLock);
|
|
|
|
if (ISBADWRITEPTR(pOut))
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("GetOutputRect: Invalid pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
return m_lpMixStream->GetStreamOutputRect(dwStreamID, pOut);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetBackgroundClr
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/02/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::SetBackgroundClr(
|
|
COLORREF clrBkg
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetBackgroundClr")));
|
|
|
|
CAutoLock lck(m_pLock);
|
|
HRESULT hr = VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
hr = m_lpMixControl->SetBackgroundColor(clrBkg);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetBackgroundClr
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/02/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::GetBackgroundClr(
|
|
COLORREF* lpClrBkg
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetBackgroundClr")));
|
|
CAutoLock lck(m_pLock);
|
|
|
|
if (ISBADWRITEPTR(lpClrBkg))
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("GetBackgroundClr: Invalid pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
hr = m_lpMixControl->GetBackgroundColor(lpClrBkg);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetMixingPrefs
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/02/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::SetMixingPrefs(
|
|
DWORD dwRenderFlags
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetMixingPrefs")));
|
|
CAutoLock lck(m_pLock);
|
|
|
|
HRESULT hr = VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
hr = m_lpMixControl->SetMixingPrefs(dwRenderFlags);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetMixingPrefs
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/02/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::GetMixingPrefs(
|
|
DWORD* pdwRenderFlags
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetMixingPrefs")));
|
|
CAutoLock lck(m_pLock);
|
|
|
|
if (ISBADWRITEPTR(pdwRenderFlags))
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("GetMixingPrefs: Invalid pointer")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
hr = m_lpMixControl->GetMixingPrefs(pdwRenderFlags);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* IsVPMConnectedToUs
|
|
*
|
|
* check for the VPM - we can't frame step if it is connected to us.
|
|
*
|
|
* History:
|
|
* Wed 06/13/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
CVMRFilter::IsVPMConnectedToUs()
|
|
{
|
|
for (DWORD i = 0; i < m_dwNumPins; i++) {
|
|
|
|
if (m_pInputPins[i]->m_Connected) {
|
|
|
|
PIN_INFO Inf;
|
|
HRESULT hr = m_pInputPins[i]->m_Connected->QueryPinInfo(&Inf);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
IVPManager* vpm;
|
|
hr = Inf.pFilter->QueryInterface(IID_IVPManager,(LPVOID*)&vpm);
|
|
Inf.pFilter->Release();
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
vpm->Release();
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Set
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/11/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::Set(
|
|
REFGUID guidPropSet,
|
|
DWORD dwPropID,
|
|
LPVOID pInstanceData,
|
|
DWORD cbInstanceData,
|
|
LPVOID pPropData,
|
|
DWORD cbPropData
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Set")));
|
|
|
|
if (guidPropSet == AM_KSPROPSETID_FrameStep)
|
|
{
|
|
if (IsVPMConnectedToUs()) {
|
|
return E_PROP_ID_UNSUPPORTED;
|
|
}
|
|
|
|
if (dwPropID != AM_PROPERTY_FRAMESTEP_STEP &&
|
|
dwPropID != AM_PROPERTY_FRAMESTEP_CANCEL &&
|
|
dwPropID != AM_PROPERTY_FRAMESTEP_CANSTEP &&
|
|
dwPropID != AM_PROPERTY_FRAMESTEP_CANSTEPMULTIPLE)
|
|
{
|
|
return E_PROP_ID_UNSUPPORTED;
|
|
}
|
|
|
|
switch (dwPropID) {
|
|
case AM_PROPERTY_FRAMESTEP_STEP:
|
|
if (cbPropData < sizeof(AM_FRAMESTEP_STEP)) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (0 == ((AM_FRAMESTEP_STEP *)pPropData)->dwFramesToStep) {
|
|
return E_INVALIDARG;
|
|
}
|
|
else {
|
|
CAutoLock cLock(&m_InterfaceLock);
|
|
DWORD dwStep = ((AM_FRAMESTEP_STEP *)pPropData)->dwFramesToStep;
|
|
return m_lpISControl->FrameStep(dwStep, 0);
|
|
}
|
|
return S_OK;
|
|
|
|
|
|
case AM_PROPERTY_FRAMESTEP_CANCEL:
|
|
{
|
|
CAutoLock cLock(&m_InterfaceLock);
|
|
return m_lpISControl->CancelFrameStep();
|
|
}
|
|
return S_OK;
|
|
|
|
case AM_PROPERTY_FRAMESTEP_CANSTEP:
|
|
case AM_PROPERTY_FRAMESTEP_CANSTEPMULTIPLE:
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
if (guidPropSet != AM_KSPROPSETID_CopyProt)
|
|
return E_PROP_SET_UNSUPPORTED;
|
|
|
|
if (dwPropID != AM_PROPERTY_COPY_MACROVISION)
|
|
return E_PROP_ID_UNSUPPORTED;
|
|
|
|
if (pPropData == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (cbPropData < sizeof(DWORD))
|
|
return E_INVALIDARG ;
|
|
|
|
if (m_MacroVision.SetMacroVision(m_hMonitor, *((LPDWORD)pPropData)))
|
|
return NOERROR;
|
|
else
|
|
return VFW_E_COPYPROT_FAILED;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Get
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/11/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::Get(
|
|
REFGUID guidPropSet,
|
|
DWORD PropID,
|
|
LPVOID pInstanceData,
|
|
DWORD cbInstanceData,
|
|
LPVOID pPropData,
|
|
DWORD cbPropData,
|
|
DWORD *pcbReturned
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Get")));
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* QuerySupported
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/11/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::QuerySupported(
|
|
REFGUID guidPropSet,
|
|
DWORD dwPropID,
|
|
DWORD *pTypeSupport
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::QuerySupported")));
|
|
|
|
if (guidPropSet != AM_KSPROPSETID_CopyProt)
|
|
return E_PROP_SET_UNSUPPORTED ;
|
|
|
|
if (dwPropID != AM_PROPERTY_COPY_MACROVISION)
|
|
return E_PROP_ID_UNSUPPORTED ;
|
|
|
|
if (pTypeSupport)
|
|
*pTypeSupport = KSPROPERTY_SUPPORT_SET ;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetImageCompositor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 06/23/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetImageCompositor(
|
|
IVMRImageCompositor* lpVMRImgCompositor
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetImageCompositor")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
hr = m_lpMixControl->SetImageCompositor(lpVMRImgCompositor);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetNumberOfStreams
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/11/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetNumberOfStreams(
|
|
DWORD dwMaxStreams
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetNumberOfStreams")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
|
|
if (m_hr3D != DD_OK) {
|
|
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("This graphics mode does not have the necessary 3D h/w to perform mix!ing !")));
|
|
|
|
return m_hr3D;
|
|
}
|
|
|
|
// preempt egregiously bad calls before passing to mixer
|
|
if (dwMaxStreams > MAX_MIXER_STREAMS) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Too many Mixer Streams !!")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_fInputPinCountSet && m_VMRModePassThru && !NumInputPinsConnected())
|
|
{
|
|
if (dwMaxStreams > 0) {
|
|
|
|
hr = S_OK;
|
|
if (dwMaxStreams > 1) {
|
|
// We subtract one from the number of streams because the
|
|
// first input pin has already been created in the constructor.
|
|
hr = CreateExtraInputPins(dwMaxStreams-1);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = MixerInit(dwMaxStreams);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Mixer initialization FAILED!!")));
|
|
|
|
if (dwMaxStreams > 1) {
|
|
DestroyExtraInputPins();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
DbgLog((LOG_ERROR, 1, TEXT("MaxStreams must be greater than 0")));
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
m_fInputPinCountSet = true;
|
|
m_VMRModePassThru = false;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetNumberOfStreams
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/11/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetNumberOfStreams(
|
|
DWORD* pdwMaxStreams
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetNumberOfStreams")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if ( ISBADWRITEPTR(pdwMaxStreams) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
if (m_lpMixControl) {
|
|
ASSERT(!m_VMRModePassThru);
|
|
hr = m_lpMixControl->GetNumberOfStreams(pdwMaxStreams);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetRenderingPrefs
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetRenderingPrefs(
|
|
DWORD dwRenderingPrefs
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetRenderingPrefs")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (dwRenderingPrefs & ~RenderPrefs_Mask) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid rendering pref specified")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
if (m_pPresenterConfig) {
|
|
|
|
if (dwRenderingPrefs & RenderPrefs_PreferAGPMemWhenMixing) {
|
|
m_dwRenderPrefs |= RenderPrefs_PreferAGPMemWhenMixing;
|
|
}
|
|
else {
|
|
m_dwRenderPrefs &= ~RenderPrefs_PreferAGPMemWhenMixing;
|
|
}
|
|
|
|
// turn of flags that don't effect the AP object.
|
|
dwRenderingPrefs &= ~RenderPrefs_PreferAGPMemWhenMixing;
|
|
|
|
hr = m_pPresenterConfig->SetRenderingPrefs(dwRenderingPrefs);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetRenderingPrefs
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetRenderingPrefs(
|
|
DWORD* pdwRenderingPrefs
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetRenderingPrefs")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if ( ISBADWRITEPTR(pdwRenderingPrefs) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
if (m_pPresenterConfig) {
|
|
hr = m_pPresenterConfig->GetRenderingPrefs(pdwRenderingPrefs);
|
|
if (SUCCEEDED(hr)) {
|
|
*pdwRenderingPrefs |= m_dwRenderPrefs;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetRenderingMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetRenderingMode(
|
|
DWORD RenderingMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetRenderingMode")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
|
|
if ( ( 0 == RenderingMode ) ||
|
|
( RenderingMode & ~(VMRMode_Mask) ) ||
|
|
( RenderingMode & (RenderingMode-1) ) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid rendering mode") ));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// This is the only place where "pass thru" mode can be switched on
|
|
//
|
|
if (ModeChangeAllowed()) {
|
|
|
|
SetVMRMode(RenderingMode);
|
|
|
|
hr = S_OK;
|
|
if ((RenderingMode & VMRMode_Windowless) || (RenderingMode & VMRMode_Windowed)) {
|
|
hr = ValidateIVRWindowlessControlState();
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetRenderingMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetRenderingMode(
|
|
DWORD* pRenderingMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetRenderingMode")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( ISBADWRITEPTR(pRenderingMode) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
*pRenderingMode = m_VMRMode;
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetAspectRatioModePrivate
|
|
*
|
|
*
|
|
* Called by VMRConfigInternal - no longer used
|
|
*
|
|
* History:
|
|
* Fri 01/05/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetAspectRatioModePrivate(
|
|
DWORD* lpAspectRatioMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetAspectRatioModePrivate")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( ISBADWRITEPTR(lpAspectRatioMode) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (m_lpWLControl) {
|
|
|
|
hr = m_lpWLControl->GetAspectRatioMode(lpAspectRatioMode);
|
|
}
|
|
else {
|
|
*lpAspectRatioMode = m_ARMode;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetAspectRatioModePrivate
|
|
*
|
|
*
|
|
* Called by VMRConfigInternal - no longer used
|
|
*
|
|
* History:
|
|
* Fri 01/05/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetAspectRatioModePrivate(
|
|
DWORD AspectRatioMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetAspectRatioModePrivate")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = S_OK;
|
|
|
|
if (AspectRatioMode != VMR_ARMODE_NONE &&
|
|
AspectRatioMode != VMR_ARMODE_LETTER_BOX) {
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (m_lpWLControl) {
|
|
|
|
hr = m_lpWLControl->SetAspectRatioMode(AspectRatioMode);
|
|
}
|
|
else {
|
|
m_ARMode = AspectRatioMode;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetMonitor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetMonitor(
|
|
const VMRGUID *pGUID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetMonitor")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
if (m_pPresenterMonitorConfig) {
|
|
hr = m_pPresenterMonitorConfig->SetMonitor( pGUID );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetMonitor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetMonitor(
|
|
VMRGUID *pGUID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetMonitor")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if ( ISBADWRITEPTR(pGUID) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
if (m_pPresenterMonitorConfig) {
|
|
hr = m_pPresenterMonitorConfig->GetMonitor( pGUID );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetDefaultMonitor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetDefaultMonitor(
|
|
const VMRGUID *pGUID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetDefaultMonitor")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if ( ISBADREADPTR(pGUID) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
if (m_pPresenterMonitorConfig) {
|
|
hr = m_pPresenterMonitorConfig->SetDefaultMonitor( pGUID );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetDefaultMonitor
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetDefaultMonitor(
|
|
VMRGUID *pGUID
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetDefaultMonitor")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if ( ISBADWRITEPTR(pGUID) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
if (m_pPresenterMonitorConfig) {
|
|
hr = m_pPresenterMonitorConfig->GetDefaultMonitor( pGUID );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetAvailableMonitors
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Tue 04/25/2000 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetAvailableMonitors(
|
|
VMRMONITORINFO* pInfo,
|
|
DWORD dwMaxInfoArraySize,
|
|
DWORD* pdwNumDevices
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetAvailableMonitors")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if ( ISBADWRITEPTR(pdwNumDevices) ||
|
|
( (NULL != pInfo) && ISBADWRITEARRAY(pInfo,dwMaxInfoArraySize)))
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
if (m_pPresenterMonitorConfig) {
|
|
hr = m_pPresenterMonitorConfig->GetAvailableMonitors(pInfo,
|
|
dwMaxInfoArraySize,
|
|
pdwNumDevices);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetAlphaBitmap
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/15/2000 - nwilt - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetAlphaBitmap( const VMRALPHABITMAP *pBmpParms )
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetAlphaBitmap")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
|
|
if ( ISBADREADPTR( pBmpParms ) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (m_lpMixBitmap) {
|
|
hr = m_lpMixBitmap->SetAlphaBitmap( pBmpParms );
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* UpdateAlphaBitmapParameters
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 10/31/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::UpdateAlphaBitmapParameters( VMRALPHABITMAP *pBmpParms )
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::UpdateAlphaBitmap")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
|
|
if ( ISBADWRITEPTR( pBmpParms ) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (m_lpMixBitmap) {
|
|
hr = m_lpMixBitmap->UpdateAlphaBitmapParameters( pBmpParms );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetAlphaBitmapParameters
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/15/2000 - nwilt - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetAlphaBitmapParameters( VMRALPHABITMAP *pBmpParms )
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetAlphaBitmap")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
HRESULT hr = VFW_E_WRONG_STATE;
|
|
|
|
if ( ISBADWRITEPTR( pBmpParms ) )
|
|
{
|
|
DbgLog((LOG_ERROR, 1, TEXT("Bad pointer") ));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (m_lpMixBitmap) {
|
|
hr = m_lpMixBitmap->GetAlphaBitmapParameters( pBmpParms );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* get_FramesDroppedInRenderer
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::get_FramesDroppedInRenderer(
|
|
int *cFramesDropped
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::get_FramesDroppedInRenderer")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
if (m_lpISQualProp) {
|
|
hr = m_lpISQualProp->get_FramesDroppedInRenderer(cFramesDropped);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* get_FramesDrawn
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::get_FramesDrawn(
|
|
int *pcFramesDrawn
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::get_FramesDrawn")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
if (m_lpISQualProp) {
|
|
hr = m_lpISQualProp->get_FramesDrawn(pcFramesDrawn);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* get_AvgFrameRate
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::get_AvgFrameRate(
|
|
int *piAvgFrameRate
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::get_AvgFrameRate")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
if (m_lpISQualProp) {
|
|
hr = m_lpISQualProp->get_AvgFrameRate(piAvgFrameRate);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* get_Jitter
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::get_Jitter(
|
|
int *piJitter
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::get_Jitter")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
if (m_lpISQualProp) {
|
|
hr = m_lpISQualProp->get_Jitter(piJitter);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* get_AvgSyncOffset
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::get_AvgSyncOffset(
|
|
int *piAvg
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::get_AvgSyncOffset")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
if (m_lpISQualProp) {
|
|
hr = m_lpISQualProp->get_AvgSyncOffset(piAvg);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* get_DevSyncOffset
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::get_DevSyncOffset(
|
|
int *piDev
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::get_DevSyncOffset")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
if (m_lpISQualProp) {
|
|
hr = m_lpISQualProp->get_DevSyncOffset(piDev);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetSink
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetSink(
|
|
IQualityControl * piqc
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetSink")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Notify
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 05/22/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::Notify(
|
|
IBaseFilter * pSelf,
|
|
Quality q
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::Notify")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
HRESULT hr = E_NOTIMPL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* JoinFilterGraph
|
|
*
|
|
*
|
|
* Override JoinFilterGraph so that, just before leaving
|
|
* the graph we can send an EC_WINDOW_DESTROYED event
|
|
*
|
|
* History:
|
|
* Mon 11/06/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::JoinFilterGraph(
|
|
IFilterGraph *pGraph,
|
|
LPCWSTR pName
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::JoinFilterGraph")));
|
|
|
|
if (m_VMRMode == VMRMode_Windowed && m_pVideoWindow) {
|
|
|
|
// Since we send EC_ACTIVATE, we also need to ensure
|
|
// we send EC_WINDOW_DESTROYED or the resource manager may be
|
|
// holding us as a focus object
|
|
|
|
if (!pGraph && m_pGraph) {
|
|
|
|
// We were in a graph and now we're not
|
|
// Do this properly in case we are aggregated
|
|
IBaseFilter* pFilter;
|
|
QueryInterface(IID_IBaseFilter,(void **) &pFilter);
|
|
NotifyEvent(EC_WINDOW_DESTROYED, (LPARAM) pFilter, 0);
|
|
pFilter->Release();
|
|
}
|
|
}
|
|
|
|
return CBaseFilter::JoinFilterGraph(pGraph, pName);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetPages
|
|
*
|
|
*
|
|
* Implement ISpecifyPropertyPages interface.
|
|
* Returns GUIDs of all supported property pages.
|
|
*
|
|
* History:
|
|
* 3/23/2001 - StRowe - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP CVMRFilter::GetPages(CAUUID *pPages)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetPages")));
|
|
|
|
pPages->cElems = 3;
|
|
pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID)*(pPages->cElems));
|
|
if (pPages->pElems == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
pPages->pElems[0] = CLSID_VMRFilterConfigProp;
|
|
pPages->pElems[1] = CLSID_COMQualityProperties;
|
|
pPages->pElems[2] = CLSID_VMRDeinterlaceProp;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// CPersistStream
|
|
/******************************Public*Routine******************************\
|
|
* WriteToStream
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/23/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::WriteToStream(
|
|
IStream *pStream
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::WriteToStream")));
|
|
VMRFilterInfo vmrInfo;
|
|
|
|
ZeroMemory(&vmrInfo, sizeof(vmrInfo));
|
|
vmrInfo.dwSize = sizeof(vmrInfo);
|
|
|
|
//
|
|
// Only write mixer info if we actually have a mixer !!
|
|
//
|
|
|
|
if (m_lpMixControl) {
|
|
|
|
vmrInfo.dwNumPins = m_dwNumPins;
|
|
for (DWORD i = 0; i < m_dwNumPins; i++) {
|
|
|
|
GetAlpha(i, &vmrInfo.StreamInfo[i].alpha);
|
|
GetZOrder(i, &vmrInfo.StreamInfo[i].zOrder);
|
|
GetOutputRect(i, &vmrInfo.StreamInfo[i].rect);
|
|
}
|
|
}
|
|
|
|
return pStream->Write(&vmrInfo, sizeof(vmrInfo), 0);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ReadFromStream
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/23/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::ReadFromStream(
|
|
IStream *pStream
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::ReadFromStream")));
|
|
VMRFilterInfo vmrInfo;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = pStream->Read(&vmrInfo, sizeof(vmrInfo), 0);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
if (vmrInfo.dwSize != sizeof(vmrInfo)) {
|
|
return VFW_E_INVALID_FILE_VERSION;
|
|
}
|
|
|
|
//
|
|
// zero pins means we are in "pass-thru" mode, so we
|
|
// don't have to restore any more info.
|
|
//
|
|
|
|
if (vmrInfo.dwNumPins > 0) {
|
|
|
|
hr = SetNumberOfStreams(vmrInfo.dwNumPins);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
for (DWORD i = 0; i < vmrInfo.dwNumPins; i++) {
|
|
|
|
SetAlpha(i, vmrInfo.StreamInfo[i].alpha);
|
|
SetZOrder(i, vmrInfo.StreamInfo[i].zOrder);
|
|
SetOutputRect(i, &vmrInfo.StreamInfo[i].rect);
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SizeMax
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/23/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
int
|
|
CVMRFilter::SizeMax()
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SizeMax")));
|
|
return sizeof(VMRFilterInfo);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetClassID
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 03/23/2001 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetClassID(
|
|
CLSID *pClsid
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetClassID")));
|
|
return CBaseFilter::GetClassID(pClsid);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CompleteConnect(dwPinID)
|
|
*
|
|
*
|
|
* Notes:
|
|
* Called by the VMR pin on connect. We use this to override the aspect ratio
|
|
* mode.
|
|
*
|
|
* History:
|
|
* Fri 07/12/2001 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRFilter::CompleteConnect(
|
|
DWORD dwPinId,
|
|
const CMediaType& cmt
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::CompleteConnect")));
|
|
|
|
|
|
if (NumInputPinsConnected() == 1 || dwPinId == 0) {
|
|
|
|
//
|
|
// set the default ASPECT ratio mode based on the input type
|
|
//
|
|
|
|
if (!m_bARModeDefaultSet) {
|
|
|
|
if (cmt.FormatType() && *cmt.FormatType() == FORMAT_VideoInfo2) {
|
|
|
|
//
|
|
// Look for the presence of a VideoInfo format type.
|
|
// If we find the upstream filter can propose these types
|
|
// we don't set the aspect ratio mode becuase this filter
|
|
// would have connected to the old renderer not the OVMixer
|
|
// The old renderer didn't perform any aspect ratio correction
|
|
// so we had better not too.
|
|
//
|
|
|
|
IPin* pReceivePin = m_pInputPins[dwPinId]->m_Connected;
|
|
IEnumMediaTypes *pEnumMediaTypes = NULL;
|
|
BOOL fVideoInfoAvail = FALSE;
|
|
|
|
HRESULT hr = pReceivePin->EnumMediaTypes(&pEnumMediaTypes);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
do {
|
|
|
|
AM_MEDIA_TYPE* pEnumMT;
|
|
ULONG ulFetched;
|
|
|
|
hr = pEnumMediaTypes->Next(1, &pEnumMT, &ulFetched);
|
|
if (FAILED(hr) || ulFetched != 1) {
|
|
break;
|
|
}
|
|
|
|
fVideoInfoAvail = (pEnumMT->formattype == FORMAT_VideoInfo);
|
|
DeleteMediaType(pEnumMT);
|
|
|
|
} while (!fVideoInfoAvail);
|
|
|
|
pEnumMediaTypes->Release();
|
|
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
if (fVideoInfoAvail) {
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// reset state if set (we don't want to force Windowless
|
|
// unless the app has set it (e.g. auto render won't set the
|
|
// state until we play)
|
|
//
|
|
hr = S_OK;
|
|
if (m_lpWLControl) {
|
|
|
|
hr = ValidateIVRWindowlessControlState();
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_lpWLControl->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
|
|
}
|
|
}
|
|
|
|
//
|
|
// if there is no lpWLControl, we set it next time
|
|
// ValidateIVRWindowlessControlState is called
|
|
//
|
|
if (SUCCEEDED(hr)) {
|
|
m_ARMode = VMR_ARMODE_LETTER_BOX;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Private*Routine******************************\
|
|
* NumInputPinsConnected
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 07/12/2001 - GlennE - Created
|
|
*
|
|
\**************************************************************************/
|
|
int CVMRFilter::NumInputPinsConnected() const
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::NumInputPinsConnected")));
|
|
int iCount = 0;
|
|
for (DWORD i = 0; i < m_dwNumPins; i++) {
|
|
if (m_pInputPins[i]->m_Connected) {
|
|
iCount++;
|
|
}
|
|
}
|
|
return iCount;
|
|
}
|
|
|
|
|
|
|
|
// IVMRDeinterlaceControl
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* VMRVideoDesc2DXVA_VideoDesc
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Thu 04/25/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
VMRVideoDesc2DXVA_VideoDesc(
|
|
DXVA_VideoDesc* lpDXVAVideoDesc,
|
|
const VMRVideoDesc* lpVMRVideoDesc
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::VMRVideoDesc2DXVA_VideoDesc")));
|
|
|
|
lpDXVAVideoDesc->Size = sizeof(DXVA_VideoDesc);
|
|
lpDXVAVideoDesc->SampleWidth = lpVMRVideoDesc->dwSampleWidth;
|
|
lpDXVAVideoDesc->SampleHeight = lpVMRVideoDesc->dwSampleHeight;
|
|
if (lpVMRVideoDesc->SingleFieldPerSample) {
|
|
lpDXVAVideoDesc->SampleFormat = DXVA_SampleFieldSingleEven;
|
|
}
|
|
else {
|
|
lpDXVAVideoDesc->SampleFormat = DXVA_SampleFieldInterleavedEvenFirst;
|
|
}
|
|
lpDXVAVideoDesc->d3dFormat = lpVMRVideoDesc->dwFourCC;
|
|
lpDXVAVideoDesc->InputSampleFreq.Numerator = lpVMRVideoDesc->InputSampleFreq.dwNumerator;
|
|
lpDXVAVideoDesc->InputSampleFreq.Denominator = lpVMRVideoDesc->InputSampleFreq.dwDenominator;
|
|
lpDXVAVideoDesc->OutputFrameFreq.Numerator = lpVMRVideoDesc->OutputFrameFreq.dwNumerator;
|
|
lpDXVAVideoDesc->OutputFrameFreq.Denominator = lpVMRVideoDesc->OutputFrameFreq.dwDenominator;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetNumberOfDeinterlaceModes
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/22/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetNumberOfDeinterlaceModes(
|
|
VMRVideoDesc* lpVideoDesc,
|
|
LPDWORD lpdwNumDeinterlaceModes,
|
|
LPGUID lpDeinterlaceModes
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetNumberOfDeinterlaceModes")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (ISBADREADPTR(lpVideoDesc)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (ISBADWRITEPTR(lpdwNumDeinterlaceModes)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
if (!m_pDeinterlace) {
|
|
return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
|
|
}
|
|
|
|
|
|
DWORD dwNumModes = MAX_DEINTERLACE_DEVICE_GUIDS;
|
|
GUID Modes[MAX_DEINTERLACE_DEVICE_GUIDS];
|
|
DXVA_VideoDesc VideoDesc;
|
|
VMRVideoDesc2DXVA_VideoDesc(&VideoDesc, lpVideoDesc);
|
|
|
|
HRESULT hr = m_pDeinterlace->QueryAvailableModes(&VideoDesc, &dwNumModes,
|
|
Modes);
|
|
if (hr == S_OK) {
|
|
|
|
if (lpDeinterlaceModes != NULL) {
|
|
dwNumModes = min(*lpdwNumDeinterlaceModes, dwNumModes);
|
|
CopyMemory(lpDeinterlaceModes, Modes, dwNumModes * sizeof(GUID));
|
|
}
|
|
}
|
|
|
|
*lpdwNumDeinterlaceModes = dwNumModes;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetDeinterlaceModeCaps
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/22/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetDeinterlaceModeCaps(
|
|
LPGUID lpDeinterlaceMode,
|
|
VMRVideoDesc* lpVideoDesc,
|
|
VMRDeinterlaceCaps* lpDeinterlaceCaps
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetDeinterlaceModeCaps")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (ISBADREADPTR(lpDeinterlaceMode)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (ISBADREADPTR(lpVideoDesc)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (ISBADWRITEPTR(lpDeinterlaceCaps)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
if (!m_pDeinterlace) {
|
|
return VFW_E_DDRAW_CAPS_NOT_SUITABLE;
|
|
}
|
|
|
|
DXVA_VideoDesc VideoDesc;
|
|
VMRVideoDesc2DXVA_VideoDesc(&VideoDesc, lpVideoDesc);
|
|
DXVA_DeinterlaceCaps DeinterlaceCaps;
|
|
|
|
HRESULT hr = m_pDeinterlace->QueryModeCaps(lpDeinterlaceMode,
|
|
&VideoDesc, &DeinterlaceCaps);
|
|
if (hr == S_OK) {
|
|
|
|
lpDeinterlaceCaps->dwNumPreviousOutputFrames =
|
|
DeinterlaceCaps.NumPreviousOutputFrames;
|
|
|
|
lpDeinterlaceCaps->dwNumForwardRefSamples =
|
|
DeinterlaceCaps.NumForwardRefSamples;
|
|
|
|
lpDeinterlaceCaps->dwNumBackwardRefSamples =
|
|
DeinterlaceCaps.NumBackwardRefSamples;
|
|
|
|
lpDeinterlaceCaps->DeinterlaceTechnology =
|
|
(VMRDeinterlaceTech)DeinterlaceCaps.DeinterlaceTechnology;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetActualDeinterlaceMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/22/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetActualDeinterlaceMode(
|
|
DWORD dwStreamID,
|
|
LPGUID lpDeinterlaceMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetActualDeinterlaceMode")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (ISBADWRITEPTR(lpDeinterlaceMode)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
*lpDeinterlaceMode = m_pInputPins[dwStreamID]->m_DeinterlaceGUID;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetDeinterlaceMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/22/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetDeinterlaceMode(
|
|
DWORD dwStreamID,
|
|
LPGUID lpDeinterlaceMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetDeinterlaceMode")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (ISBADWRITEPTR(lpDeinterlaceMode)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
if (m_pInputPins[dwStreamID]->m_DeinterlaceUserGUIDSet) {
|
|
*lpDeinterlaceMode = m_pInputPins[dwStreamID]->m_DeinterlaceUserGUID;
|
|
}
|
|
else {
|
|
*lpDeinterlaceMode = GUID_NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetDeinterlaceMode
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/22/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetDeinterlaceMode(
|
|
DWORD dwStreamID,
|
|
LPGUID lpDeinterlaceMode
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetDeinterlaceMode")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (ISBADREADPTR(lpDeinterlaceMode)) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (dwStreamID > m_dwNumPins) {
|
|
if (dwStreamID != 0xFFFFFFFF) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid stream ID")));
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
if (dwStreamID == 0xFFFFFFFF) {
|
|
for (DWORD i = 0; i < m_dwNumPins; i++) {
|
|
m_pInputPins[i]->m_DeinterlaceUserGUIDSet = TRUE;
|
|
m_pInputPins[i]->m_DeinterlaceUserGUID = *lpDeinterlaceMode;
|
|
}
|
|
}
|
|
else {
|
|
m_pInputPins[dwStreamID]->m_DeinterlaceUserGUIDSet = TRUE;
|
|
m_pInputPins[dwStreamID]->m_DeinterlaceUserGUID = *lpDeinterlaceMode;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetDeinterlacePrefs
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/22/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::GetDeinterlacePrefs(
|
|
LPDWORD lpdwDeinterlacePrefs
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::GetDeinterlacePrefs")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (ISBADWRITEPTR(lpdwDeinterlacePrefs)) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid pointer passed to GetDeinterlacePrefs")));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
*lpdwDeinterlacePrefs = m_dwDeinterlacePrefs;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* SetDeinterlacePrefs
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Mon 04/22/2002 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRFilter::SetDeinterlacePrefs(
|
|
DWORD dwDeinterlacePrefs
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRFilter::SetDeinterlacePrefs")));
|
|
CAutoLock cInterfaceLock(&m_InterfaceLock);
|
|
|
|
if (dwDeinterlacePrefs == 0 || (dwDeinterlacePrefs & ~DeinterlacePref_Mask)) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Invalid deinterlace pref specified")));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (!m_lpMixStream) {
|
|
return VFW_E_VMR_NOT_IN_MIXER_MODE;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
switch (dwDeinterlacePrefs) {
|
|
case DeinterlacePref_NextBest:
|
|
case DeinterlacePref_BOB:
|
|
case DeinterlacePref_Weave:
|
|
m_dwDeinterlacePrefs = dwDeinterlacePrefs;
|
|
break;
|
|
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|