DirectShow Utility
DirectShow 工具類,誰用誰知道!
#ifndef DSUtility_H
#define DSUtility_H
//////////////////////////////////////////////////////////////////////////
#include <DShow.h>
#include <DMODShow.h>
#include <ATLColl.h>
//////////////////////////////////////////////////////////////////////////
#include "COMUtility.h"
//////////////////////////////////////////////////////////////////////////
typedef CAtlList<IBaseFilter *> CFilterList;
//////////////////////////////////////////////////////////////////////////
template <DWORD dwUnique>
class DSUtilityT
{
typedef DSUtilityT<dwUnique> This;
public:
static HRESULT AddFilter(IGraphBuilder *pGraph, REFCLSID clsidDMO, REFCLSID clsidCat, LPCWSTR pwszName,
IBaseFilter **ppBaseFilter)
{
if (pGraph == NULL || ppBaseFilter == NULL || pwszName == NULL) {
return E_POINTER;
}
*ppBaseFilter = NULL;
HRESULT hr = S_OK;
{
CComQIPtr<IBaseFilter> pBaseFilter;
CComQIPtr<IDMOWrapperFilter> pDMOWrapper;
hr = pBaseFilter.CoCreateInstance(CLSID_DMOWrapperFilter);
if (FAILED(hr)) {
goto Exit;
}
pDMOWrapper = pBaseFilter;
if (pDMOWrapper == NULL) {
hr = E_FAIL;
goto Exit;
}
hr = pDMOWrapper->Init(clsidDMO, clsidCat);
if (FAILED(hr)) {
goto Exit;
}
if (SUCCEEDED(pGraph->AddFilter(pBaseFilter, pwszName))) {
*ppBaseFilter = pBaseFilter.Detach();
}
}
Exit:
return hr;
}
static HRESULT AddFilter(IGraphBuilder *pGraph, REFCLSID clsid, LPCWSTR pwszName, IBaseFilter
**ppBaseFilter, LPCWSTR lpszPath)
{
if (pGraph == NULL || ppBaseFilter == NULL || pwszName == NULL || lpszPath == NULL) {
return E_POINTER;
}
*ppBaseFilter = NULL;
HRESULT hr = S_OK;
{
CComPtr<IUnknown> pUnknown;
hr = COMUtility::CreateObjectFromPath(clsid, &pUnknown, lpszPath);
if (FAILED(hr)) {
goto Exit;
}
CComQIPtr<IBaseFilter> pBaseFilter(pUnknown);
if (SUCCEEDED(pGraph->AddFilter(pBaseFilter, pwszName))) {
*ppBaseFilter = pBaseFilter.Detach();
}
}
Exit:
return hr;
}
static HRESULT AddFilter(IGraphBuilder *pGraph, REFCLSID clsid, LPCWSTR pwszName, IBaseFilter
**ppBaseFilter)
{
if (pGraph == NULL || ppBaseFilter == NULL || pwszName == NULL) {
return E_POINTER;
}
*ppBaseFilter = NULL;
CComPtr<IBaseFilter> pBaseFilter;
HRESULT hr = pBaseFilter.CoCreateInstance(clsid);
if (FAILED(hr)) {
return hr;
}
if (SUCCEEDED(pGraph->AddFilter(pBaseFilter, pwszName))) {
*ppBaseFilter = pBaseFilter.Detach();
}
pBaseFilter.Release();
return S_OK;
}
template <class EnumeratorT>
static HRESULT EnumFilter(IGraphBuilder *pGraph, EnumeratorT &enumerator, DWORD dwContext)
{
if (pGraph == NULL) {
return E_POINTER;
}
CComPtr<IEnumFilters> pEnumFilters;
if (FAILED(pGraph->EnumFilters(&pEnumFilters))) {
return E_FAIL;
}
CComPtr<IBaseFilter> pBaseFilter;
while (pEnumFilters->Next(1, &pBaseFilter, 0) == S_OK) {
if (!enumerator(pBaseFilter, dwContext)) {
break;
}
pBaseFilter.Release();
}
return S_OK;
}
template <class EnumeratorT>
static HRESULT EnumPin(IBaseFilter *pBaseFilter, EnumeratorT &enumerator, DWORD dwContext)
{
if (pBaseFilter == NULL) {
return E_POINTER;
}
CComPtr<IEnumPins> pEnumPins;
if (FAILED(pBaseFilter->EnumPins(&pEnumPins))) {
return E_FAIL;
}
CComPtr<IPin> pPin;
while (pEnumPins->Next(1, &pPin, 0) == S_OK) {
if (!enumerator(pPin, dwContext)) {
break;
}
pPin.Release();
}
return S_OK;
}
//////////////////////////////////////////////////////////////////////////
struct stGetUnconnectedPin
{
stGetUnconnectedPin()
: pPinDest(NULL),
pinDirDest(PINDIR_INPUT)
{
}
BOOL operator() (IPin *pPin, DWORD dwContext)
{
PIN_DIRECTION pinDir;
if (pPin == NULL || FAILED(pPin->QueryDirection(&pinDir)) || pinDir != pinDirDest) {
return TRUE;
}
CComPtr<IPin> pConnectedTo;
if (SUCCEEDED(pPin->ConnectedTo(&pConnectedTo))) {
return TRUE;
}
pPinDest = pPin;
pPinDest->AddRef();
return FALSE;
}
PIN_DIRECTION pinDirDest;
IPin *pPinDest;
};
static HRESULT GetUnconnectedPin(IBaseFilter *pFilter, PIN_DIRECTION pinDir, IPin **ppPin)
{
if (pFilter == NULL || ppPin == NULL) {
return E_POINTER;
}
*ppPin = NULL;
stGetUnconnectedPin getUnconnectedPin;
getUnconnectedPin.pPinDest = NULL;
getUnconnectedPin.pinDirDest= pinDir;
HRESULT hr = This::EnumPin(pFilter, getUnconnectedPin, 0);
*ppPin = getUnconnectedPin.pPinDest;
return hr;
}
//////////////////////////////////////////////////////////////////////////
struct stGetCapturePin
{
stGetCapturePin()
: pPinDest(NULL)
{
}
BOOL operator() (IPin *pPin, DWORD dwContext)
{
CComQIPtr<IKsPropertySet> pPropertySet(pPin);
if (pPropertySet == NULL) {
return TRUE;
}
GUID guidPropID;
DWORD dwReturn = 0;
if (FAILED(pPropertySet->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0,
&guidPropID, sizeof(guidPropID), &dwReturn))) {
return TRUE;
}
if (guidPropID == PIN_CATEGORY_CAPTURE) {
pPinDest = pPin;
pPinDest->AddRef();
return FALSE;
}
return TRUE;
}
IPin *pPinDest;
};
static HRESULT GetCapturePin(IBaseFilter *pFilter, IPin **ppPin)
{
if (pFilter == NULL || ppPin == NULL) {
return E_POINTER;
}
*ppPin = NULL;
stGetCapturePin getCapturePin;
getCapturePin.pPinDest = NULL;
HRESULT hr = This::EnumPin(pFilter, getCapturePin, 0);
*ppPin = getCapturePin.pPinDest;
return hr;
}
//////////////////////////////////////////////////////////////////////////
struct stGetPinCount
{
stGetPinCount()
: lpInputPinCount(NULL),
lpOutputPinCount(NULL)
{
}
BOOL operator() (IPin *pPin, DWORD dwContext)
{
PIN_DIRECTION pinDir = PINDIR_INPUT;
if (pPin == NULL || FAILED(pPin->QueryDirection(&pinDir))) {
return TRUE;
}
switch (pinDir) {
case PINDIR_INPUT:
if (lpInputPinCount != NULL) {
++(*lpInputPinCount);
}
break;
case PINDIR_OUTPUT:
if (lpOutputPinCount != NULL) {
++(*lpOutputPinCount);
}
break;
}
return FALSE;
}
LPDWORD lpInputPinCount;
LPDWORD lpOutputPinCount;
};
static HRESULT GetPinCount(IBaseFilter *pFilter, LPDWORD lpInputPinCount, LPDWORD lpOutputPinCount)
{
if (pFilter == NULL || (lpInputPinCount == NULL && lpOutputPinCount == NULL)) {
return E_POINTER;
}
if (lpInputPinCount != NULL) {
*lpInputPinCount = 0;
}
if (lpOutputPinCount != NULL) {
*lpOutputPinCount = 0;
}
stGetPinCount getPinCount;
getPinCount.lpInputPinCount = lpInputPinCount;
getPinCount.lpOutputPinCount= lpOutputPinCount;
return This::EnumPin(pFilter, getPinCount, 0);
}
//////////////////////////////////////////////////////////////////////////
struct stGetPin
{
stGetPin()
: pPinDest(NULL),
pinDirDest(PINDIR_INPUT),
pszPartialName(NULL)
{
}
BOOL operator() (IPin *pPin, DWORD dwContext)
{
PIN_INFO pinInfo = { 0 };
if (pPin == NULL || FAILED(pPin->QueryPinInfo(&pinInfo))) {
return TRUE;
}
if (pinInfo.dir == pinDirDest) {
// Ignore the pin name
if (pszPartialName == NULL) {
pPinDest = pPin;
}
else {
CHAR szPinName[128] = { 0 };
::WideCharToMultiByte(CP_ACP, 0, pinInfo.achName, -1, szPinName,
sizeof(szPinName), NULL, NULL);
if (::StrStr(szPinName, pszPartialName)) {
pPinDest = pPin;
}
}
}
pinInfo.pFilter->Release();
if (pPinDest != NULL) {
pPinDest->AddRef();
}
return FALSE;
}
IPin *pPinDest;
LPCTSTR pszPartialName;
PIN_DIRECTION pinDirDest;
};
static HRESULT GetPin(IPin **ppPin, IBaseFilter *pFilter, PIN_DIRECTION pinDir, LPCTSTR pszPartialName)
{
if (pFilter == NULL || ppPin == NULL) {
return E_POINTER;
}
stGetPin getPin;
getPin.pPinDest = NULL;
getPin.pinDirDest = pinDir;
HRESULT hr = This::EnumPin(pFilter, getPin, 0);
*ppPin = getPin.pPinDest;
return hr;
}
//////////////////////////////////////////////////////////////////////////
struct stCompletelyConnected
{
stCompletelyConnected()
: bAllConnected(TRUE)
{
}
BOOL operator() (IPin *pPin, DWORD dwContext)
{
if (pPin == NULL) {
return TRUE;
}
CComPtr<IPin> pConnectedTo;
if (FAILED(pPin->ConnectedTo(&pConnectedTo))) {
bAllConnected = FALSE;
}
return bAllConnected ? TRUE : FALSE;
}
BOOL bAllConnected;
};
static HRESULT CompletelyConnected(IBaseFilter *pFilter, LPBOOL lpCompletelyConnected)
{
if (pFilter == NULL || lpCompletelyConnected == NULL) {
return E_POINTER;
}
stCompletelyConnected completelyConnected;
HRESULT hr = This::EnumPin(pFilter, completelyConnected, 0);
*lpCompletelyConnected = completelyConnected.bAllConnected;
return hr;
}
//////////////////////////////////////////////////////////////////////////
static HRESULT ConnectFilters(IGraphBuilder *pGraph, IPin *pPinOutput, IBaseFilter *pFilterInput)
{
if (pGraph == NULL || pPinOutput == NULL || pFilterInput == NULL) {
return E_POINTER;
}
PIN_DIRECTION pinDir;
pPinOutput->QueryDirection(&pinDir);
if (pinDir != PINDIR_OUTPUT) {
return E_INVALIDARG;
}
CComPtr<IPin> pPinInput;
HRESULT hr = GetUnconnectedPin(pFilterInput, PINDIR_INPUT, &pPinInput);
if (FAILED(hr)) {
return hr;
}
return pGraph->Connect(pPinOutput, pPinInput);
}
static HRESULT ConnectFilters(IGraphBuilder *pGraph, IBaseFilter *pFilterOutput, IBaseFilter
*pFilterInput)
{
if (pGraph == NULL || pFilterOutput == NULL || pFilterInput == NULL) {
return E_POINTER;
}
CComPtr<IPin> pPinOutput;
HRESULT hr = This::GetUnconnectedPin(pFilterOutput, PINDIR_OUTPUT, &pPinOutput);
if (FAILED(hr)) {
return hr;
}
return This::ConnectFilters(pGraph, pPinOutput, pFilterInput);
}
//////////////////////////////////////////////////////////////////////////
static HRESULT GetNextFilter(IBaseFilter *pFilter, PIN_DIRECTION pinDirDest, IBaseFilter
**ppFilterNext)
{
if (pFilter == NULL || ppFilterNext == NULL) {
return E_POINTER;
}
*ppFilterNext = NULL;
CComPtr<IEnumPins> pEnumPins;
if (FAILED(pFilter->EnumPins(&pEnumPins))) {
return E_FAIL;
}
CComPtr<IPin> pPin;
while (pEnumPins->Next(1, &pPin, 0) == S_OK) {
PIN_DIRECTION pinDir;
if (FAILED(pPin->QueryDirection(&pinDir))) {
break;
}
if (pinDir == pinDirDest) {
CComPtr<IPin> pPinNext;
if (SUCCEEDED(pPin->ConnectedTo(&pPinNext))) {
PIN_INFO pinInfo;
if (FAILED(pPinNext->QueryPinInfo(&pinInfo)) || (pinInfo.pFilter ==
NULL)) {
return E_UNEXPECTED;
}
*ppFilterNext = pinInfo.pFilter;
return S_OK;
}
}
pPin.Release();
}
pEnumPins.Release();
return E_FAIL;
}
static VOID AddFilter(CFilterList &filterList, IBaseFilter *pFilter)
{
if (pFilter == NULL) {
return;
}
POSITION posIndex = filterList.GetHeadPosition();
while (posIndex != NULL) {
CComPtr<IBaseFilter> pFilterNext(filterList.GetNext(posIndex));
if (pFilterNext.IsEqualObject(pFilter)) {
return;
}
}
pFilter->AddRef();
filterList.AddTail(pFilter);
}
static HRESULT GetPeerFilters(IBaseFilter *pFilterStart, PIN_DIRECTION pinDirDest, CFilterList
&FilterList)
{
if (pFilterStart == NULL) {
return E_POINTER;
}
CComPtr<IPin> pPin;
CComPtr<IEnumPins> pEnumPins;
if (FAILED(pFilterStart->EnumPins(&pEnumPins))) {
return E_FAIL;
}
while (pEnumPins->Next(1, &pPin, 0) == S_OK) {
PIN_DIRECTION pinDir;
if (FAILED(pPin->QueryDirection(&pinDir))) {
pPin.Release();
break;
}
if (pinDir == pinDirDest) {
CComPtr<IPin> pPinNext;
if (SUCCEEDED(pPin->ConnectedTo(&pPinNext))) {
PIN_INFO pinInfo;
if (FAILED(pPinNext->QueryPinInfo(&pinInfo)) || (pinInfo.pFilter ==
NULL)) {
return E_UNEXPECTED;
}
This::AddFilter(FilterList, pinInfo.pFilter);
pinInfo.pFilter->Release();
}
}
pPin.Release();
}
pEnumPins.Release();
return S_OK;
}
static void NukeDownstream(IGraphBuilder *pGraph, IBaseFilter *pFilter)
{
if (pGraph == NULL || pFilter == NULL) {
return;
}
CComPtr<IEnumPins> pEnumPins;
if (FALSE(pFilter->EnumPins(&pEnumPins)) || pEnumPins == NULL) {
return;
}
pEnumPins->Reset();
CComPtr<IPin> pPin;
ULONG cFetched = 0;
while (SUCCEEDED(pEnumPins->Next(1, &pPin, &cFetched))) {
if (pPin == NULL && cFetched == 0) {
break;
}
CComPtr<IPin> pConnectedPin;
pPin->ConnectedTo(&pConnectedPin);
if (pConnectedPin != NULL) {
PIN_INFO pinInfo;
if (SUCCEEDED(pConnectedPin->QueryPinInfo(&pinInfo))) {
if (pinInfo.dir == PINDIR_INPUT) {
This::NukeDownstream(pGraph, pinInfo.pFilter);
pGraph->Disconnect(pConnectedPin);
pGraph->Disconnect(pPin);
pGraph->RemoveFilter(pinInfo.pFilter);
}
pinInfo.pFilter->Release();
}
pConnectedPin.Release();
}
pPin.Release();
}
pEnumPins.Release();
}
static void NukeUpstream(IGraphBuilder *pGraph, IBaseFilter *pFilter)
{
if (pGraph == NULL || pFilter == NULL) {
return;
}
CComPtr<IEnumPins> pEnumPins;
if (FAILED(pFilter->EnumPins(&pEnumPins)) || pEnumPins == NULL) {
return;
}
pEnumPins->Reset();
CComPtr<IPin> pPin;
ULONG cFetched = 0;
while (SUCCEEDED(pEnumPins->Next(1, &pPin, &cFetched))) {
if (pPin == NULL || cFetched == 0) {
break;
}
CComPtr<IPin> pConnectedPin;
pPin->ConnectedTo(&pConnectedPin);
if (pConnectedPin != NULL) {
PIN_INFO pinInfo;
if (SUCCEEDED(pConnectedPin->QueryPinInfo(&pinInfo))) {
if (pinInfo.dir == PINDIR_OUTPUT) {
This::NukeUpstream(pGraph, pinInfo.pFilter);
pGraph->Disconnect(pConnectedPin);
pGraph->Disconnect(pPin);
pGraph->RemoveFilter(pinInfo.pFilter);
}
pinInfo.pFilter->Release();
}
pConnectedPin.Release();
}
pPin.Release();
}
pEnumPins.Release();
}
//////////////////////////////////////////////////////////////////////////
static BOOL IsFilterRegistered(REFCLSID filterId)
{
CComPtr<IBaseFilter> pBaseFilter;
return (SUCCEEDED(pBaseFilter.CoCreateInstance(filterId)) && pBaseFilter != NULL);
}
static BOOL RegisterFilter(LPCSTR pszFilterAx)
{
typedef HRESULT (WINAPI *REGISTER_FUNC)();
HMODULE hModule = ::LoadLibraryA(pszFilterAx);
if (hModule == NULL) {
return FALSE;
}
REGISTER_FUNC registerFunc = (REGISTER_FUNC) GetProcAddress(hModule, "DllRegisterServer");
if (registerFunc != NULL) {
registerFunc();
}
::FreeLibrary(hModule);
return (registerFunc != NULL);
}
static BOOL RegisterFilter(LPCWSTR pszFilterAx)
{
typedef HRESULT (WINAPI *REGISTER_FUNC)();
HMODULE hModule = ::LoadLibraryW(pszFilterAx);
if (hModule == NULL) {
return FALSE;
}
REGISTER_FUNC registerFunc = (REGISTER_FUNC) GetProcAddress(hModule, "DllRegisterServer");
if (registerFunc != NULL) {
registerFunc();
}
::FreeLibrary(hModule);
return (registerFunc != NULL);
}
//////////////////////////////////////////////////////////////////////////
static DWORD DecideDeviceType(IBaseFilter *pBaseFilter)
{
if (pBaseFilter == NULL) {
return DT_UNKNOWN;
}
// Check if DV device
CComQIPtr<IAMExtTransport> pAMExtTransPost(pBaseFilter);
if (pAMExtTransPost != NULL) {
return DT_DV;
}
// Check if WDM analog
CComQIPtr<IAMAnalogVideoDecoder> pDecoder(pBaseFilter);
if (pDecoder != NULL) {
return DT_ANALOG_WDM;
}
// Check if VFW analog
CComQIPtr<IAMVfwCaptureDialogs> pVfwDlgs(pBaseFilter);
if (pVfwDlgs != NULL) {
return DT_ANALOG_VFW;
}
// Check if audio capture device
CComQIPtr<IAMAudioInputMixer> pAudioMixer(pBaseFilter);
if (pAudioMixer != NULL) {
return DT_ANALOG_AUDIO;
}
return DT_UNKNOWN;
}
// Given the displayname of devices, determine if they are the same one
template <typename StringT1, typename StringT2>
static BOOL IsSameDevice(StringT1 pszDeviceName1, StringT2 pszDeviceName2)
{
CAtlString deviceName1;
CAtlString deviceName2;
CAtlString temp1(pszDeviceName1);
CAtlString temp2(pszDeviceName2);
INT backSlash1 = temp1.Find(TEXT("\\\\"), 0);
INT backSlash2 = temp2.Find(TEXT("\\\\"), 0);
if (backSlash1 >= 0 && backSlash2 >= 0) {
deviceName1 = temp1.Right(temp1.GetLength() - backSlash1);
deviceName2 = temp2.Right(temp2.GetLength() - backSlash2);
return (deviceName1.CompareNoCase(deviceName2) == 0);
}
else {
return (temp1.CompareNoCase(temp2) == 0);
}
}
template <typename QueryCallbackT>
static BOOL QueryDeviceCategory(REFGUID guidCategory, QueryCallbackT queryCallback, DWORD dwContext)
{
CComPtr<ICreateDevEnum> pEnumHardware;
if (queryCallback == NULL || FAILED(pEnumHardware.CoCreateInstance(CLSID_SystemDeviceEnum)) ||
pEnumHardware == NULL) {
return FALSE;
}
CComPtr<IEnumMoniker> pEnumMoniker;
if (FAILED(pEnumHardware->CreateClassEnumerator(guidCategory, &pEnumMoniker, 0)) ||
pEnumMoniker == NULL) {
return FALSE;
}
pEnumMoniker->Reset();
ULONG lFetched = 0;
CComPtr<IMoniker> pMoniker;
while (SUCCEEDED(pEnumMoniker->Next(1, &pMoniker, &lFetched)) && (lFetched > 0)) {
if (pMoniker == NULL) {
continue;
}
LPOLESTR pwzDisplayName = NULL;
CComPtr<IBaseFilter> pBaseFilter;
CComPtr<IPropertyBag> pPropertyBag;
CComVariant varFriendlyName;
HRESULT hr = pMoniker->GetDisplayName(NULL, NULL, &pwzDisplayName);
if (FAILED(hr)) {
goto Next;
}
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (LPVOID *) &pPropertyBag);
if (FAILED(hr)) {
goto Next;
}
hr = pPropertyBag->Read(L"FriendlyName", &varFriendlyName, NULL);
if (FAILED(hr)) {
goto Next;
}
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (PVOID *) &pBaseFilter);
if (FAILED(hr)) {
goto Next;
}
queryCallback(pwzDisplayName, V_BSTR(&varFriendlyName), pBaseFilter, dwContext);
Next:
if (pwzDisplayName != NULL) {
CoTaskMemFree(pwzDisplayName);
}
pMoniker.Release();
}
return TRUE;
}
template <typename QueryCallbackT>
static BOOL QueryVideoCaptureDevices(QueryCallbackT queryCallback, DWORD dwContext) { return
This::QueryDeviceCategory(CLSID_VideoInputDeviceCategory, queryCallback, dwContext); }
template <typename QueryCallbackT>
static BOOL QueryAudioCaptureDevices(QueryCallbackT queryCallback, DWORD dwContext) { return
This::QueryDeviceCategory(CLSID_AudioInputDeviceCategory, queryCallback, dwContext); }
template <typename StringT>
static IBaseFilter * CreateHardwareFilter(REFGUID guidCategory, StringT lpszFriendlyName)
{
CComPtr<ICreateDevEnum> pEnumHardware;
HRESULT hr = pEnumHardware.CoCreateInstance(CLSID_SystemDeviceEnum);
if (FAILED(hr) || pEnumHardware == NULL) {
return NULL;
}
CComPtr<IBaseFilter> pHardwareFilter;
CComPtr<IEnumMoniker> pEnumMoniker;
hr = pEnumHardware->CreateClassEnumerator(guidCategory, &pEnumMoniker, 0);
if (pEnumMoniker == NULL) {
return NULL;
}
pEnumMoniker->Reset();
ULONG lFetched = 0;
CComPtr<IMoniker> pMoniker;
while (pHardwareFilter == NULL && SUCCEEDED(pEnumMoniker->Next(1, &pMoniker, &lFetched)) &&
lFetched) {
if (pMoniker == NULL) {
continue;
}
CComPtr<IPropertyBag> pPropertyBag;
CComVariant varName;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (LPVOID *) &pPropertyBag);
if (SUCCEEDED(hr)) {
hr = pPropertyBag->Read(L"FriendlyName", &varName, NULL);
}
if (SUCCEEDED(hr)) {
if (CComBSTR(V_BSTR(&varName)) == CComBSTR(lpszFriendlyName)) {
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (PVOID *)
&pHardwareFilter);
}
}
pMoniker.Release();
}
return pHardwareFilter.Detach();
}
template <typename StringT>
static IBaseFilter * CreateHardwareFilterEx(REFGUID guidCategory, StringT pszDisplayName, CComVariant
&varFriendlyName)
{
CComPtr<ICreateDevEnum> pEnumHardware;
if (FAILED(pEnumHardware.CoCreateInstance(CLSID_SystemDeviceEnum)) || pEnumHardware == NULL) {
return NULL;
}
CComPtr<IBaseFilter> pHardwareFilter;
CComPtr<IEnumMoniker> pEnumMoniker;
HRESULT hr = pEnumHardware->CreateClassEnumerator(guidCategory, &pEnumMoniker, 0);
if (pEnumMoniker == NULL) {
return NULL;
}
pEnumMoniker->Reset();
ULONG lFetched = 0;
CComPtr<IMoniker> pMoniker;
while (pHardwareFilter == NULL && SUCCEEDED(pEnumMoniker->Next(1, &pMoniker, &lFetched)) &&
(lFetched > 0)) {
if (pMoniker == NULL) {
continue;
}
LPOLESTR pwzDisplayName = NULL;
hr = pMoniker->GetDisplayName(NULL, NULL, &pwzDisplayName);
if (SUCCEEDED(hr)) {
if (This::IsSameDevice(pwzDisplayName, pszDisplayName)) {
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (LPVOID *)
&pHardwareFilter);
}
CoTaskMemFree(pwzDisplayName);
}
if (pszFriendlyName != NULL && pHardwareFilter != NULL) {
CComPtr<IPropertyBag> pPropertyBag;
pszFriendlyName[0] = 0;
if (SUCCEEDED(pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (PVOID *)
&pPropertyBag))) {
pPropertyBag->Read(L"FriendlyName", &varFriendlyName, NULL);
}
}
pMoniker.Release();
}
return pHardwareFilter.Detach();
}
// Create device according to the display name
template <typename StringT>
static IBaseFilter * CreateDevice(BOOL bVideo, StringT pszDisplayName, CComVariant &varFriendlyName)
{ return This::CreateHardwareFilterEx(bVideo ? CLSID_VideoInputDeviceCategory :
CLSID_AudioInputDeviceCategory, pszDisplayName, varFriendlyName); }
template <typename StringT>
static IBaseFilter * CreateCompressor(BOOL bVideo, StringT pszName) { return
This::CreateHardwareFilter(bVideo ? CLSID_VideoCompressorCategory : CLSID_AudioCompressorCategory, pszName); }
template <typename StringT>
static IBaseFilter * CreateVideoDevice(StringT pszFriendlyName) { return
This::CreateHardwareFilter(CLSID_VideoInputDeviceCategory, pszFriendlyName); }
template <typename StringT>
static IBaseFilter * CreateAudioDevice(StringT pszFriendlyName) { return
This::CreateHardwareFilter(CLSID_AudioInputDeviceCategory, pszFriendlyName); }
static IBaseFilter * FindFilter(IGraphBuilder *pGraphBuilder, REFCLSID clsID)
{
if (pGraphBuilder == NULL) {
return NULL;
}
CComPtr<IEnumFilters> pEnumFilters;
pGraphBuilder->EnumFilters(&pEnumFilters);
if (pEnumFilters == NULL) {
return NULL;
}
CLSID clsid;
ULONG lFetchCount = 0;
CComQIPtr<IPersist> pPersist;
CComQIPtr<IBaseFilter> pBaseFilter;
CComQIPtr<IBaseFilter> pFoundFilter;
while (S_OK == pEnumFilters->Next(1, &pBaseFilter, &lFetchCount) && lFetchCount && !
pFoundFilter) {
pPersist = pBaseFilter;
if (pPersist != NULL) {
pPersist->GetClassID(&clsid);
if (clsID == clsid) {
pFoundFilter = pBaseFilter;
}
}
pPersist.Release();
pFoundFilter.Release();
}
return pFoundFilter.Detach();
}
static HRESULT ShowFilterPropertyPage(IBaseFilter *pBaseFilter)
{
if (pBaseFilter == NULL) {
return E_INVALIDARG;
}
CComQIPtr<ISpecifyPropertyPages> pSpecify(pBaseFilter);
if (pSpecify == NULL) {
return E_NOINTERFACE;
}
CAUUID caGUID = { 0 };
pSpecify->GetPages(&caGUID);
pSpecify.Release();
OleCreatePropertyFrame(::GetActiveWindow(), 0, 0, NULL, 1, (IUnknown **) &pBaseFilter,
caGUID.cElems, caGUID.pElems, 0, 0, NULL);
CoTaskMemFree(caGUID.pElems);
return S_OK;
}
template <typename QueryCallbackT>
static VOID QueryMediaType(IAMStreamConfig *pStreamConfig, QueryCallbackT queryCallback, DWORD
dwContext)
{
INT nConfigCount= 0;
INT nConfigSize = 0;
pStreamConfig->GetNumberOfCapabilities(&nConfigCount, &nConfigSize);
LPBYTE lpConfig = new BYTE[nConfigSize];
AM_MEDIA_TYPE *pMediaType = NULL;
for (INT i=0; i<nConfigCount; ++i) {
pStreamConfig->GetStreamCaps(i, &pMediaType, lpConfig);
queryCallback(pStreamConfig, i, pMediaType, dwContext);
DeleteMediaType(pMediaType);
}
delete []lpConfig;
lpConfig = NULL;
}
};
//////////////////////////////////////////////////////////////////////////
typedef DSUtilityT<0> DSUtility;
//////////////////////////////////////////////////////////////////////////
#endif
相關文章
- DirectShow系列講座之一——DirectShow系統概述 (轉)
- dbverify Utility
- COM Utility
- Utility FilterFilter
- PG: Utility queries
- dbms_utility
- DBNEWID Utility
- C# DirectShow 播放多媒體C#
- DBVERIFY utility的使用
- DirectShow之介面實戰篇(一) (轉)
- DirectShow之介面實戰篇(二) (轉)
- DirectShow之介面實戰篇(三) (轉)
- DirectShow系列講座之二——Filter原理 (轉)Filter
- DirectShow技術描述與應用(3) (轉)
- DirectShow技術描述與應用(2) (轉)
- A Facial Recognition utility in a dozen of LOC
- ASM Metadata Dump UtilityASM
- DBMS_Utility學習
- DBMS_UTILITY.ANALYZE_SCHEMA
- dbms_utility.get_time
- Partition|Disk Utility 如何分割磁碟
- SMART Utility for mac (硬碟檢測)Mac硬碟
- File Compare Utility 3.0.002
- DBMS_UTILITY.COMPILE_SCHEMACompile
- enable run glance utility in windows CMDWindows
- DirectShow應用程式設計介紹(翻譯) (轉)程式設計
- 硬碟檢測工具:SMART Utility for mac硬碟Mac
- SMART Utility for Mac:硬碟健康的守護者Mac硬碟
- ASMCMD - ASM command line utility .ASM
- Tracing the LSNRCTL Control Utility
- DirectShow系列講座之三——開發自己的Filter (轉)Filter
- macOS Developer Beta Access Utility(蘋果開發者工具)MacDeveloper蘋果
- Oracle AMDU- ASM Metadata Dump UtilityOracleASM
- DBMS_UTILITY.FORMAT_ERROR_BACKTRACE FunctionORMErrorFunction
- dbms_utility的兩個有用方法
- Managed DirectX中的DirectShow應用(簡單Demo及原始碼)原始碼
- underscore 系列之防衝突與 Utility FunctionsFunction
- [Upgrade] Oracle 10.2.0.5 opatch utility upgradeOracle