为 UWP 设备应用创建相机驱动程序 MFT

重要

此主题已弃用。 有关更新指南,请参阅设备 MFT 设计指南

UWP 设备应用可让设备制造商通过相机驱动程序 MFT(媒体基础转换)在相机视频流中应用自定义设置和特效。 本主题介绍驱动程序 MFT,并使用驱动程序 MFT 示例演示创建方法。 要了解有关 UWP 设备应用的一般详细信息,请参阅初识 UWP 设备应用

驱动程序 MFT

本节介绍媒体基础转换 (MFT),你可以创建该转换来对来自相机的媒体捕获流应用特效。 你可以通过这种方式为色彩效果、方案模式和人脸跟踪效果提供转换,使你的相机与众不同。 这种 MFT 被称为驱动程序 MFT,当 UWP 应用程序开始视频捕获时,它首先应用于来自相机驱动程序的连接视频流。 当该应用调用相机选项 UI 时,Windows 会自动提供对驱动程序 MFT 实现的任何接口的访问,以控制其自定义效果。

the camera driver mft helps a windows store device app provide custom effects.

UWP 设备应用不需要驱动程序 MFT。 设备制造商可能会选择在没有驱动程序 MFT 的情况下实施 UWP 设备应用,这样做只是为了提供一个包含其硬件品牌的差异化用户界面,而无需对视频流应用自定义设置和特效。

如何使用驱动程序 MFT

适用于相机的 UWP 设备应用与从 CameraCaptureUI API 调用相机的 Microsoft Store 商店应用在不同的进程中运行。 要使 Microsoft Store 设备应用控制驱动程序 MFT,必须在不同进程空间中发生特定的事件序列。

  1. UWP 应用想要捕获照片,因此它调用 CaptureFileAsync 方法

  2. Windows 请求驱动程序 MFT 指针和相机的设备 ID

  3. 驱动程序 MFT 指针传递到设置主机

  4. 主机查询设备属性,以获取与相机关联的 Microsoft Store 设备应用的应用 ID(根据设备元数据)

  5. 如果未找到 UWP 设备应用,则默认浮出控件将与捕获引擎交互

  6. 如果找到 UWP 设备应用,则会激活它,并且设置主机会将驱动程序 MFT 指针传递给它

  7. UWP 设备应用使用通过指针公开的接口控制驱动程序 MFT

the process interaction for invoking a windows store device app.

AvStream 驱动程序模型要求

相机的驱动程序必须使用 AvStream 驱动程序模型。 有关 AVStream 驱动程序模型的详细信息,请参阅 AVStream 微型驱动程序设计指南

驱动程序 MFT 如何向应用公开

驱动程序 MFT 在 Windows 中注册为 COM 接口,以便将其实现的转换应用于特定设备(如相机)输出的媒体流。

注意

不应使用 MFTRegister 函数注册驱动程序 MFT,因为它是设备专用的,而不是常规用途的 MFT。 有关注册表项的信息,请参阅本主题后面的安装和注册驱动程序 MFT 部分。

当应用启动视频捕获时,将实例化媒体基础源阅读器以提供视频流。 此媒体源从设备注册表项读取注册表值。 如果在注册表值中找到驱动程序 MFT COM 类的 CLSID,源读取器将实例化驱动程序 MFT 并将其插入媒体管道。

除了 UWP 设备应用外,还可使用以下 API 访问与之关联的设备捕获视频时的驱动程序 MFT 功能:

  • 在使用 HTML 的 UWP 应用中使用 HTML5 <视频>标记。 驱动程序 MFT 启用的转换会影响使用<视频>元素播放的视频,如以下代码示例所示:

    var video = document.getElementById('myvideo');
        video.src = URL.createObjectURL(fileItem);
        video.play();
    
  • 使用 Windows 运行时的 UWP 应用中的 Windows.Media.MediaCapture API。 有关如何使用此 API 的详细信息,请参阅媒体捕获示例。

  • 媒体基础的源读取器,用于处理媒体数据的应用。 调用 IMFSourceReaderEx::GetTransformForStream 时,驱动程序 MFT 将作为第一个 (0) MFT 向应用程序公开。 将返回的类别为 MFT_CATEGORY_VIDEO_EFFECT

    source reader's role in media capture.

