媒体基础架构EVR和DirectX 11

5
我正在尝试使用DirectX 11在Windows 10桌面上编写一个使用Media Foundation的EVR。 到目前为止,我找到的唯一解决方案是这里。 不幸的是,我不知道(和许多其他人一样)如何正确使用它。 请问有人能指导我如何将MF与DirectX 11/12结合使用吗?
我正在使用代码激活我的EVR:
hr = MFCreateVideoRendererActivate(hwndVideo, &pRendererActivate);
hr = pRendererActivate->SetGUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, CLSID_DX11VideoRenderer);

我来到了MF请求GetDeviceID的地方,但是在kernel.dll中引发了一个异常。我认为混合器和渲染设备之间存在不匹配。它们的默认设备是DX9。在我的例子中,我必须提供DirectX 11设备CLSID。


2
DX11VideoRenderer是全新的渲染器。您不需要使用EVR。为了在项目中使用它,您需要通过CreateDX11VideoRenderer(Activate)函数在DX11VideoRenderer.h文件中创建它。然后,您可以在媒体会话中使用Activate。为了构建示例,您需要Windows 8.1 SDK。例如,我认为它已经与Visual Studio 2013一起安装了。此SDK附带的Topoedit可用于测试DX11视频渲染器。 - VuVirt
1
在D3D11中,EVR概念似乎已经被弃用,而是倾向于编写一个单体的IMFMediaSink来终止流。如果你考虑到所有由MS提供的EVR所做的工作都是协调其所谓的混合器和呈现器插件之间的关系,那么这就是有道理的,而且鉴于D3D11本身直接提供了层和视口功能,以前的混合器插件也不再需要了。这就是为什么MS的DX11VideoRenderer示例实现了IMFMediaSink,并没有提到IMFVideoPresenter。这只是我的印象;我还在努力弄清楚它。 - Glenn Slayden
话虽如此,在D3D11上仍然可能使用EVR,但正如这里所指出的那样,您需要用自定义组件替换混合器和呈现器,此时EVR对场景的增益就很小了,对吧? - Glenn Slayden
1
以下链接似乎进一步证实,只要您提供了呈现器和混合器,并且没有将它们标识为IID_IDirect3DDevice9,就应该能够使用系统提供的EVR来驱动Direct3D 11: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2aafe7a-aff8-44c2-b1ba-03de663e02db - Glenn Slayden
2个回答

1
在2023年,可以在这里找到DX11VideoRenderer示例。对于纯Win32(非WinRT)项目,它仍然是一段有用的代码。项目README文件的运行示例部分建议用户构建和注册DLL,然后从相同的Windows SDK运行topoedit.exe,并从topoedit的拓扑菜单中选择“添加DX11视频渲染器”。
由于手头没有适用于Windows 7的Windows SDK,我从topoedit示例的代码中构建了topoedit.exe。在运行的可执行文件或代码中都没有找到“添加DX11视频渲染器”的菜单行的痕迹。

更新了topoedit代码,以便它可以像已有的“Add EVR”一样接收承诺的“Add DX11VR”菜单行。您可以将此项目用作学习如何将MF与DirectX 11结合的起点。

请注意,您无法使用MFCreateVideoRendererActivate创建DX11VideoRenderer激活对象:该方法仅适用于激活基于DirectX 9的增强视频渲染器。要激活DX11VideoRenderer,您需要使用从DX11VideoRenderer.dll导出的CreateDX11VideoRendererActivate方法。

如果您尝试通过topoedit.exe的“Add Custom Sink”菜单行添加DX11VideoRenderer,则会遇到缺少D3D11Device的熟悉问题。激活DX11VideoRenderer的正确方法是使用CreateDX11VideoRendererActivate方法创建激活对象,并使用激活对象的ActivateObject方法创建IMFMediaSink对象。


1

DX11VideoRenderer是一个很好的示例,展示如何使用基于Dx11的Presenter。然而,没有太多的代码片段来演示如何使用它。

你可以探索两种方式:

  1. 使用regsvr32注册编译后的DX11VideoRenderer COM CLSID,并将其添加到TopoEdit中。
  2. 不注册使用。

    • 调用LoadLibrary()加载dll。
    • 调用GetProcAddress()获取DllGetClassObject()的pfn。
    • 使用上述pfn和CLSID_DX11VideoRenderer以及IID_IClassFactory检索媒体接收器工厂。
    • 使用媒体接收器工厂创建媒体接收器。
    • 将媒体接收器添加到拓扑中。

代码片段:

typedef HRESULT(_stdcall *PFN_GetClassObject)(REFCLSID, REFIID, LPVOID*);
HMODULE hSink = NULL;
PFN_GetClassObject pfn = NULL;
HRESULT hr = E_FAIL;
IClassFactory *pMediaSinkFactory = NULL;
IMFMediaSink *pMediaSink = NULL;

hSink = ::LoadLibraryEx(L“DX11VideoRenderer.dll”, 
            NULL, 
            LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);

if(hSink)
    pfn = (PFN_GetClassObject)GetProcAddress(
            hSink, 
            "DllGetClassObject");

if(pfn)
    hr = pfn(CLSID_DX11VideoRenderer, 
            IID_IClassFactory, 
            (LPVOID*)&pMediaSinkFactory);

if(pMediaSinkFactory){
    pMediaSinkFactory->CreateInstance(NULL, 
        __uuidof(IMFMediaSink), 
        (LPVOID*)&pMediaSink);
    pMediaSinkFactory->Release();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接