⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filtervideokeyer.cpp

📁 最近在学习directshow, Directshow实务精选的源代码
💻 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 + -