多引脚相机

如果你使用的是三引脚或其他多引脚相机,请参阅多引脚相机上的驱动程序 MFT 的注意事项

驱动程序 MFT 实现

本部分提供有关实现驱动程序 MFT 的信息。 有关与 UWP 设备应用一起使用的驱动程序 MFT 的完整示例,请参阅驱动程序 MFT 示例。

开发工具

需要 Microsoft Visual Studio Professional 或 Microsoft Visual Studio Ultimate。

驱动程序 MFT 特征

驱动程序 MFT 按流实例化。 对于相机支持的每个流,都会实例化 MFT 实例并将其连接到该流。 驱动程序 MFT 只能有一个输入流和一个输出流。 驱动程序 MFT 可以是同步 MFT 或异步 MFT。

相机与驱动程序 MFT 之间的通信

要在媒体源和驱动程序 MFT 之间启用双向通信,请在驱动程序 MFT 的输入流属性存储中将指向源流的属性存储的指针设置为 MFT_CONNECTED_STREAM_ATTRIBUTE。 这通过通过在驱动程序 MFT 中公开 MFT_ENUM_HARDWARE_URL_Attribute 来启用的握手过程进行,如以下示例所示:

HRESULT CDriverMft::GetAttributes(IMFAttributes** ppAttributes)
{
    HRESULT hr = S_OK;
    if (NULL == ppAttributes)
    {
       return E_POINTER; 
    };
        if(!m_pGlobalAttributes) {
           MFCreateAttributes(&m_pGlobalAttributes, 1);
           m_pGlobalAttributes-> 
             SetString(MFT_ENUM_HARDWARE_URL_Attribute, L"driverMFT");
        }
        *ppAttributes = m_pGlobalAttributes;
        (*ppAttributes)->AddRef();
        return S_OK;
}

在此示例中,驱动程序 MFT 的属性存储中的 MFT_CONNECTED_STREAM_ATTRIBUTE 设置为指向设备源流的属性存储。 有关如何设置相机与 MFT 之间的通信的更多详细信息,请参阅硬件握手序列

如何访问设备源信息

下面的代码示例演示驱动程序 MFT 如何从其输入属性存储中获取指向源转换的指针。 然后,驱动程序 MFT 可以使用源指针获取设备源信息。

if(!m_pSourceTransform && m_pInputAttributes) {

          m_pInputAttributes->
              GetUnknown( MFT_CONNECTED_STREAM_ATTRIBUTE,
              IID_PPV_ARGS(&pSourceAttributes));
          pSourceAttributes-> 
              GetUnknown(
              MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT,            
              IID_PPV_ARGS(&pUnk)));
          pUnk->QueryInterface(__uuidof(IMFTransform), 
              (void**)&m_pSourceTransform));
      }
      if (m_pSourceTransform) {
         // Put code to get device source information here.         
      }

如何实现直通模式

要将驱动程序 MFT 置于直通模式,请为输入和输出流指定相同的媒体类型。 MFT 上的 ProcessInputProcessOutput 调用仍将进行。 是否在直通模式下进行任何处理,取决于驱动程序 MFT 的实现。

要包含的头文件

你需要包含驱动程序 MFT 必须实现的 IInspectableIMFTransform 方法的头文件。 有关要包含的头文件列表,请参阅 UWP 相机设备应用示例的 SampleMFT0 目录中的 stdafx.h

// required for IInspectable
#include <inspectable.h>

如何实现 IInspectable

用于相机 UWP 设备应用的驱动程序 MFT 必须实现方法 IInspectable,以便 Microsoft Store 设备应用可以在启动时访问指向驱动程序 MFT 的指针。 驱动程序 MFT 应按以下方式实现方法 IInspectable

  • IInspectable::GetIids 应在 iids 输出参数中返回 null,在 iidCount 输出参数中返回 0。

  • IInspectable::GetRuntimeClassName 应在输出参数中返回 null。

  • IInspectable::GetRuntiGetTrustLevel 应在输出参数中返回 TrustLevel::BaseTrust

