DirectShow 应用程序的设备角色

注意

MMDevice API 支持设备角色。 但是,Windows Vista 的用户界面不支持这一功能。 将来的 Windows 版本可能会对设备角色提供用户界面支持。 有关详细信息,请参阅 Windows Vista 中的设备角色

 

DirectShow API 没有为应用程序提供选择分配给特定设备角色音频终结点设备的方法。 但是,在 Windows Vista 中,核心音频 API 可与 DirectShow 应用程序配合使用,以便根据设备角色来选择设备。 借助核心音频 API,应用程序可以:

  • 识别用户分配给特定设备角色的音频终结点设备。
  • 创建一个 DirectShow 音频呈现筛选器,该筛选器带有一个封装音频终结点设备的 IBaseFilter 接口。
  • 生成包含筛选器的 DirectShow 图形。

有关 DirectShow 和 IBaseFilter 的详细信息,请参阅 Windows SDK 文档。

下面的代码示例展示了如何创建 DirectShow 音频呈现筛选器,该筛选器封装了分配给特定设备角色的呈现终结点设备:

//-----------------------------------------------------------
// Create a DirectShow audio rendering filter that
// encapsulates the audio endpoint device that is currently
// assigned to the specified device role.
//-----------------------------------------------------------
#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

// This application's audio session GUID
const GUID guidAudioSessionId = {
    0xb13ff52e, 0xa5cf, 0x4fca,
    {0x9f, 0xc3, 0x42, 0x26, 0x5b, 0x0b, 0x14, 0xfb}
};

HRESULT CreateAudioRenderer(ERole role, IBaseFilter** ppAudioRenderer)
{
    HRESULT hr = S_OK;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDevice *pDevice = NULL;

    if (ppAudioRenderer == NULL)
    {
        return E_POINTER;
    }

    // Activate the IBaseFilter interface on the
    // audio renderer with the specified role.
    hr = CoCreateInstance(CLSID_MMDeviceEnumerator,
                          NULL, CLSCTX_INPROC_SERVER,
                          __uuidof(IMMDeviceEnumerator),
                          (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, role,
                                              &pDevice);
    EXIT_ON_ERROR(hr)

    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 = pDevice->Activate(__uuidof(IBaseFilter),
                           CLSCTX_ALL, &var,
                           (void**)ppAudioRenderer);
    EXIT_ON_ERROR(hr)

Exit:
    SAFE_RELEASE(pEnumerator);
    SAFE_RELEASE(pDevice);
    return hr;
}

在前面的代码示例中,CreateAudioRenderer 函数接受设备角色(eConsole、eMultimedia 或 eCommunications)作为输入参数。 第二个参数是一个指针,函数通过它写入 IBaseFilter 接口实例的地址。 此外,该示例还展示了如何使用 IMMDevice::Activate 方法将 IBaseFilter 实例中的音频流分配给具有特定于应用程序的会话 GUID(由 guidAudioSessionId 常量指定)的跨进程音频会话。 Activate 调用中的第三个参数指向一个包含会话 GUID 和跨进程标志的结构。 如果用户运行多个应用程序实例,那么所有实例的音频流都使用相同的会话 GUID,因此它们都属于同一个会话。

或者,调用方可以在 Activate 调用中指定 NULL 作为第三个参数,以便将流分配给作为进程特定的会话的默认会话,其会话 GUID 值为 GUID_NULL。 有关详细信息,请参阅 IMMDevice::Activate

与传统音频 API 的互操作性