使用媒体基础对通过桌面复制获得的 D3D 图面进行编码

Encoding a D3D Surface obtained through Desktop Duplication using Media Foundation

本文关键字:D3D 编码 复制 媒体 桌面      更新时间:2023-10-16

我想对桌面复制 API 帧进行编码,以便在使用 Media Foundation 对其进行编码后通过网络发送。当我调用IMFTransform::P rocessInput时,我遇到了一个E_NOTIMPL错误,让我有点蒙在鼓里。

这些是我到目前为止所做的步骤,我正在详细说明它们,因为我花了几天时间从网络上稀缺的分散信息中收集所有内容,所以如果它得到解决,它有望帮助其他人。以下所有内容都符合S_OK:

  • 我正在通过复制API获取表面,使用MFCreateVideoSampleFromSurface从中创建IMFSample
  • 我正在使用 IMFActivate::ActivateObject 从使用 MFT_CATEGORY_VIDEO_ENCODER 和 MFVideoFormat_H264 初始化的 IMFActivate 获得视频编码器
  • 我正在使用比特率、帧率、纵横比等在输入上初始化 IMFMediaType,最重要的是:MFVideoFormat_NV12,似乎是唯一一个使用桌面复制 API DXGI_FORMAT_B8G8R8A8_UNORM的人。
  • 我在输出上设置 IMFMediatype 与上述相同,除了MFVideoFormat_H264作为SUB_TYPE。
  • 我用上面的 2 调用 IMFTransform::SetOutputType,然后调用 IMFTransform::SetInputType。
  • 我将 IMFSample 时间设置为 0,因为它似乎不是由 MFCreateVideaSampleFromSurface 设置的。还使用 MFFrameRate设置为使用输入 FPS 设置每帧平均时间的采样持续时间。

在所有这些之后,我调用MFTransform::P rocessInput与上面创建的IMFSample,并得到一个"未实施E_NOTIMPL"作为HRESULT。我已经读到我应该为上面的 IMFTransform 编码器设置一个 IMFDXGIDeviceManager,所以我使用:

  • MFCreateDXGIDeviceManager从我的ID3D11Device与桌面复制API和任意重置令牌一起使用。
  • 使用设备和令牌执行 IMFDXGIDeviceManager::ResetDevice。
  • 调用IMFTransform::P rocessMessage(MFT_MESSAGE_SET_D3D_MANAGER,reinterpret_cast(m_pDXDeviceManager)。

在最后一步中,我在 HRESULT 上得到了另一个"未实现E_NOTIMPL",这就是我不知道我做错了什么或需要做什么的地方。

首先要做的是检查编码器是否MF_SA_D3D11_AWARE

我认为它没有,阅读这个:MFT_MESSAGE_SET_D3D_MANAGER

如果 MFT 不支持此消息,则应返回E_NOTIMPL

但有一点很奇怪:DirectX Surface Buffer

调用 IMFMediaBuffer::Lock。通常不建议这样做,因为它会强制对象从 Direct3D 图面复制内存,然后再复制回来。

进程输入应该已经工作了。