应用程序可能需要在过滤器图表中找到特定的过滤器,或者甚至需要在过滤器上定位特定的过滤器。例如,它可能使用特定过滤器暴露的接口, 或者它可能会构建专门的过滤器图形,并需要调用各个引脚上的方法来连接过滤器。为此,DirectShow提供了几种枚举过滤器图形中对象的方法。
Enumerating Filters
Filter Graph Manager支持IFilterGraph :: EnumFilters方法,枚举过滤器图中的所有过滤器。 它返回一个指向IEnumFilters接口的指针。 IEnumFilters :: Next方法检索IBaseFilter接口指针。
以下示例显示了枚举图中的过滤器并显示每个过滤器名称的消息框的函数。 它使用IBaseFilter :: QueryFilterInfo方法来检索过滤器的名称。 请注意函数在接口上调用Release以减少引用计数的位置。
HRESULT EnumFilters (IFilterGraph *pGraph)
{
IEnumFilters *pEnum = NULL;
IBaseFilter *pFilter;
ULONG cFetched;
HRESULT hr = pGraph->EnumFilters(&pEnum);
if (FAILED(hr)) return hr;
while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
{
FILTER_INFO FilterInfo;
hr = pFilter->QueryFilterInfo(&FilterInfo);
if (FAILED(hr))
{
MessageBox(NULL, TEXT("Could not get the filter info"),
TEXT("Error"), MB_OK | MB_ICONERROR);
continue; // Maybe the next one will work.
}
#ifdef UNICODE
MessageBox(NULL, FilterInfo.achName, TEXT("Filter Name"), MB_OK);
#else
char szName[MAX_FILTER_NAME];
int cch = WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName,
MAX_FILTER_NAME, szName, MAX_FILTER_NAME, 0, 0);
if (cch > 0)
MessageBox(NULL, szName, TEXT("Filter Name"), MB_OK);
#endif
// The FILTER_INFO structure holds a pointer to the Filter Graph
// Manager, with a reference count that must be released.
if (FilterInfo.pGraph != NULL)
{
FilterInfo.pGraph->Release();
}
pFilter->Release();
}
pEnum->Release();
return S_OK;
}
Enumerating Pins
过滤器支持IBaseFilter :: EnumPins方法,枚举过滤器上可用的引脚。 它返回一个指向IEnumPins接口的指针。 IEnumPins :: Next方法检索IPin接口指针。
以下示例显示了一个函数,该函数在给定滤波器上定位具有给定方向(输入或输出)的引脚。 它使用PIN_DIRECTION枚举来指定引脚方向,并使用IPin :: QueryDirection方法来查找每个枚举引脚的方向。 如果这个函数找到一个匹配的引脚,它将返回一个IPin接口指针,其中引用计数为未完成。 调用者负责释放界面。
HRESULT GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
{
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
HRESULT hr;
if (ppPin == NULL)
{
return E_POINTER;
}
hr = pFilter->EnumPins(&pEnum);
if (FAILED(hr))
{
return hr;
}
while(pEnum->Next(1, &pPin, 0) == S_OK)
{
PIN_DIRECTION PinDirThis;
hr = pPin->QueryDirection(&PinDirThis);
if (FAILED(hr))
{
pPin->Release();
pEnum->Release();
return hr;
}
if (PinDir == PinDirThis)
{
// Found a match. Return the IPin pointer to the caller.
*ppPin = pPin;
pEnum->Release();
return S_OK;
}
// Release the pin for the next time through the loop.
pPin->Release();
}
// No more pins. We did not find a match.
pEnum->Release();
return E_FAIL;
}
Enmerating Media Types
引脚支持IPin :: EnumMediaTypes方法,枚举引脚的首选媒体类型。 它返回一个指向IEnumMediaTypes接口的指针。 IEnumMediaTypes :: Next方法检索指向描述媒体类型的AM_MEDIA_TYPE结构的指针。
媒体类型枚举器主要用于帮助Filter Graph Manager进行智能连接,并且您的应用程序可能不会使用它。 引脚不一定会返回任何首选的媒体类型。 而且,它返回的媒体类型可能取决于过滤器的连接状态。 例如,根据为过滤器的输入引脚设置哪种介质类型,过滤器的输出引脚可能会返回一组不同的介质类型。
以下示例查找与指定的主要类型,子类型或格式类型匹配的首选媒体类型。
/ Given a pin, find a preferred media type
//
// pPin Pointer to the pin.
// majorType Preferred major type (GUID_NULL = don't care).
// subType Preferred subtype (GUID_NULL = don't care).
// formatType Preferred format type (GUID_NULL = don't care).
// ppmt Receives a pointer to the media type. Can be NULL.
//
// Note: If you want to check whether a pin supports a desired media type,
// but do not need the format details, set ppmt to NULL.
//
// If ppmt is not NULL and the method succeeds, the caller must
// delete the media type, including the format block.
HRESULT GetPinMediaType(
IPin *pPin, // pointer to the pin
REFGUID majorType, // desired major type, or GUID_NULL = don't care
REFGUID subType, // desired subtype, or GUID_NULL = don't care
REFGUID formatType, // desired format type, of GUID_NULL = don't care
AM_MEDIA_TYPE **ppmt // Receives a pointer to the media type. (Can be NULL)
)
{
*ppmt = NULL;
IEnumMediaTypes *pEnum = NULL;
AM_MEDIA_TYPE *pmt = NULL;
BOOL bFound = FALSE;
HRESULT hr = pPin->EnumMediaTypes(&pEnum);
if (FAILED(hr))
{
return hr;
}
while (hr = pEnum->Next(1, &pmt, NULL), hr == S_OK)
{
if ((majorType == GUID_NULL) || (majorType == pmt->majortype))
{
if ((subType == GUID_NULL) || (subType == pmt->subtype))
{
if ((formatType == GUID_NULL) ||
(formatType == pmt->formattype))
{
// Found a match.
if (ppmt)
{
*ppmt = pmt; // Return it to the caller
}
else
{
_DeleteMediaType(pmt);
}
bFound = TRUE;
break;
}
}
}
_DeleteMediaType(pmt);
}
SafeRelease(&pEnum);
if (SUCCEEDED(hr))
{
if (!bFound)
{
hr = VFW_E_NOT_FOUND;
}
}
return hr;
}
参考:
https://www.yuque.com/docs/share/9656d65c-4f49-49a1-ba9e-3019c2cecf1a