MFTEnum2 函数 (mfapi.h)

获取与指定搜索条件匹配的 Microsoft Media Foundation (MCT) 转换的列表。 此函数扩展 MFTEnumEx 函数,以允许外部应用程序和内部组件发现与特定视频适配器对应的硬件 MMT。

语法

HRESULT MFTEnum2(
  [in]           GUID                         guidCategory,
  [in]           UINT32                       Flags,
  [in]           const MFT_REGISTER_TYPE_INFO *pInputType,
  [in]           const MFT_REGISTER_TYPE_INFO *pOutputType,
  [in, optional] IMFAttributes                *pAttributes,
  [out]          IMFActivate                  ***pppMFTActivate,
  [out]          UINT32                       *pnumMFTActivate
);

参数

[in] guidCategory

一个 GUID,指定要枚举的 MCT 类别。 有关 MFT 类别的列表,请参阅 MFT_CATEGORY

[in] Flags

_MFT_ENUM_FLAG枚举中零个或多个标志的按位 OR

[in] pInputType

指向 MFT_REGISTER_TYPE_INFO 结构的指针,该结构指定要匹配的输入媒体类型。

此参数可以为 NULL。 如果 为 NULL,则匹配所有输入类型。

[in] pOutputType

指向 MFT_REGISTER_TYPE_INFO 结构的指针,该结构指定要匹配的输出媒体类型。

此参数可以为 NULL。 如果 为 NULL,则匹配所有输出类型。

[in, optional] pAttributes

指向用于访问标准属性存储的 IMFAttributes 接口的指针。 若要指定查询 MMFT 的特定硬件适配器,请将 MFT_ENUM_ADAPTER_LUID 属性设置为适配器的 LUID。 如果执行此操作,还必须指定MFT_ENUM_FLAG_HARDWARE标志或返回E_INVALIDARG。

[out] pppMFTActivate

接收 IMFActivate 接口指针数组。 每个指针表示与搜索条件匹配的 MFT 的激活对象。 函数为数组分配内存。 调用方必须释放指针并调用 CoTaskMemFree 函数以释放数组的内存。

[out] pnumMFTActivate

接收 pppMFTActivate 数组中的元素数。 如果没有 MCT 与搜索条件匹配,则此参数接收值零。

返回值

如果该方法成功,则它会返回 S_OK。 如果失败,可能的返回代码包括但不限于下表中显示的值。

返回代码 说明
E_INVALIDARG
pAttributes 参数中提供了包含 MFT_ENUM_ADAPTER_LUID 属性的 IMFAttributes,但未指定MFT_ENUM_FLAG_HARDWARE标志。

注解

Flags 参数控制枚举 MRT 及其返回顺序。 此参数的标志分为多个组。

第一组标志指定 MFT 处理数据的方式。

标志 描述
MFT_ENUM_FLAG_SYNCMFT MFT 在软件中执行同步数据处理。 这是原始 MFT 处理模型,与 Windows Vista 兼容。
MFT_ENUM_FLAG_ASYNCMFT MFT 在软件中执行异步数据处理。 此处理模型需要 Windows 7。 有关详细信息,请参阅 异步 MCT
MFT_ENUM_FLAG_HARDWARE MFT 使用 AVStream 驱动程序或基于 GPU 的代理 MFT 执行基于硬件的数据处理。 此类别中的 MMFT 始终异步处理数据。 有关详细信息,请参阅 硬件 MCT
注意 如果在 pAttributes 参数中提供了包含 MFT_ENUM_ADAPTER_LUID 属性的 IMFAttributes ,则必须设置MFT_ENUM_FLAG_HARDWARE标志,否则将返回E_INVALIDARG。
 
 

每个 MFT 都属于这些类别之一。 若要枚举类别,请在 Flags 参数中设置相应的标志。 可以组合这些标志来枚举多个类别。 如果未指定这些标志,则默认类别是同步 MRT (MFT_ENUM_FLAG_SYNCMFT) 。

接下来,以下标志包括从结果中排除的 MCT。 默认情况下,与这些条件匹配的标志将从结果中排除。 使用任何这些标志来包括它们。

