IMMDevice::Activate() with IBaseFilter return REGDB_E_CLASSNOTREG Class 未注册

IMMDevice::Activate() with IBaseFilter return REGDB_E_CLASSNOTREG Class not registered

我想获取接口 IBaseFilter 系统混音器,但出现错误 REGDB_E_CLASSNOTREG Class 未注册于:

hr = pEndpoint->Activate(__uuidof(IBaseFilter), CLSCTX_ALL, /*&var*/ NULL, (void**)ppFilter);

此代码可以更早地工作。

完整代码:

过滤器名称 = "Stereo mixer (IDT High Definition Audio CODEC)"

HRESULT CCapture::GetAudioCaptureFilterByName(wstring *filterName, IBaseFilter **ppFilter)
{
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pEnumerator = 0;
    IMMDeviceCollection *pCollection = 0;
    IMMDevice *pEndpoint = 0;
    IPropertyStore *pProps = 0;
    LPWSTR pwszID = 0;

    hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
    if (FAILED(hr)) return hr;

    hr = pEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &pCollection);
    if (FAILED(hr))
    {
        if (pEnumerator) pEnumerator->Release();
        return hr;
    }

    UINT  count;
    hr = pCollection->GetCount(&count);
    if (FAILED(hr))
    {
        if (pCollection) pCollection->Release();
        if (pEnumerator) pEnumerator->Release();
        return hr;
    }

    if (count == 0)
    {
        if (pCollection) pCollection->Release();
        if (pEnumerator) pEnumerator->Release();
        return hr;
    }

    for (ULONG i = 0; i < count; i++)
    {
        hr = pCollection->Item(i, &pEndpoint);
        if (FAILED(hr))
        {
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }

        // Получаем ID устройства.
        hr = pEndpoint->GetId(&pwszID);
        if (FAILED(hr))
        {
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }

        hr = pEndpoint->OpenPropertyStore(STGM_READ, &pProps);
        if (FAILED(hr))
        {
            CoTaskMemFree(pwszID);
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }

        PROPVARIANT varName;
        PropVariantInit(&varName);

        // Получаем дружественное имя устройства.
        hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName);
        if (FAILED(hr))
        {
            CoTaskMemFree(pwszID);
            if (pProps) pProps->Release();
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();
            return hr;
        }


        wstring *wstr = new wstring(varName.pwszVal);
        if (wstr->compare(*filterName) == 0)
        {
            DIRECTX_AUDIO_ACTIVATION_PARAMS  daap;
            daap.cbDirectXAudioActivationParams = sizeof(daap);
            daap.guidAudioSession = guidAudioSessionId;
            daap.dwAudioStreamFlags = AUDCLNT_STREAMFLAGS_CROSSPROCESS;

            PROPVARIANT var;
            PropVariantInit(&var);

            var.vt = VT_BLOB;
            var.blob.cbSize = sizeof(daap);
            var.blob.pBlobData = (BYTE*)&daap;

            hr = pEndpoint->Activate(__uuidof(IBaseFilter), CLSCTX_ALL, /*&var*/ NULL, (void**)ppFilter);

            delete wstr;
            CoTaskMemFree(pwszID);
            PropVariantClear(&varName);

            if (pProps) pProps->Release();
            if (pEndpoint) pEndpoint->Release();
            if (pCollection) pCollection->Release();
            if (pEnumerator) pEnumerator->Release();

            return hr;
        }

        delete wstr;
        CoTaskMemFree(pwszID);
        pwszID = NULL;
        PropVariantClear(&varName);
        if (pProps) pProps->Release();
        if (pEndpoint) pEndpoint->Release();
        pProps = 0;
        pEndpoint = 0;
    }

    hr = E_FAIL;
    if (pProps) pProps->Release();
    if (pEndpoint) pEndpoint->Release();
    if (pCollection) pCollection->Release();
    if (pEnumerator) pEnumerator->Release();

    return hr;
}

问题是由于与已安装的 DirectShowSpy 工具发生冲突。

MMDevice 的 Activate for IBaseFilter 大概做了以下事情:

if(interface is IBaseFilter)
{
  IMMDeviceActivator pMmDeviceActivator;
  CoCreateInstace(CLSID_SystemDeviceEnum, ..., &pMmDeviceActivator);
  return pMmDeviceActivator->Activate(pMmDevice, ...)
}

系统设备枚举器 CLSID_SystemDeviceEnumIMMDeviceActivator 的实现未记录(接口保留供内部使用)并且 DirectShowSpy 没有很好地处理它。从版本 1.0.0.2106 开始它就正确了。