📄 filtervideokeyer.cpp
字号:
//
// CFilterVideoKeyer.cpp
//
/*-----------------------------------------------------*\
HQ Tech, Make Technology Easy!
More information, please go to http://hqtech.nease.net.
/*-----------------------------------------------------*/
#include <streams.h> // quartz, includes windows
// Eliminate two expected level 4 warnings from the Microsoft compiler.
// The class does not have an assignment or copy operator, and so cannot
// be passed by value. This is normal. This file compiles clean at the
// highest (most picky) warning level (-W4).
#pragma warning(disable: 4511 4512)
#include <measure.h> // performance measurement (MSR_)
#include <initguid.h>
#if (1100 > _MSC_VER)
#include <olectlid.h>
#else
#include <olectl.h>
#endif
#include "VideoKeyerDefs.h"
#include "FilterVideoKeyer.h"
#include "CBranchInputPin.h"
//
// setup data
//
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
&MEDIATYPE_NULL, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
const AMOVIESETUP_PIN psudPins[] =
{
{
L"Input", // String pin name
FALSE, // Is it rendered
FALSE, // Is it an output
FALSE, // Allowed none
FALSE, // Allowed many
&CLSID_NULL, // Connects to filter
L"Output", // Connects to pin
1, // Number of types
&sudPinTypes }, // The pin details
{
L"Mixing", // String pin name
FALSE, // Is it rendered
FALSE, // Is it an output
FALSE, // Allowed none
FALSE, // Allowed many
&CLSID_NULL, // Connects to filter
L"Output", // Connects to pin
1, // Number of types
&sudPinTypes }, // The pin details
{ L"Output", // String pin name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Allowed none
FALSE, // Allowed many
&CLSID_NULL, // Connects to filter
L"Input", // Connects to pin
1, // Number of types
&sudPinTypes // The pin details
}
};
const AMOVIESETUP_FILTER sudFilter =
{
&CLSID_VideoKeyer, // Filter CLSID
L"HQ Video Keyer", // Filter name
MERIT_DO_NOT_USE, // Its merit
3, // Number of pins
psudPins // Pin details
};
// List of class IDs and creator functions for the class factory. This
// provides the link between the OLE entry point in the DLL and an object
// being created. The class factory will call the static CreateInstance
CFactoryTemplate g_Templates[] =
{
{
L"HQ Video Keyer",
&CLSID_VideoKeyer,
CFilterVideoKeyer::CreateInstance,
NULL,
&sudFilter
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
// ----------------------------------------------------------------------------
// Filter implementation
// ----------------------------------------------------------------------------
CFilterVideoKeyer::CFilterVideoKeyer(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) :
CTransInPlaceFilter(tszName, punk, CLSID_VideoKeyer, phr)
{
mMixingInput = new CBranchInputPin(this, phr, L"Mixing In");
}
CFilterVideoKeyer::~CFilterVideoKeyer()
{
delete mMixingInput;
}
//
// CreateInstance
//
// Override CClassFactory method.
// Provide the way for COM to create a filter object
//
CUnknown * WINAPI CFilterVideoKeyer::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
CFilterVideoKeyer *pNewObject = new CFilterVideoKeyer(NAME("Video_Keyer"), punk, phr);
if (pNewObject == NULL)
{
*phr = E_OUTOFMEMORY;
}
return pNewObject;
}
//
// Basic COM - used here to reveal our own interfaces
STDMETHODIMP CFilterVideoKeyer::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
CheckPointer(ppv, E_POINTER);
if (riid == IID_IVideoKeyer)
{
return GetInterface((IVideoKeyer *) this, ppv);
}
else
{
return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
}
}
int CFilterVideoKeyer::GetPinCount()
{
return 3;
}
CBasePin * CFilterVideoKeyer::GetPin(int n)
{
switch (n)
{
case 0:
return CTransInPlaceFilter::GetPin(0);
case 1:
return CTransInPlaceFilter::GetPin(1);
case 2:
return mMixingInput;
}
return NULL;
}
STDMETHODIMP CFilterVideoKeyer::FindPin(LPCWSTR Id, IPin ** ppPin)
{
CheckPointer(ppPin,E_POINTER);
ValidateReadWritePtr(ppPin,sizeof(IPin *));
// Pin IDs of L"In" and L"Out" are specified in CTransformXXPin::QueryId.
if (0 == lstrcmpW(Id, L"In"))
{
*ppPin = GetPin(0);
}
else if (0 == lstrcmpW(Id, L"Out"))
{
*ppPin = GetPin(1);
}
else if (0 == lstrcmpW(Id, L"Mixing In"))
{
*ppPin = GetPin(2);
}
else
{
*ppPin = NULL;
return VFW_E_NOT_FOUND;
}
HRESULT hr = NOERROR;
// AddRef() returned pointer - but GetPin could fail if memory is low.
if (*ppPin)
{
(*ppPin)->AddRef();
}
else
{
hr = E_OUTOFMEMORY; // probably. There's no pin anyway.
}
return hr;
}
HRESULT CFilterVideoKeyer::CheckInputType(const CMediaType* mtIn)
{
// Dynamic format change will never be allowed!
if (!IsStopped())
{
return E_FAIL;
}
if (!IsSupportedRGB(mtIn))
{
return E_FAIL;
}
return NOERROR;
}
BOOL CFilterVideoKeyer::IsSupportedRGB(const CMediaType* mtIn)
{
if (mtIn->majortype == MEDIATYPE_Video &&
mtIn->formattype == FORMAT_VideoInfo)
{
if (mtIn->subtype == MEDIASUBTYPE_RGB565 ||
mtIn->subtype == MEDIASUBTYPE_RGB32)
{
return TRUE;
}
}
return FALSE;
}
HRESULT CFilterVideoKeyer::CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin)
{
HRESULT hr = CTransInPlaceFilter::CompleteConnect(direction, pReceivePin);
if (SUCCEEDED(hr) && direction == PINDIR_INPUT)
{
CMediaType mt = m_pInput->CurrentMediaType();
mController.SetInputVideoInfo((VIDEOINFOHEADER *)mt.Format());
}
return NOERROR;
}
HRESULT CFilterVideoKeyer::Transform(IMediaSample *pSample)
{
if (mMixingInput->IsConnected())
{
mController.DoMixing(pSample);
}
return NOERROR;
}
// override these so that the derived filter can catch them
STDMETHODIMP CFilterVideoKeyer::Stop()
{
CAutoLock lck1(&m_csFilter);
if(m_State == State_Stopped) {
return NOERROR;
}
// Succeed the Stop if we are not completely connected
ASSERT(m_pInput == NULL || m_pOutput != NULL);
if(m_pInput == NULL || m_pInput->IsConnected() == FALSE ||
m_pOutput->IsConnected() == FALSE) {
m_State = State_Stopped;
m_bEOSDelivered = FALSE;
return NOERROR;
}
ASSERT(m_pInput);
ASSERT(m_pOutput);
mController.Stop(); // Make non-blocking
mMixingInput->Inactive();
// decommit the input pin before locking or we can deadlock
m_pInput->Inactive();
// synchronize with Receive calls
CAutoLock lck2(&m_csReceive);
m_pOutput->Inactive();
// allow a class derived from CTransformFilter
// to know about starting and stopping streaming
HRESULT hr = StopStreaming();
if(SUCCEEDED(hr)) {
// complete the state transition
m_State = State_Stopped;
m_bEOSDelivered = FALSE;
}
return hr;
}
HRESULT CFilterVideoKeyer::StartStreaming()
{
mController.Start();
return NOERROR;
}
HRESULT CFilterVideoKeyer::EndOfStream(void)
{
mController.MainVideoEndOfStream();
return CTransInPlaceFilter::EndOfStream();
}
// --- IVideoKeyer methods ---
STDMETHODIMP CFilterVideoKeyer::get_ConnectedMediaType(CMediaType * outMainType,
CMediaType * outMixingType)
{
HRESULT hr = S_OK;
if (outMainType)
{
// Check main input pin connection
if (m_pInput && m_pInput->IsConnected())
{
*outMainType = m_pInput->CurrentMediaType();
}
else
{
hr = E_FAIL;
}
}
if (SUCCEEDED(hr) && outMixingType)
{
// Check mixing input pin connection
if (mMixingInput && mMixingInput->IsConnected())
{
*outMixingType = mMixingInput->CurrentMediaType();
}
else
{
hr = E_FAIL;
}
}
return hr;
}
// Only when filter is in stopped state, we can set some params.
STDMETHODIMP CFilterVideoKeyer::put_DetectType(DETECT_TYPE inType)
{
if (m_State == State_Stopped)
{
mController.SetDetectType(inType);
return NOERROR;
}
return E_FAIL;
}
STDMETHODIMP CFilterVideoKeyer::get_DetectType(DETECT_TYPE * outType)
{
mController.GetDetectType(outType);
return NOERROR;
}
STDMETHODIMP CFilterVideoKeyer::put_BackgroundColor(BYTE inRed,
BYTE inGreen,
BYTE inBlue)
{
if (m_State == State_Stopped)
{
mController.SetBackgroundColor(inRed, inGreen, inBlue);
return NOERROR;
}
return E_FAIL;
}
STDMETHODIMP CFilterVideoKeyer::get_BackgroundColor(BYTE * outRed,
BYTE * outGreen,
BYTE * outBlue)
{
mController.GetBackgroundColor(outRed, outGreen, outBlue);
return NOERROR;
}
/******************************Public Routine******************************\
* exported entry points for registration and
* unregistration (in this case they only call
* through to default implmentations).
*
*
*
* History:
*
\**************************************************************************/
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
}
// Microsoft C Compiler will give hundreds of warnings about
// unused inline functions in header files. Try to disable them.
#pragma warning( disable:4514)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -