5

I am trying to write an EVR for Media Foundation using DirectX 11 on Windows 10 (Desktop). The only one solution I have found so far is here Unfortunately I don't know (as many others) how to correctly use it. Does somebody can point me to the right direction on how to combine MF with DirectX 11/12 please?

I am using the code for activate my EVR:

hr = MFCreateVideoRendererActivate(hwndVideo, &pRendererActivate);
hr = pRendererActivate->SetGUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID, CLSID_DX11VideoRenderer);

I came to the point where MF asks for GetDeviceID and an exception is raised in kernel.dll. I think that there is a mismatch between a mixer and renderer device. Default device for them is DX9. In my example I must provide a DirectX 11 device CLSID.

  • 2
    DX11VideoRenderer is an entirely new renderer. You don't use EVR with it. In order to use it in your project you need to create it via the CreateDX11VideoRenderer(Activate) functions that can be located in DX11VideoRenderer.h file.You can then use the Activate in your Media Session for instance. In order to build the sample you need Windows 8.1 SDK. I think it is sintalled with Visual Studio 2013 for instance. Topoedit that comes with this SDK can be used for testing the DX11 Video Renderer. – VuVirt Jan 13 '17 at 18:34
  • 1
    It appears that the EVR concept is deprecated in D3D11 in favor of simply writing a monolithic IMFMediaSink that does whatever you want to terminate the stream. This makes sense when you consider that really, all the MS-provided EVR was doing is coordinating between its so-called mixer and presenter plug-ins, and there's no longer any need for the former given the layer and viewport features provided directly in D3D11 itself. That's why the DX11VideoRenderer sample from MS implements IMFMediaSink and makes no mention of IMFVideoPresenter. Just my impression; I'm still trying to figure it out. – Glenn Slayden May 01 '17 at 05:01
  • Having said that, it may be possible to still use the EVR on D3D11, but as noted [here](https://msdn.microsoft.com/en-us/library/windows/desktop/ms703065(v=vs.85).aspx), you would need to replace **both** mixer and presenter with custom components, at which point the EVR is adding little value to the scenario, right? – Glenn Slayden May 01 '17 at 05:17
  • 1
    The following link seems to further corroborate that you should be able to use the system-provided EVR to drive DIrect3D 11 if you supply both presenter **and** mixer, as long as you don't identify them as IID_IDirect3DDevice9: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2aafe7a-aff8-44c2-b1ba-03de663e02db – Glenn Slayden May 13 '17 at 08:08

2 Answers2

1

DX11VideoRenderer is a good example to show how to use Dx11 based presenter. However there aren't much code snippet to demonstrate how to use it.

There are two ways you could look into:

  1. Register the compiled DX11VideoRenderer COM CLSID using regsvr32, and add it in the TopoEdit.
  2. Use without register.

    • Call LoadLibrary() to the dll.
    • Call GetProcAddress() to get pfn of DllGetClassObject().
    • Call above pfn with CLSID_DX11VideoRenderer and IID_IClassFactory to retrieve the media sink factory.
    • Use media sink factory to create media sink.
    • Add media sink to topology.

Code snippet:

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();
}
Ivellios
  • 100
  • 7
1

In the year of 2023, a DX11VideoRenderer sample can be found here. It is still a useful piece of code for pure Win32 (non-WinRT) projects. The section Run the sample of the project README file advices the user to build and register the DLL, then run the topoedit.exe from the same the Windows SDK, and select "Add DX11 Video Renderer" from the Topology menu of topoedit.

Having no Windows SDK for Windows 7 at hand, I built the topoedit.exe from the code of the topoedit sample. No trace of the menu line "Add DX11 Video Renderer" found -- neither in the running executable, nor in the code.

I updated the topoedit code so that it received the promised 'Add DX11VR' menu line, on analogy with already available 'Add EVR'. You can use this project as a starting point in your study of how to combine MF with DirectX 11.

Notice that you cannot create an activate object for DX11VideoRenderer activation with MFCreateVideoRendererActivate: this method only suitable for activating the Enhanced Video Renderer, which is based off DirectX 9. To activate DX11VideoRenderer, you use the CreateDX11VideoRendererActivate method, which is exported from DX11VideoRenderer.dll.

If you try and add DX11VideoRenderer thru a menu line 'Add Custom Sink' of topoedit.exe, you would run into the familiar problem of an absent D3D11Device. The proper way to activate DX11VideoRenderer is to create an activation object with the CreateDX11VideoRendererActivate method and use the method ActivateObject of the activation object to create IMFMediaSink object.

V.V.T
  • 231
  • 1
  • 7