下面的代码示例演示 IInspectable 方法在示例驱动程序 MFT 中的实现方式。 这段代码可在示例 SampleMFT0 目录中的 Mft0.cpp 文件中找到。

// Mft0.cpp
STDMETHODIMP CMft0::GetIids( 
    /* [out] */ __RPC__out ULONG *iidCount,
    /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*iidCount) IID **iids)
{
    HRESULT hr = S_OK;
    do {
        CHK_NULL_PTR_BRK(iidCount);
        CHK_NULL_PTR_BRK(iids);
        *iids = NULL;
        *iidCount = 0;
    } while (FALSE);

    return hr;
}

STDMETHODIMP CMft0::GetRuntimeClassName( 
    /* [out] */ __RPC__deref_out_opt HSTRING *className)
{
    HRESULT hr = S_OK;
    do {
        CHK_NULL_PTR_BRK(className);
        *className = NULL;
    } while (FALSE);

    return hr;
}

STDMETHODIMP CMft0::GetTrustLevel( 
    /* [out] */ __RPC__out TrustLevel *trustLevel)
{
    HRESULT hr = S_OK;
    do {
        CHK_NULL_PTR_BRK(trustLevel);
        *trustLevel = TrustLevel::BaseTrust;
    } while (FALSE);

    return hr;
}

COM 实现

驱动程序 MFT 实现的每个接口都应实现和派生自 IUnknown,这样才能正确地封送到相机的 UWP 设备应用中。 下面是驱动程序 MFT 的示例 .idl 文件,可以说明这一点。

// SampleMft0.idl : IDL source for SampleMft0
//

// This file will be processed by the MIDL tool to
// produce the type library (SampleMft0.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";
import "Inspectable.idl";
import "mftransform.idl";
[
    object,
    uuid(F5208B72-A37A-457E-A309-AE3060780E21),
    oleautomation,
    nonextensible,
    pointer_default(unique)
]
interface IMft0 : IUnknown{
    [id(1)] HRESULT UpdateDsp([in] UINT32 uiPercentOfScreen);
    [id(2)] HRESULT Enable(void);
    [id(3)] HRESULT Disable(void);
    [id(4)] HRESULT GetDspSetting([out] UINT* puiPercentOfScreen, [out] BOOL* pIsEnabled);
};
[
    uuid(DE05674A-C564-4C0E-9B7C-E1519F7AA767),
    version(1.0),
]
library SampleMft0Lib
{
    importlib("stdole2.tlb");
    [
        uuid(7BB640D9-33A4-4759-B290-F41A31DCF848)      
    ]
    coclass Mft0
    {
        [default] interface IMft0;
        interface IInspectable;
        interface IMFTransform;
    };
};

注意

驱动程序 MFT 是一个常规 COM 类,可以使用 CoCreateInstance 创建。 不应使用 MFTRegister 函数注册它,因为它不是常规用途 MFT。

创建代理

驱动程序 MFT 是进程外服务器。 要在 UWP 设备应用中使用它,必须在代理中提供封送支持,以便可以跨进程边界使用驱动程序 MFT 接口。 可以在驱动程序 MFT 示例中找到此示例。 此示例使用 MIDL 编译器生成无存根代理。

向应用公开驱动程序 MFT

要在 C# 或 JavaScript 中编写与驱动程序 MFT 交互的 UWP 设备应用,需要在 Microsoft Store 设备应用的 Microsoft Visual Studio 项目中创建其他组件。 此组件是一个包装器,用于在对 Microsoft Store 设备应用可见的 Windows 运行时组件中公开驱动程序 MFT 接口。

适用于相机的 UWP 设备应用示例的包装区子项目提供了一个示例,演示如何将驱动程序 MFT 公开到 Windows 运行时,以便可以从 C# 或 JavaScript 中实现的 UWP 设备应用使用它。 它旨在与驱动程序 MFT 示例协同工作。 有关安装、运行和测试示例的分步指南,请参阅驱动程序 MFT 示例页。

安装和注册驱动程序 MFT