标志 描述
MFT_ENUM_FLAG_FIELDOFUSE 包括必须由应用程序解锁的 MCT。
MFT_ENUM_FLAG_LOCALMFT 包括通过 MFTRegisterLocal 或 MFTRegisterLocalByCLSID 函数在调用方进程中注册的 MMT
MFT_ENUM_FLAG_TRANSCODE_ONLY 包括针对转码(而不是播放)优化的 MCT。
 

最后一个标志用于对结果进行排序和筛选:

标志 描述
MFT_ENUM_FLAG_SORTANDFILTER 对结果进行排序和筛选。
 

如果设置了 MFT_ENUM_FLAG_SORTANDFILTER 标志, MFTEnum2 函数将按如下所示对结果进行排序:

  • 本地:如果设置了 MFT_ENUM_FLAG_LOCALMFT 标志,则本地 MMF 首先显示在列表中。 若要注册本地 MFT,请调用 MFTRegisterLocalMFTRegisterLocalByCLSID 函数。
  • 优点:具有优点值的 MMF 在列表中旁边显示,其优点值 (从高到低) 的顺序。 有关优点的详细信息,请参阅 MFT_CODEC_MERIT_Attribute
  • 首选:如果 MFT 列在插件控件的首选列表中,则该 MFT 显示在列表中的下一个。 有关插件控件的详细信息,请参阅 IMFPluginControl
  • 如果 MFT 出现在阻止列表中,则会从结果中排除该 MFT。 有关阻止列表的详细信息,请参阅 IMFPluginControl::IsDisabled
  • 与搜索条件匹配的任何其他 MMFT 显示在列表末尾,未排序。
如果未设置 MFT_ENUM_FLAG_SORTANDFILTER 标志, MFTEnum2 函数将返回未排序的列表。

Flags 参数设置为零等效于使用 值MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER

标志 设置为 MFT_ENUM_FLAG_SYNCMFT 等效于调用 MFTEnum 函数。

如果没有 MCT 与搜索条件匹配,则函数将返回 S_OK,除非发生其他错误。 因此,在取消引用 pppMFTActivate 指针之前,始终检查 pcMFTActivate 参数中收到的计数。

注意 无法仅枚举本地 MCT,而别无他法。 将 标志 设置为 等于 MFT_ENUM_FLAG_LOCALMFT 等效于包含 MFT_ENUM_FLAG_SYNCMFT 标志。 但是,如果还通过指定 MFT_ENUM_FLAG_SORTANDFILTER 标志对结果进行排序,则本地 MMFT 首先显示在列表中。
 

创建 MFT

如果至少有一个 MFT 与搜索条件匹配, 则 pppMFTActivate 参数将接收 IMFActivate 指针数组。 为每个匹配的 MFT 返回一个指针。 每个指针表示 MFT 的 一个激活对象 。 有关详细信息,请参阅 激活对象

有关每个 MFT 的其他信息存储为激活对象上的属性。 有关可能属性的列表,请参阅 转换属性

若要创建 MFT 的实例,请调用 IMFActivate::ActivateObject

硬件编解码器

如果以下注册表项设置为零,则硬件编解码器将从枚举结果中排除:

解码器: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Media Foundation\HardwareMFT\EnableDecoders

编码器: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Media Foundation\HardwareMFT\EnableEncoders

视频处理器: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Media Foundation\HardwareMFT\EnableVideoProcessors

这些密钥适用于 OEM,不应由应用程序使用。

对于硬件编解码器,MFTEnum2guidCategory 参数还可以指定以下内核流式处理 (KS) 设备类别之一:

  • KSCATEGORY_DATACOMPRESSOR
  • KSCATEGORY_DATADECOMPRESSOR
硬件编解码器还应在 MFT_CATEGORY GUID 下注册,因此应用程序通常应使用这些类别而不是 KS 设备类别。

示例

以下示例检索第一个可用的 IDXGIAdapter1 并获取适配器 LUID,这是标识后续示例的适配器所必需的。

