流路由实现注意事项
在 Windows 7 中,使用核心音频 API(如 Media Foundation、DirectSound 和 Wave API)的高级平台 API 通过处理从现有设备切换到新的默认音频终结点的流来实现流路由功能。 使用这些 API 的媒体应用程序使用流路由行为,而无需对源进行任何修改。 直接 WASAPI 客户端可以使用核心音频组件发送的通知并实现流路由功能。
直接 WASAPI 客户端(直接使用 WASAPI 的媒体应用程序)接收新设备和核心音频组件发送的音频会话通知。 流路由功能的行为由应用程序处理这些通知的方式定义。
MMDevice API 和音频会话以回调形式向 WASAPI 客户端发送有关设备状态更改和会话更改的通知。 若要获取这些通知,客户端必须注册其 IMMNotificationClient 和 IAudioSessionEvents 实现。 有关详细信息,请参阅流路由的相关通知。
在流路由中所述的 USB 耳机场景中,应用程序正在播放音频流,并使用 MMDeviceAPI 和 WASAPI 在默认呈现设备(Speaker)上呈现流。 更改默认设备后,应用程序会收到 IMMNotificationClient 通知。 应用程序还会收到 IAudioSessionEvents 通知,指示用户删除了音频终结点设备,或者音频会话连接到的设备更改了流格式。 收到通知后,应用程序停止流式传输到扬声器终结点,并重新打开流以在当前默认终结点(耳机)上呈现。
为了响应此类通知,客户端可能会以用户选择的新格式重新打开新默认设备上的流。
流管理
以下列表总结了 WASAPI 客户端提供流切换功能必须执行的步骤。
等待相关的 IMMNotificationClient 通知。 如果设备是默认设备,则会收到 IMMNotificationClient::OnDefaultDeviceChanged 通知。
如果新设备可用,请获取对新设备的终结点的引用。 为新的默认设备调用 IMMDeviceEnumerator::GetDefaultAudioEndpoint。 如果新设备不是默认设备,可以通过调用 IMMDeviceEnumerator::GetDevice 来检索设备。 有关详细信息,请参阅获取流路由的设备终结点。
等待 IAudioSessionEvents::OnSessionDisconnected 及原因值。
注意
所有这些操作都是异步操作,因此无法预测应用程序接收设备更改和会话断开连接通知的顺序。 应用程序必须实现通知处理才能按任意顺序接收这些通知。 但是,应用程序通常在默认设备更改通知前收到 AudioSessionDisconnect 值。
评估原因值并确定是需要将流传输到另一个音频终结点,还是需要使用新格式重新初始化流。
如果原因指示应将流重新路由到新的默认设备,请停止流式传输到旧的默认设备。
执行位置映射计算。
在新设备上打开流并传输所有状态信息。
在新的默认设备上恢复流式处理。
处理旧默认设备的离开。
若要使流切换操作看起来无缝,必须尽快完成。 这取决于新设备上重新启动流涉及的组件的性能。
位置映射注意事项
当应用程序收到 IMMNotificationClient 和 IAudioSessionEvents 通知时,可以将现有流路由到新的默认设备。 在新设备上中断和打开现有音频流时,新设备上的呈现必须从旧设备上停止流的位置开始。 为此,应用程序必须具有最后一个已知设备位置,才能计算新设备上的起始位置。 例如,此位置可用作后续位置映射的增量偏移。 当流开始呈现时,可以将新设备位置重新映射到缓存的设备位置。
以下步骤总结了无缝流转换的过程。
- 缓存旧设备上的流的最后一个设备位置。
- 停止旧设备上的流。
- 执行重新映射计算以获取新位置。
- 开始在新设备上呈现流。
- 释放旧流。
在转换期间,应用程序必须确保时钟同步,从而生成不同步的音频和视频流。 如果视频示例在音频流路由到新设备时继续呈现,则可能会出现这种情况。 应用程序必须缓存重新映射计算的时钟位置,并确保在新设备上重新打开音频流之前不会呈现视频样本,以便在剪辑恢复呈现时同步音频和视频流。 在某些情况下,呈现视频帧的呈现时间基于音频时钟,此时足以停止音频流,直到流切换完成,并且音频视频同步不需要视频流的其他位置映射实现。
如果在呈现时,因旧设备丢失导致 IAudioRenderClient::GetBuffer 返回错误,由于流式处理操作已终止,因此应用程序不需要停止旧流。 有关处理此错误的信息,请参阅从无效设备错误恢复。
相关主题