本部分列出了安装驱动程序 MFT 的步骤:

  1. 驱动程序 MFT DLL 必须安装在以下位置的子目录中:

    • %SystemDrive%\Program Files\
  2. 相机安装程序通过在驱动程序 MFT DLL 上调用 regsvr32 或者为安装程序用于注册的 DLL 提供驱动程序清单 (.man) 文件来注册驱动程序 MFT。

  3. 在相机的注册表项中设置 CameraPostProcessingPluginCLSID 值。 INF 文件应将 CameraPostProcessingPluginCLSID 值设置为驱动程序 MFT 类的 CLSID GUID,从而在设备的设备类注册表项值中指定驱动程序 MFT 的 CLSID。 下面是 INF 文件条目中的一个示例,用于填充相机的注册表项:

KSCATEGORY_VIDEO_CAMERA:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{E5323777-F976-4f5b-9B55-B94699C46E44}\##?#USB#VID_045E&PID_075D&MI_00#8&23C3DB65&0&0000#{E5323777-F976-4f5b-9B55-B94699C46E44}\#GLOBAL\Device Parameters]
"CLSID"="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
"FriendlyName"="USB Video Device"
"RTCFlags"=dword:00000010
"CameraPostProcessingPluginCLSID"="{3456A71B-ECD7-11D0-B908-00A0C9223196}" 
KSCATEGORY_CAPTURE:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{ 65E8773D-8F56-11D0-A3B9-00A0C9223196}\##?#USB#VID_045E&PID_075D&MI_00#8&23C3DB65&0&0000#{65E8773D-8F56-11D0-A3B9-00A0C9223196}\#GLOBAL\Device Parameters]
"CLSID"="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
"FriendlyName"="USB Video Device"
"RTCFlags"=dword:00000010
"CameraPostProcessingPluginCLSID"="{3456A71B-ECD7-11D0-B908-00A0C9223196}"

注意

KSCATEGORY_VIDEO_CAMERA 建议用于相机。 通常只需要其中一个注册表项,具体取决于设备的注册方式。

将应用与相机相关联

本部分包含有关在设备元数据和 Windows 注册表中标识相机所需的步骤的信息。 此元数据使你能够配对 UWP 设备应用并标识应用,以便在相机首次连接时无缝下载。

更新

首次安装应用后,如果用户下载应用的更新版本,则更新会自动集成到相机捕获体验中。 但是,不会自动下载更新。 用户必须从 Microsoft Store 下载其他应用更新,因为应用仅在首次连接时自动安装。 UWP 设备应用的主页可提供可用更新通知,并提供下载更新的链接。

重要

更新后的应用应能与通过 Windows 更新发布的任何更新后的驱动程序配合使用。

多个相机

多个相机型号可在其设备元数据中声明相同的 UWP 设备应用。 如果系统具有多个内部嵌入式相机,则相机必须共享相同的 UWP 设备应用。 该应用包括用于确定正在使用的相机的逻辑,并且可以在其“更多”选项体验中为每个相机显示不同的 UI。 有关自定义该体验的详细信息,请参阅如何自定义相机选项

内部相机

适用于内部相机的 UWP 设备应用有资格从 Microsoft Store 自动安装,但建议预安装它们,以便获得最无缝的用户体验。 要支持内部相机并将 UWP 设备应用与之关联,还需要额外的步骤。 有关详细信息,请参阅识别内部相机的位置

创建设备元数据包

对于内部和外部相机,需要创建设备元数据包。 将相机的 UWP 设备应用提交到 Microsoft Store(或者在内部相机的情况下使用 OPK 预安装)时,除了应用本身外,还需要提供包含以下内容的元数据:

  • 应用程序发布者名称

  • 应用程序包名称

  • 应用程序元素标识符

  • 设备体验标识符

有关如何使用设备元数据将应用与设备关联的详细信息,请参阅构建 UWP 设备应用

构建 UWP 设备应用

UWP 设备应用的自动安装

硬件握手序列(硬件 MFT)

AVStream 微型驱动程序设计指南

适用于相机的 UWP 设备应用示例

驱动程序 MFT 示例