Search code examples
c#directshowdirectshow.net

No video when using Enhanced Video Renderer


Situation:

Creating an decrypting filter with directshow. The graph is DecryptFileSource -> GDCL Mpeg-4 Demux -> FFDShow Video Decoder -> Enhanced Video Renderer

Issue:

  • GraphEdit: Shows the video, works fine.
  • GraphStudioNext: shows the video, works fine.
  • GraphEditPlus: Does not show the video, does not work.
  • Through Code: Does not work either. However if I replace the EVR with "Video Renderer" or "VMR9"

Another user had this issue here however his answer was vague. According to Roman (In the comments on the previous link) it requires a specific initialization. However I'm unsure how to go about specifically initializing it.

No Errors are thrown when I attempt create the graph through code. I have a seeking enabled and I can see that the IMediaPosition is working. Just no video is showing but the audio plays


Solution

  • I found the answer.

    1. Compile EVRPresenter.dll found in "Program Files\Microsoft SDKs\Windows\v6.1\Samples\Multimedia\MediaFoundation\EVRPresenter"

    2. Install the DLL "regsvr32 EVRPresenter.dll"

    3. Compile and include the MediaFoundation.dll into my product. Link here

    4. Instead of creating the object like I normally do

    Like this:

    IBaseFilter pEnhancedVideoRenderer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_EnhancedVideoRenderer));
    

    instead

            IBaseFilter pEVR = (IBaseFilter)new MediaFoundation.EVR.EnhancedVideoRenderer();
            hr = pGraph.AddFilter(pEVR, "Enhanced Video Renderer");
    
            MediaFoundation.EVR.IMFVideoDisplayControl m_pDisplay;
    
            InitializeEVR(pEVR, 1, out m_pDisplay);
    

    InitializeEVR:

    private void InitializeEVR(IBaseFilter pEVR, int dwStreams, out MediaFoundation.EVR.IMFVideoDisplayControl ppDisplay)
            {
                MediaFoundation.EVR.IMFVideoRenderer pRenderer;
                MediaFoundation.EVR.IMFVideoDisplayControl pDisplay;
                MediaFoundation.EVR.IEVRFilterConfig pConfig;
                MediaFoundation.EVR.IMFVideoPresenter pPresenter;
    
                // Before doing anything else, set any custom presenter or mixer.
    
                // Presenter?
                if (m_PresenterCLSID != Guid.Empty)
                {
                    Type type = Type.GetTypeFromCLSID(m_PresenterCLSID);
    
                    // An error here means that the custom presenter sample from
                    // http://mfnet.sourceforge.net hasn't been installed or
                    // registered.
                    pPresenter = (MediaFoundation.EVR.IMFVideoPresenter)Activator.CreateInstance(type);
    
                    try
                    {
                        pRenderer = (MediaFoundation.EVR.IMFVideoRenderer)pEVR;
    
                        pRenderer.InitializeRenderer(null, pPresenter);
                    }
                    finally
                    {
                        //Marshal.ReleaseComObject(pPresenter);
                    }
                }
    
                // Continue with the rest of the set-up.
    
                // Set the video window.
                object o;
                MediaFoundation.IMFGetService pGetService = null;
                pGetService = (MediaFoundation.IMFGetService)pEVR;
                pGetService.GetService(MediaFoundation.MFServices.MR_VIDEO_RENDER_SERVICE, typeof(MediaFoundation.EVR.IMFVideoDisplayControl).GUID, out o);
    
                try
                {
                    pDisplay = (MediaFoundation.EVR.IMFVideoDisplayControl)o;
                }
                catch
                {
                    Marshal.ReleaseComObject(o);
                    throw;
                }
    
                try
                {
                    // Set the number of streams.
                    pDisplay.SetVideoWindow(this.Handle);
    
                    if (dwStreams > 1)
                    {
                        pConfig = (MediaFoundation.EVR.IEVRFilterConfig)pEVR;
                        pConfig.SetNumberOfStreams(dwStreams);
                    }
    
                    // Set the display position to the entire window.
                    Rectangle r = this.ClientRectangle;
                    MediaFoundation.Misc.MFRect rc = new MediaFoundation.Misc.MFRect(r.Left, r.Top, r.Right, r.Bottom);
    
                    pDisplay.SetVideoPosition(null, rc);
    
                    // Return the IMFVideoDisplayControl pointer to the caller.
                    ppDisplay = pDisplay;
                }
                finally
                {
                    //Marshal.ReleaseComObject(pDisplay);
                }
                m_pMixer = null;
            }