DirectShow Utility

LiuYinChina發表於2013-02-18
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


相關文章