2016-07-25 115 views
5

我正尝试使用MediaFoundation API对视频进行编码,但我遇到了将示例推送到SinkWriter的问题。使用Media Foundation对Direct X表面进行编码

我正在通过Desktop Duplication API获取要编码的帧。我最终得到的是带有桌面图像的ID3D11Texture2D。

我试图创建一个包含此表面的IMFVideoSample,然后将该视频示例推送到SinkWriter。

我试着去了解这个以不同的方式:

  • 我叫MFCreateVideoSampleFromSurface(texture, &pSample)其中质地的ID3D11Texture2D,填补了SampleTime和SampleDuration,然后通过创建样品到SinkWriter。
    SinkWriter返回了E_INVALIDARG。

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

  • 我阅读了MediaFoundation文档,找不到有关如何从DirectX纹理创建样本的详细信息。

我跑出来的东西尝试。
有没有人在那里使用过这个API,并且可以想到我应该检查的东西,或者我可以怎样去调试这个东西?

+0

我认为你使用MFCreateVideoSampleFromSurface和MFCreateDXGISurfaceBuffer犯了一个错误。这些函数创建用于写入DirectX和可视化表面的缓冲区,并使用接口“IMF2DBuffer”创建对象,但编码器和编写器需要具有“IMFMediaBuffer”的对象。他们无法理解'IMF2DBuffer'。尝试使用函数'MFCreateSampleCopierMFT' - 它创建的MFT对象用于从[IMFMediaBuffer]复制到[MSDN]上的IMF2DBuffer(https://msdn.microsoft.com/en-us/library/windows/desktop/dd388101(v = vs.85)的.aspx)。可能是它可以做倒转的工作!?! –

+0

你确定吗? 查看“MFCreateDXGISurfaceBuffer”的文档,它指出它返回一个指向IMFMediaBuffer的指针。 –

+0

您可以尝试通过'MFCreateDXGISurfaceBuffer'中的'IMFMediaBuffer'缓冲区获取数据。 –

回答

1

首先你应该学会使用mftrace tool。 很可能,它会马上告诉你这个问题。

但我的猜测是,下列问题可能发生。

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

  2. 也许,SinkWriter需要一个可以在CPU上读取的纹理。为了解决这个问题,当一个框架可用时,创建一个相同格式+大小的分段纹理,调用CopyResource将桌面复制到分段纹理,然后将该分段纹理传递给MF。

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

当您为示例设置D3D纹理时,没有数据被复制到任何地方,该示例仅保留纹理。

MF工作异步,它可能会缓存其拓扑节点中的几个样本,如果他们想。

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

+0

我试图不要让太多问题陷入困境,但我在将它传递给MF之前先复制桌面纹理,方法是获取桌面纹理描述符并在使用CopyResource之前使用该纹理创建新纹理。 但是,感谢lor的mftrace指针,会看看那个。 –

+0

我使用了mfctrace,并发现发送到水槽的样本被报告为0B大小,所以它们的创建出了问题。 –