Skip to main content

 none
Disable Video Auto-processing with EVR RRS feed

  • Question

  • My program uses Media Foundation to play video. It uses a Media Foundation session, topology, media source and the Enhanced Video Renderer (EVR) to play video in a window, as described in "How to Play Media Files with Media Foundation" in the docs. It works great except for one issue.

    Unless the user changes the default graphics driver settings, some graphics drivers automatically introduce additional video processing, such as "contrast enhancement" and "skin tone mapping." While this processing might be desirable in some programs, my program is a video editor used for color grading so it is essential that these effects be disabled. This Microsoft note describes one way of disabling these effects:

    "Windows 8 tries to provide a consistent, high-quality video experience across devices (desktop and portable computers, tablet devices, and other devices). This is achieved by disabling auto-processing in the video driver by using the VideoProcessorSetStreamAutoProcessingMode method when the DX11 Video Processor is initialized. This makes sure of a consistent video playback experience and also consistent battery life expectations across Windows 8 devices and Microsoft Store apps.

    Note Applications that depend on DX9 (for example, Windows Media Player) are not affected by this design and will continue to operate with auto-processing turned on."

    I have experimented with the DX11 Video Processor and it does seem that these effects can be enabled and disabled using the VideoProcessorSetStreamAutoProcessingMode function as described. However, I'm not sure what to do about the EVR, which I believe might be DX9 based.

    My question is how to disable video auto-processing using Media Foundation to play video with the EVR?

    I have looked for a way to configure the EVR to use DX11. I have looked through all the interfaces and services retrievable from Media Foundation sessions that might be used to disable auto-processing. I have looked at Microsoft's DX11VideoRenderer sample code to see if it might be used instead of the EVR but it does not support all the Media Foundation features my program uses.

    I notice that the Windows Movies & TV application is able to play video without auto-processing so hold out hope that this is possible.
    Wednesday, November 13, 2019 11:11 PM

Answers

  • I replaced the EVR with DX11VideoRenderer and it seems to be working. These are the issues I ran into and how I solved them:

    - The DX11 video processing path supports only BT-601 transfer matrix. BT-601 is pretty rate these days and it made the colors of my BT-709 videos wrong. I should have fixed it to respect the transfer matrix in the media type but since I know all my input videos will be BT-709, I just hard coded that transfer matrix for now.

    - The DX11 video processing path does not explicitly select studio range for YUV input surfaces. Safer to explicitly select D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_16_235 rather than defalt D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_UNDEFINED.

    - The DX11 video processing path does not disable auto-processing by default. Need to call VideoProcessorSetStreamAutoProcessingMode on the video processor to turn it off. One line fix.

    - Unlike EVR, DX11VideoRenderer has fixed streams, which makes it's not a drop in replacement for EVR. Need to set the topology output node's stream ID to one:

        outputNode->SetUINT32(MF_TOPONODE_STREAMID, 1);

    - If lNextSleep time rounds down to zero in CScheduler::ProcessSample, the scheduler hangs in an infinite loop. Easy to fix.

    - DX11VideoRender doesn't support scrubbing. The scheduler goes into an infinite loop if you try to use it because m_fRate is zero so it never makes progress. It was two dozen lines of code to implement support for m_fRate == 0 and MEStreamSinkScrubSampleComplete event.

    - CPresenter::m_ConnectionGUID is an uninitialized variable.


    Thursday, November 14, 2019 10:22 PM

All replies

  • Movies & TV uses Direct3D 11. Perhaps it would be a good idea for you too... Out of curiosity, what is missing in DX11VideoRenderer?

    http://alax.info/blog/tag/directshow

    Wednesday, November 13, 2019 11:36 PM
  • Thanks for the quick response. I'm leaning towards writing my own video player with DX11 and will probably do so at some point. It would put me behind schedule if I used that to solve the auto-processing issue though.

    The feature that DX11VideoRenderer lacks is IMFVideoDisplayControl::GetCurrentImage. That function returns two things: a system memory copy of the currently displayed frame and the time of the displayed frame. My program actually only needs the time and reading back the image is wasteful. The reason I am not using IPresentationClock::GetTime is because that function returns a time that lags the currently displayed frame by a few frames.
    Thursday, November 14, 2019 1:02 AM
  • The missing function is fairly easy to add. This renderer operates with textures, so you'd just keep a copy of last presented texture and on request your job is to create a similar staging texture with the same properties, copy one to the other via D3D11 device, then map staging texture to system memory and read the contents. OK, GetCurrentImage also converts to RGB but you could do it yourself too with Color Converter DSP. All together it is not that difficult and use of D3D11 renderer with source code vs. outdated D3D9 has its own important benefits.

    http://alax.info/blog/tag/directshow

    Thursday, November 14, 2019 8:33 AM
  • I replaced the EVR with DX11VideoRenderer and it seems to be working. These are the issues I ran into and how I solved them:

    - The DX11 video processing path supports only BT-601 transfer matrix. BT-601 is pretty rate these days and it made the colors of my BT-709 videos wrong. I should have fixed it to respect the transfer matrix in the media type but since I know all my input videos will be BT-709, I just hard coded that transfer matrix for now.

    - The DX11 video processing path does not explicitly select studio range for YUV input surfaces. Safer to explicitly select D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_16_235 rather than defalt D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_UNDEFINED.

    - The DX11 video processing path does not disable auto-processing by default. Need to call VideoProcessorSetStreamAutoProcessingMode on the video processor to turn it off. One line fix.

    - Unlike EVR, DX11VideoRenderer has fixed streams, which makes it's not a drop in replacement for EVR. Need to set the topology output node's stream ID to one:

        outputNode->SetUINT32(MF_TOPONODE_STREAMID, 1);

    - If lNextSleep time rounds down to zero in CScheduler::ProcessSample, the scheduler hangs in an infinite loop. Easy to fix.

    - DX11VideoRender doesn't support scrubbing. The scheduler goes into an infinite loop if you try to use it because m_fRate is zero so it never makes progress. It was two dozen lines of code to implement support for m_fRate == 0 and MEStreamSinkScrubSampleComplete event.

    - CPresenter::m_ConnectionGUID is an uninitialized variable.


    Thursday, November 14, 2019 10:22 PM