流式处理音频呈现器
流式处理音频呈现器(SAR)是呈现音频的媒体接收器。 SAR 的每个实例都呈现单个音频流。 若要呈现多个流,请使用 SAR 的多个实例。
若要创建 SAR,请调用以下任一函数:
- MFCreateAudioRenderer。 返回指向 SAR 的指针。
- MFCreateAudioRendererActivate。 返回指向激活对象的指针,该对象可用于创建 SAR。
如果要播放受保护的内容,则返回激活对象的第二个函数是必需的,因为激活对象必须序列化为受保护的进程。 对于明文内容,可以使用任一函数。
SAR 可以接收 PCM 或 IEEE 浮点格式的未压缩音频。 如果播放速率快于 1×,则 SAR 会自动调整音调。
配置音频呈现器
SAR 支持多个配置属性。 设置这些属性的机制取决于你调用哪个函数来创建 SAR。 如果使用 MFCreateAudioRenderer 函数,请执行以下作:
- 通过调用 MFCreateAttributes创建新的属性存储。
- 将属性添加到属性存储区。
- 将属性存储传递到 pAudioAttributes 参数中的 MFCreateAudioRenderer 函数。
如果使用 MFCreateAudioRendererActivate 函数,该函数将返回指向 ppActivate 参数中 IMFAttributes 接口的指针。 使用此指针添加属性。
有关配置属性的列表,请参阅 音频呈现器属性。
选择音频终结点设备
音频终结点设备 是呈现或捕获音频的硬件设备。 示例包括扬声器、耳机、麦克风和 CD 播放器。 SAR 始终使用音频呈现设备。 有两种方法可以选择设备。
第一种方法是使用 IMMDeviceEnumerator 接口枚举系统上的音频呈现设备。 此接口记录在核心音频 API 文档中。
- 创建设备枚举器对象。
- 使用设备枚举器枚举音频呈现设备。 每个设备都由指向 IMMDevice 接口的指针表示。
- 根据设备属性或用户选择选择选择设备。
- 调用 IMMDevice::GetId 以获取设备标识符。
- 将设备标识符设置为 MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID 特性的值。
你可以通过 角色指定音频设备,而不是枚举设备。 音频角色标识一般用途类别。 例如,为游戏和系统通知定义 主机 角色,而为音乐和电影定义 多媒体 角色。 每个角色都有一个分配给它的音频呈现设备,用户可以更改这些分配。 如果指定设备角色,SAR 将使用为该角色分配的任何音频设备。 若要指定设备角色,请设置 MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE 属性。
本节中列出的两个属性互斥。 如果未设置其中任一设备,SAR 将使用分配给 eConsole 角色的音频设备。
以下代码枚举音频呈现设备,并将列表中的第一台设备分配给 SAR。 此示例使用 MFCreateAudioRenderer 函数创建 SAR。
#include <mmdeviceapi.h>
HRESULT hr = S_OK;
IMMDeviceEnumerator *pEnum = NULL; // Audio device enumerator.
IMMDeviceCollection *pDevices = NULL; // Audio device collection.
IMMDevice *pDevice = NULL; // An audio device.
IMFAttributes *pAttributes = NULL; // Attribute store.
IMFMediaSink *pSink = NULL; // Streaming audio renderer (SAR)
LPWSTR wstrID = NULL; // Device ID.
// Create the device enumerator.
hr = CoCreateInstance(
__uuidof(MMDeviceEnumerator),
NULL,
CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnum
);
// Enumerate the rendering devices.
if (SUCCEEDED(hr))
{
hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices);
}
// Get ID of the first device in the list.
if (SUCCEEDED(hr))
{
hr = pDevices->Item(0, &pDevice);
}
if (SUCCEEDED(hr))
{
hr = pDevice->GetId(&wstrID);
}
// Create an attribute store and set the device ID attribute.
if (SUCCEEDED(hr))
{
hr = MFCreateAttributes(&pAttributes, 2);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetString(
MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID,
wstrID
);
}
// Create the audio renderer.
if (SUCCEEDED(hr))
{
hr = MFCreateAudioRenderer(pAttributes, &pSink);
}
SAFE_RELEASE(pEnum);
SAFE_RELEASE(pDevices);
SAFE_RELEASE(pDevice);
SAFE_RELEASE(pAttributes);
CoTaskMemFree(wstrID);
若要为 SAR 创建激活对象,请将调用 IMMDevice::GetId 后显示的代码更改为以下内容:
IMFActivate *pActivate = NULL; // Activation object.
if (SUCCEEDED(hr))
{
hr = MFCreateAudioRendererActivate(&pActivate);
}
if (SUCCEEDED(hr))
{
hr = pActivate->SetString(
MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID,
wstrID
);
}
SAFE_RELEASE(pActivate);
选择音频会话
音频会话是应用程序可以共同管理的相关音频流组。 应用程序可以控制每个会话的音量级别和静音状态。 会话由 GUID 标识。 若要指定 SAR 的音频会话,请使用 MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID 属性。 如果未设置此属性,SAR 会加入该过程的默认会话,由 GUID_NULL标识。
默认情况下,音频会话特定于进程,这意味着它仅包含来自调用进程的流。 若要加入跨进程会话,请使用值 MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_CROSSPROCESS设置 MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS 属性。
创建 SAR 后,可以使用 IMFAudioPolicy 接口将会话加入一组会话,所有这些会话均由控制面板中的相同卷控件控制。 还可以使用此接口设置显示在卷控件中的显示名称和图标。
控制音量级别
若要控制 SAR 音频会话中所有流的主音量级别,请使用 IMFSimpleAudioVolume 接口。 若要控制单个流的卷,或控制流中各个通道的音量,请使用 IMFAudioStreamVolume 接口。 这两个接口都是通过调用 IMFGetService::GetService获取的。 可以直接在 SAR 上调用 GetService,也可以在媒体会话上调用它。 音量级别表示为衰减值。 对于每个通道,衰减级别是主卷和通道卷的乘积。
相关主题