HRESULT hr = S_OK;
IDXGIFactory1 *pDxgiFactory = NULL;
IDXGIAdapter1 *pDxgiAdapter = NULL;
LUID adapterLuid;

if (FAILED(hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)&pDxgiFactory)))
{
    return hr;
}

if (FAILED(hr = pDxgiFactory->EnumAdapters1(0, &pDxgiAdapter)))
{
    return hr;
}

DXGI_ADAPTER_DESC1 AdapterDescr;
if (FAILED(hr = pDxgiAdapter->GetDesc1(&AdapterDescr)))
{
    if (pDxgiAdapter)
    {
        pDxgiAdapter->Release();
        pDxgiAdapter = NULL;
    }
    return hr;
}

adapterLuid = AdapterDescr.AdapterLuid;

以下示例搜索硬件视频或音频解码器。 不包括异步、硬件、转码和使用字段解码器。 如果找到匹配项,则代码会在列表中创建第一个 MFT。 与 MFTEnumEx 文章中的并行示例不同,此示例创建 IMFAttributes 的实例,并将 MFT_ENUM_ADAPTER_LUID 属性设置为从中请求解码器的接口的 LUID。 在对 MFTEnum2 的调用中,设置所需的 MFT_ENUM_FLAG_HARDWARE 标志,并提供 IMFAttributes 参数。

HRESULT FindHWDecoder(
    const GUID& subtype,        // Subtype
    BOOL bAudio,                // TRUE for audio, FALSE for video
    LUID& adapterLuid,          // LUID of the graphics adapter for which to find the decoder
    IMFTransform **ppDecoder    // Receives a pointer to the decoder.
)
{
    HRESULT hr = S_OK;

    
    UINT32 count = 0;

    IMFActivate **ppActivate = NULL;

    CComPtr<IMFAttributes> spAttributes;
    hr = MFCreateAttributes(&spAttributes, 1);
    if (FAILED(hr = spAttributes->SetBlob(MFT_ENUM_ADAPTER_LUID, (BYTE*)&adapterLuid, sizeof(LUID))))
    {
        return hr;
    }


    MFT_REGISTER_TYPE_INFO info = { 0 };

    info.guidMajorType = bAudio ? MFMediaType_Audio : MFMediaType_Video;
    info.guidSubtype = subtype;

    hr = MFTEnum2(
        bAudio ? MFT_CATEGORY_AUDIO_DECODER : MFT_CATEGORY_VIDEO_DECODER,
        MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER,
        &info,      // Input type
        NULL,       // Output type
        spAttributes,
        &ppActivate,
        &count
    );

    if (SUCCEEDED(hr) && count == 0)
    {
        hr = MF_E_TOPO_CODEC_NOT_FOUND;
    }

    // Create the first decoder in the list.

    if (SUCCEEDED(hr))
    {
        hr = ppActivate[0]->ActivateObject(IID_PPV_ARGS(ppDecoder));
    }

    for (UINT32 i = 0; i < count; i++)
    {
        ppActivate[i]->Release();
    }
    CoTaskMemFree(ppActivate);

    return hr;
}

下一个示例搜索硬件视频或音频编码器。 不包括异步编码器、硬件编码器、转码编码器和使用场编码器。 与 MFTEnumEx 文章中的并行示例不同,此示例创建 IMFAttributes 的实例,并将 MFT_ENUM_ADAPTER_LUID 属性设置为从中请求编码器的接口的 LUID。 在对 MFTEnum2 的调用中,设置所需的 MFT_ENUM_FLAG_HARDWARE 标志,并提供 IMFAttributes 参数。

