使用 Media Foundation 对 Direct X 表面进行编码

问题描述 投票:0回答:2

我正在尝试使用 MediaFoundation API 对视频进行编码,但在将示例推送到 SinkWriter 时遇到问题。

我正在通过桌面复制 API 获取要编码的帧。我最终得到的是 ID3D11Texture2D,其中包含桌面图像。

我正在尝试创建一个包含此表面的 IMFVideoSample,然后将该视频样本推送到 SinkWriter。

我尝试过以不同的方式解决这个问题:

  • 我调用了

    MFCreateVideoSampleFromSurface(texture, &pSample)
    ,其中纹理是ID3D11Texture2D,填充了SampleTime和SampleDuration,然后将创建的样本传递给SinkWriter。
    SinkWriter 返回了 E_INVALIDARG。

  • 我尝试通过传递 nullptr 作为第一个参数来创建示例,并使用 MFCreateDXGISurfaceBuffer 自己创建缓冲区,然后将生成的缓冲区传递到示例中。
    那也没用。

  • 我通读了 MediaFoundation 文档,但找不到有关如何从 DirectX 纹理创建示例的详细信息。

我没有什么可尝试的了。
有没有人以前使用过这个 API,并且能想到我应该检查的事情,或者有什么方法可以调试这个 API?

c++ directx-11 ms-media-foundation dxgi
2个回答
2
投票

首先你应该学会使用

mftrace
工具。 很可能,它会立即告诉您问题所在。

但我的猜测是,可能会出现以下问题。

  1. 可能除了 SampleTime / SampleDuration 之外还需要一些其他属性。

  2. 可能,SinkWriter 需要一个可以在 CPU 上读取的纹理。要解决此问题,当框架可用时,创建相同格式和大小的暂存纹理,调用 CopyResource 将桌面复制到暂存纹理,然后将该暂存纹理传递给 MF。

  3. 即使您使用硬件编码器,因此CPU永远不会尝试读取纹理数据,我认为直接将桌面纹理传递给MF也不是一个好主意。

当您为样本设置D3D纹理时,不会复制任何数据,样本仅保留纹理。

MF 异步工作,如果愿意的话,它可以在其拓扑节点中缓冲多个样本。

DD 同步为您提供数据,您只能在 AcquireNextFrame 和 ReleaseFrame 调用之间访问纹理。


0
投票

如果它对某人有帮助,它可以通过调用 MF.CreateDXGISurfaceBuffer(surface, 0, false, &dstBuffer) 来工作,但是,这似乎没有在任何地方指定,您还必须调用 dstBuffer.SetCurrentLength(length) 来设置表面缓冲区的适当长度。

© www.soinside.com 2019 - 2024. All rights reserved.