//
// CFilterTitleOverlay.cpp
//
#include
// 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 // performance measurement (MSR_)
#include
#if (1100 > _MSC_VER)
#include
#else
#include
#endif
#include "CFilterTitleOverlay.h"
#include "CTitleOverlayProp.h"
#include "CSysTimeOverlayController.h"
#include "CScrollController.h"
//唯一标识符
// {E3FB4BFE-8E5C-4aec-8162-7DA55BE486A1}
DEFINE_GUID(CLSID_HQTitleOverlay,
0xe3fb4bfe, 0x8e5c, 0x4aec, 0x81, 0x62, 0x7d, 0xa5, 0x5b, 0xe4, 0x86, 0xa1);
// {E70FE57A-19AA-4a4c-B39A-408D49D73851}
DEFINE_GUID(CLSID_HQTitleOverlayProp,
0xe70fe57a, 0x19aa, 0x4a4c, 0xb3, 0x9a, 0x40, 0x8d, 0x49, 0xd7, 0x38, 0x51);
//
// 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"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_HQTitleOverlay, // Filter CLSID
L"HQ Title Overlay Std.", // Filter name
MERIT_DO_NOT_USE, // Its merit
2, // 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
//注意g_Templates名称是固定的
CFactoryTemplate g_Templates[] =
{
{
L"HQ Title Overlay Std.",
&CLSID_HQTitleOverlay,
CFilterTitleOverlay::CreateInstance,
NULL,
&sudFilter
},
{
L"HQ Title Overlay Property Page",
&CLSID_HQTitleOverlayProp,
CTitleOverlayProp::CreateInstance
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
// ----------------------------------------------------------------------------
// Filter implementation
// ----------------------------------------------------------------------------
CFilterTitleOverlay::CFilterTitleOverlay(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) :
CTransInPlaceFilter(tszName, punk, CLSID_HQTitleOverlay, phr)
{
mOverlayType = OT_STATIC;
mOverlayController = new COverlayController();
mNeedEstimateFrameRate = FALSE;
char szTitle[] = "Hello, DirectShow!";
put_Title(szTitle, sizeof(szTitle));
}
CFilterTitleOverlay::~CFilterTitleOverlay()
{
ReleaseOverlayController();
}
void CFilterTitleOverlay::ReleaseOverlayController(void)
{
if (mOverlayController)
{
delete mOverlayController;
mOverlayController = NULL;
}
}
//
// CreateInstance
//
// Override CClassFactory method.
// Provide the way for COM to create a CNullInPlace object
//
//创建
CUnknown * WINAPI CFilterTitleOverlay::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
#if 1
//防伪??!!
char szCreatorPath[256], szCreatorName[256];
::strcpy(szCreatorPath, "");
::strcpy(szCreatorName, "");
HMODULE hModule = ::GetModuleHandle(NULL);
::GetModuleFileName(hModule, szCreatorPath, 256);
char * backSlash = ::strrchr(szCreatorPath, '\\');
if (backSlash)
{
strcpy(szCreatorName, backSlash);
}
::_strlwr(szCreatorName);
// Please specify your app name with lowercase
// 检查调用该Filter的程序
// 一开始调试不了,就卡在这了 = =
if (::strstr(szCreatorName, "graphedit") == NULL &&
::strstr(szCreatorName, "ourapp") == NULL)
{
*phr = E_FAIL;
return NULL;
}
#endif
//通过New对象的方法
CFilterTitleOverlay *pNewObject = new CFilterTitleOverlay(NAME("TitleOverlay"), punk, phr);
if (pNewObject == NULL)
{
*phr = E_OUTOFMEMORY;
}
return pNewObject;
}
//
// Basic COM - used here to reveal our own interfaces
//暴露接口,使外部程序可以QueryInterface,关键!
STDMETHODIMP CFilterTitleOverlay::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
CheckPointer(ppv, E_POINTER);
//根据不同的REFIID,获得不同的接口指针
if (riid == IID_ISpecifyPropertyPages)
{
return GetInterface((ISpecifyPropertyPages *) this, ppv);
}
else if (riid == IID_ITitleOverlay)
{
return GetInterface((ITitleOverlay *) this, ppv);
}
else
{
//不是以上的REFIID的话,调用父类的
return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
}
} // NonDelegatingQueryInterface
// Only RGB 32/24/565/555 supported
HRESULT CFilterTitleOverlay::CheckInputType(const CMediaType* mtIn)
{
// Dynamic format change will never be allowed!
if (IsStopped() && *mtIn->Type() == MEDIATYPE_Video)
{
if (*mtIn->Subtype() == MEDIASUBTYPE_RGB32 ||
*mtIn->Subtype() == MEDIASUBTYPE_RGB24 ||
*mtIn->Subtype() == MEDIASUBTYPE_RGB555 ||
*mtIn->Subtype() == MEDIASUBTYPE_RGB565)
{
return NOERROR;
}
}
return E_INVALIDARG;
}
HRESULT CFilterTitleOverlay::Transform(IMediaSample *pSample)
{
// If we cann't read frame rate info from input pin's connection media type,
// We estimate it from the first sample's time stamp!
if (mNeedEstimateFrameRate)
{
mNeedEstimateFrameRate = FALSE;
REFERENCE_TIME startTime = 0;
REFERENCE_TIME endTime = 0;
double estimated = 25;
if (SUCCEEDED(pSample->GetTime(&startTime, &endTime)))
{
estimated = 1.0 * UNITS / (endTime - startTime);
}
mOverlayController->SetEstimatedFrameRate(estimated);
}
if (mOverlayType != OT_NONE)
{
//PBYTE是unsigned char
PBYTE pData = NULL;
//获取IMediaSample中的数据
pSample->GetPointer(&pData);
//叠加
mOverlayController->DoTitleOverlay(pData);
}
return NOERROR;
}
HRESULT CFilterTitleOverlay::SetInputVideoInfoToController(void)
{
if (mOverlayController && m_pInput && m_pInput->IsConnected())
{
//当前MEdiaType
CMediaType mt = m_pInput->CurrentMediaType();
if (mt.formattype != FORMAT_VideoInfo)
{
return E_FAIL;
}
RGB_FORMAT colorSpace = FT_NONE;
if (mt.subtype == MEDIASUBTYPE_RGB32) // Determine RGB format
{
colorSpace = FT_RGB32;
}
else if (mt.subtype == MEDIASUBTYPE_RGB24)
{
colorSpace = FT_RGB24;
}
else if (mt.subtype == MEDIASUBTYPE_RGB555)
{
colorSpace = FT_RGB555;
}
else if (mt.subtype == MEDIASUBTYPE_RGB565)
{
colorSpace = FT_RGB565;
}
else if (mt.subtype == MEDIASUBTYPE_RGB8)
{
colorSpace = FT_RGB8;
}
mOverlayController->SetInputColorSpace(colorSpace);
VIDEOINFOHEADER * pHeader = (VIDEOINFOHEADER *) mt.pbFormat;
mNeedEstimateFrameRate = pHeader->AvgTimePerFrame > 0 ? FALSE : TRUE;
mOverlayController->SetInputVideoInfo(pHeader);
return NOERROR;
}
return E_FAIL;
}
HRESULT CFilterTitleOverlay::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
{
HRESUL