Media Foundation手动构建拓扑:如何获取Media Session创建的D3D11设备?
解决Media Session场景下获取D3D11设备并配置MPEG2解码器的思路
针对你遇到的问题——手动加载MPEG2解码器时需要复用Media Session中视频渲染器创建的D3D11设备,这里有几个实用的方向和步骤:
核心思路:复用EVR的D3D11设备/管理器
Media Session里的增强视频渲染器(EVR)会自动创建D3D11设备,你不需要从零创建,关键是拿到它的设备或对应的设备管理器,再传递给解码器。
步骤1:找到拓扑中的EVR节点
默认拓扑加载器生成的拓扑里肯定包含EVR渲染节点,你需要遍历拓扑节点定位它:
IMFTopology* pTopology = /* 你的拓扑对象 */; UINT32 nodeCount = 0; pTopology->GetNodeCount(&nodeCount); IMFTopologyNode* pEVRNode = nullptr; for (UINT32 i = 0; i < nodeCount; i++) { IMFTopologyNode* pNode = nullptr; if (SUCCEEDED(pTopology->GetNode(i, &pNode))) { MF_TOPOLOGY_NODE_TYPE nodeType; pNode->GetNodeType(&nodeType); // 判断是否是渲染节点(EVR属于这类) if (nodeType == MF_TOPOLOGY_RENDERER_NODE) { pEVRNode = pNode; break; } pNode->Release(); } }
步骤2:从EVR节点获取D3D11设备管理器
EVR节点支持IMFGetService接口,你可以直接请求IDirect3DDeviceManager11(这是D3D11对应的设备管理器,别再用旧的9版本了):
IDirect3DDeviceManager11* pD3D11DeviceManager = nullptr; IMFGetService* pGetService = nullptr; if (SUCCEEDED(pEVRNode->QueryInterface(IID_PPV_ARGS(&pGetService)))) { // 请求D3D11设备管理器服务 HRESULT hr = pGetService->GetService(IID_IDirect3DDeviceManager11, (void**)&pD3D11DeviceManager); pGetService->Release(); }
步骤3:将设备管理器传递给MPEG2解码器
拿到IDirect3DDeviceManager11后,把它设置到解码器的属性中,解码器就能自动复用这个管理器关联的D3D11设备:
IMFActivate* pMPEG2DecoderActivate = /* 你的MPEG2解码器激活对象 */; pMPEG2DecoderActivate->SetUnknown(MF_SA_D3D11_DEVICE_MANAGER, pD3D11DeviceManager); // 之后再激活解码器实例 IMFTransform* pDecoder = nullptr; pMPEG2DecoderActivate->ActivateObject(IID_PPV_ARGS(&pDecoder));
备选方案:提前指定Media Session的D3D11设备
如果上面的方法遇到兼容性问题,你可以主动创建D3D11设备,让整个Media Session(包括解码器和渲染器)都用这个设备,反而更可控:
- 用
D3D11CreateDevice创建你自己的D3D11设备
- 用
- 用
MFCreateDXGIDeviceManager创建IDirect3DDeviceManager11,再调用ResetDevice把你的D3D11设备关联进去
- 用
- 创建Media Session时,设置
MF_SESSION_D3D11_DEVICE_MANAGER属性为这个设备管理器
- 创建Media Session时,设置
- 同样给MPEG2解码器设置
MF_SA_D3D11_DEVICE_MANAGER属性为同一个管理器
- 同样给MPEG2解码器设置
这种方式不需要去获取EVR的设备,所有组件都共享你创建的设备,避免了设备不兼容的问题。
关键注意点
- 一定要用
IDirect3DDeviceManager11,别再纠结旧的IDirect3DDeviceManager9,后者是D3D9的,和你要的D3D11不兼容 - 确保你的MPEG2解码器确实支持D3D11硬件加速(mpeg2videoextension应该是支持的)
- 操作接口时要注意正确释放COM对象,避免内存泄漏
内容的提问来源于stack exchange,提问作者Jerry Davis
相关产品推荐
相关产品推荐

