Tricks and Tips for using the VMR9

A few months ago I did some work involving the VMR9, and I hit several brick walls. Many of these brick walls I hit about six months previously when working on a PC application for HD DVD playback (no, there were no plans to ship it, even then), but I hadn’t taken enough notes of the solutions back then and had to re-debug them all over again. In case you hit these same problems, or I do at some point in my future, here they are and how I solved them. I do not claim domain expert status in this area, nor should you treat my claims here as gospel. I also cannot explain why these changes fixed things. However they worked for me and might for you.

I was trying to build a graph that rendered video into a custom allocator/presenter, using the VMR in renderless mode. The issues were:

  • Failure to QI the VMR for IVMRMixerControl9
  • No video output when the VMR is in renderless mode at all on Vista, identical code worked fine on XP
  • When I fixed that above, I could get MPEG2 video to render on XP but not WMV, and Vista still rendered nothing

The solutions turned out to be:

QueryInterface on the VMR9 for IVMRMixerControl9 returns E_NOINTERFACE until you call SetNumberOfStreams on it.

If you ask the VMR to use YUV in renderless mode on Vista, nothing will render. The fix is to not ask for it. (Duh).

The order you set up VMR9 for renderless mode is critical. The original code that worked OK for MPEG2 on XP but not at all for WMV was as follows (error handling omitted for clarity):

spGraph->AddFilter(spVMR,L"VMR");

spVMR->QueryInterface(IID_IVMRFilterConfig9, &spConfig);

spConfig->SetRenderingMode(VMR9Mode_Renderless);

<set up custom allocator/presenter>

After much experimentation the code that worked in all cases was:

spVMR->QueryInterface(IID_IVMRFilterConfig9,&spConfig);

spConfig->SetNumberOfStreams(1);

spConfig->SetRenderingMode(VMR9Mode_Renderless);

<set up custom allocator/presenter>

spGraph->AddFilter(spVMR,L"VMR");

I can only guess that when you add the VMR filter to the graph you must have already set up the custom allocator/presenter. Why Vista is more fussy than XP, and why MPEG2 behaved differently than WMV I cannot begin to guess at.

Comments

  • Anonymous
    July 12, 2008
    Seems like VMR9 is violating COM interface rules by conditionally reporting IVMRMixerControl9. The COM docs state: "The set of interfaces accessible on an object via QueryInterface must be static, not dynamic. Specifically, if QueryInterface returns S_OK for a given IID once, it must never return E_NOINTERFACE on subsequent calls on the same object; and if QueryInterface returns E_NOINTERFACE for a given IID, subsequent calls for the same IID on the same object must never return S_OK." The YUV issue might be something similar with what I ran into, which is WDDM video drivers that report hardware overlay support and allow them to be created, but don't actually display anything. I had to check for WDDM drivers in my app and manually block overlay support.

  • Anonymous
    July 13, 2008
    Phaeron: For sure it is. I took a look at the source code and it has a highly "unusual" implementaton of QI. If my code had been planned to ship in an actual product I would have dug into the YUV problem more deeply, as we learnt from Xbox that keeping the video streams (and mixing) in YUV was a big win in quality and perf for our scenario. However as the goal was "good enough for internal testing" I never persued it further.

  • Anonymous
    July 25, 2008
    A bit off topic Andy but how did your application go? Was it a team initiative or just something you had done for fun?

  • Anonymous
    July 25, 2008
    The project got canned along with everything else HD DVD related, unfortunately. I did get it limping along, which was all that was necessary as a test implementation.

  • Anonymous
    July 26, 2008
    Ah ok, I would have loved to see native HD DVD playback support in Vista, and I'm sure those who bought HD DVD enabled PC's/laptops would have too.

  • Anonymous
    December 02, 2008
    I'm working this issue right now in C# and instead of trying to add the VMR9 filter to the filter graph, I am using the call: hr = dvdGraph.RenderDvdVideoVolume(null, AMDvdGraphFlags.VMR9Only, out status); I understand this adds the VMR9 filter to the DvdGraphBuilder graph. I also understand that I need to configure the filter before I make the call to RenderDvdVideoVolume(). I run into a problem when I try to call SetNumberOfStreams(1). Also, when I check status from the RenderDvdVideoVolume call, it shows I have three streams. I am trying to take the DvdPlayer example and convert it using the parts of the VMR9Allocator example so I can flip the subtitles left to right or vice-versa. I can flip the video, but not the subtitles. Finally, I need to make the call to RenderDvdVideoVolume() to get the VMR9 filter added to the filter graph, so I can call FindFilterByName() to access the VMR9 filter from the filter graph. At this point, when I try to use the filter to SetAllocatorPresenter(), I get an exception stating that the interface doesn't exist. If I try to call SetAllocatorPresenter() before the call to RenderDvdVideoVolume(), I get an exception that basically states that the filter (VMR9) does not exist. If feels like I'm caught coming or going. Do you or does anyone out there have a solution to this issue?