HRESULT FindHWEncoder(
    const GUID& subtype,        // Subtype
    BOOL bAudio,                // TRUE for audio, FALSE for video
    LUID& adapterLuid,          // LUID of the graphics adapter for which to find the encoder
    IMFTransform **ppEncoder    // Receives a pointer to the decoder.
)
{
    HRESULT hr = S_OK;
    UINT32 count = 0;

    IMFActivate **ppActivate = NULL;

    CComPtr<IMFAttributes> spAttributes;
    hr = MFCreateAttributes(&spAttributes, 1);
    if (FAILED(hr = spAttributes->SetBlob(MFT_ENUM_ADAPTER_LUID, (BYTE*)&adapterLuid, sizeof(LUID))))
    {
        return hr;
    }

    MFT_REGISTER_TYPE_INFO info = { 0 };

    info.guidMajorType = bAudio ? MFMediaType_Audio : MFMediaType_Video;
    info.guidSubtype = subtype;

    hr = MFTEnum2(
        bAudio ? MFT_CATEGORY_AUDIO_ENCODER : MFT_CATEGORY_VIDEO_ENCODER,
        MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER,
        NULL,       // Input type
        &info,      // Output type
        spAttributes,
        &ppActivate,
        &count
    );

    if (SUCCEEDED(hr) && count == 0)
    {
        hr = MF_E_TOPO_CODEC_NOT_FOUND;
    }

    // Create the first encoder in the list.

    if (SUCCEEDED(hr))
    {
        hr = ppActivate[0]->ActivateObject(IID_PPV_ARGS(ppEncoder));
    }

    for (UINT32 i = 0; i < count; i++)
    {
        ppActivate[i]->Release();
    }
    CoTaskMemFree(ppActivate);

    return hr;
}

下一个示例搜索硬件视频解码器,其中包含异步、硬件或转码解码器的选项。 与 MFTEnumEx 文章中的并行示例不同,此示例创建 IMFAttributes 的实例,并将 MFT_ENUM_ADAPTER_LUID 属性设置为从中请求视频解码器的接口的 LUID。 在对 MFTEnum2 的调用中,设置所需的 MFT_ENUM_FLAG_HARDWARE 标志,并提供 IMFAttributes 参数。

HRESULT FindHWVideoDecoder(
    const GUID& subtype,
    BOOL bAllowAsync,
    BOOL bAllowHardware,
    BOOL bAllowTranscode,
    LUID& adapterLuid,          // LUID of the graphics adapter for which to find the encoder
    IMFTransform **ppDecoder
)
{
    HRESULT hr = S_OK;
    UINT32 count = 0;

    IMFActivate **ppActivate = NULL;

    MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, subtype };

    UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT |
        MFT_ENUM_FLAG_SORTANDFILTER;

    if (bAllowAsync)
    {
        unFlags |= MFT_ENUM_FLAG_ASYNCMFT;
    }
    if (bAllowHardware)
    {
        unFlags |= MFT_ENUM_FLAG_HARDWARE;
    }
    if (bAllowTranscode)
    {
        unFlags |= MFT_ENUM_FLAG_TRANSCODE_ONLY;
    }

    unFlags |= MFT_ENUM_FLAG_HARDWARE;

    CComPtr<IMFAttributes> spAttributes;
    hr = MFCreateAttributes(&spAttributes, 1);
    if (FAILED(hr = spAttributes->SetBlob(MFT_ENUM_ADAPTER_LUID, (BYTE*)&adapterLuid, sizeof(LUID))))
    {
        return hr;
    }

    hr = MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER,
        unFlags,
        &info,      // Input type
        NULL,       // Output type
        &ppActivate,
        &count);

    if (SUCCEEDED(hr) && count == 0)
    {
        hr = MF_E_TOPO_CODEC_NOT_FOUND;
    }

    // Create the first decoder in the list.
    if (SUCCEEDED(hr))
    {
        hr = ppActivate[0]->ActivateObject(IID_PPV_ARGS(ppDecoder));
    }

    for (UINT32 i = 0; i < count; i++)
    {
        ppActivate[i]->Release();
    }
    CoTaskMemFree(ppActivate);

    return hr;
}

要求

要求
最低受支持的客户端 Windows 10 [仅限桌面应用]
最低受支持的服务器 Windows Server 2016 [仅限桌面应用]
目标平台 Windows
标头 mfapi.h
Library Mfplat.lib
DLL Mfplat.dll

另请参阅

使用限制字段

MFTRegister

媒体基础函数

注册和枚举 MCT