in TTDQueries/app-sample/dshowutil.h [880:1001]
inline HRESULT IsRenderer(IBaseFilter *pFilter, BOOL *pResult)
{
if (pFilter == NULL || pResult == NULL)
{
return E_POINTER;
}
HRESULT hr = S_OK;
BOOL bIsRenderer = FALSE;
IAMFilterMiscFlags *pFlags = NULL;
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
// First try IAMFilterMiscFlags.
hr = pFilter->QueryInterface(IID_IAMFilterMiscFlags, (void**)&pFlags);
if (SUCCEEDED(hr))
{
ULONG flags = pFlags->GetMiscFlags();
if (flags & AM_FILTER_MISC_FLAGS_IS_RENDERER)
{
bIsRenderer = TRUE;
}
}
if (!bIsRenderer)
{
// Look for the following conditions:
// 1) Zero output pins AND at least 1 unmapped input pin
// - or -
// 2) At least 1 rendered input pin.
// definitions:
// unmapped input pin = IPin::QueryInternalConnections returns E_NOTIMPL
// rendered input pin = IPin::QueryInternalConnections returns "0" slots
// These cases are somewhat obscure and probably don't apply to many filters
// that actually exist.
hr = pFilter->EnumPins(&pEnum);
if (SUCCEEDED(hr))
{
bool bFoundRenderedInputPin = false;
bool bFoundUnmappedInputPin = false;
bool bFoundOuputPin = false;
while (pEnum->Next(1, &pPin, NULL) == S_OK)
{
BOOL bIsOutput = FALSE;
hr = IsPinDirection(pPin, PINDIR_OUTPUT, &bIsOutput);
if (FAILED(hr))
{
break;
}
else if (bIsOutput)
{
// This is an output pin.
bFoundOuputPin = true;
}
else
{
// It's an input pin. Is it mapped to an output pin?
ULONG nPin = 0;
hr = pPin->QueryInternalConnections(NULL, &nPin);
if (hr == S_OK)
{
// The count (nPin) was zero, and the method returned S_OK, so
// this input pin is mapped to exactly zero ouput pins.
// Therefore, it is a rendered input pin.
bFoundRenderedInputPin = true;
// We have met condition (2) above, so we can stop looking.
break;
// Note: S_FALSE here means "the count (nPin) was not large
// enough", ie, this pin is mapped to one or more output pins.
}
else if (hr == E_NOTIMPL)
{
// This pin is not mapped to any particular output pin.
bFoundUnmappedInputPin = true;
hr = S_OK;
}
else if (FAILED(hr))
{
// Unexpected error
break;
}
}
pPin->Release(); // Release for the next loop.
} // while
if (bFoundRenderedInputPin)
{
bIsRenderer = TRUE; // condition (1) above
}
else if (bFoundUnmappedInputPin && !bFoundOuputPin)
{
bIsRenderer = TRUE; // condition (2) above
}
else
{
hr = S_FALSE;
}
}
}
if (SUCCEEDED(hr))
{
*pResult = bIsRenderer;
}
SAFE_RELEASE(pFlags);
SAFE_RELEASE(pEnum);
SAFE_RELEASE(pPin);
return hr;
}