我正在尝试让 HEVC 视频解码器与 Media Foundation 一起使用。我所拥有的正在工作 - 大约六帧 - 然后 MFTransform::ProcessOutput 函数无限期地挂起,并出现以下调用堆栈:
NtWaitForMultipleObjects()
WaitForMultipleObjectsEx()
CDXVAFrameManager::WaitOnSampleReturnedByRenderer(void)
CH265DecoderTransform::ProcessOutput(unsigned long,unsigned long,struct _MFT_OUTPUT_DATA_BUFFER *,unsigned long *)
我认为这是因为我没有发布我应该发布的东西。但我不知道是什么。
我有一个 MFTransform 视频解码器和视频处理器,分别用于解码 HEVC 数据和从 NV12 转换为 RGB。它们通过发送 MFT_MESSAGE_SET_D3D_MANAGER 消息连接到用于渲染的 DirectX 11 设备。在此配置中,他们自己创建样本(MFT_OUTPUT_STREAM_PROVIDES_SAMPLES 在 MFT_OUTPUT_STREAM_INFO 结构中设置),并在完成后释放它们。
正如我上面提到的,这是有效的。至少有几帧。视频样本被解码为 NV12、转换为 RGB 并显示。
我正在查询
D3D11Multithread
对象并将 TRUE
传递给 SetMultithreadProtected
。这没有明显的区别。我是否需要通过 Enter
/Leave
调用来保护对 DirectX 的每次调用?
我在这里找到了这个问题:https://social.msdn.microsoft.com/Forums/azure/en-US/fd399107-69d3-4b55-81a9-9ab6db089cfa/video-decoding-with-custom-mft-or- msft-h264-decoder-mft?forum=mediafoundationdevelopment 具有完全相同的问题,但用相当神秘的方式解决了:
...通过释放 Windows 内部分配的指针来实现此功能。
但是我不知道哪些指针意味着什么。
在解码器挂起之前,解码器的
ProcessOutput
仅返回S_OK
。如果我在解码器挂起之前暂停它,然后运行帧处理器,它会返回 MF_E_SAMPLEALLOCATOR_EMPTY
,这表明 RGB 样本中的某些内容没有被清理。
但是什么?
据我所知,我的代码中没有资源泄漏。我将发布由媒体基金会转换创建的所有样本。 (当我的智能指针类稍后尝试合法释放它们时,尝试强制释放它们会导致崩溃。)
我需要查询示例缓冲区并释放它们吗?或者它们包含的表面?通过调用
RemoveAllBuffers
强制删除样本缓冲区没有任何区别。
我注意到解码器返回一个
CPooledSample
样本,而视频处理器返回一个CMFTrackedSample
,那么解码器是否没有收到样本已发布的通知?这是我应该做的事情吗?
编辑: 我的代码相关部分的副本可以在这里找到:https://pastebin.com/Y6p30MRG
好吧,这是(我相信任何人都不会感到惊讶)我的一个愚蠢的错误,以及媒体基金会对我的错误的极其糟糕的反应:
我没有打电话
MFStartup
。
但事实上,媒体基金会并没有费心告诉我这一点,只是假装一切都很好(直到事实并非如此),坦率地说,这是一个令人尴尬的糟糕“设计”。
一旦我开始打电话
MFStartup
,其他一切就开始按预期工作。