How to use windowless Video Mixing Renderer Filter to show video fullscreen

The question is being asked from time to time. Everyone knows what is full screen video. Video renderers implement full screen capability since long ago through their IVideoWindow::put_FullScreenMode property, and even Filter Graph Manager exposes its own IVideoWindow interface to forward calls to filter’s implementation of IVideoWindow interface.

However, for Video Mixing Renderers, version 7 and 9, the preferred and recommended mode is windowless, where no IVideoWindow interface is available.

Note The IVMRWindowlessControl or IVMRWindowlessControl9 interface is now preferred over IVideoWindow. For more information, see Using Windowless Mode.

So in order to implement full screen mode it takes the application to attach Video Mixing Renderer filter to a private frameless window, to its entire client area and expand the window to entire monitor area.

The sample project FullScreenWindowlessVmrSample01 is illustrating this technique.

FullScreenWindowlessVmrSample01 Main Dialog


How to overlay a bitmap on top of video with Video Mixing Renderer (VMR-9)

A 100-lines code snippet which illustrates how a bitmap is overlaid over displayed video with Video Mixing Renderer 9 Filter using IVMRMixerBitmap9 interface. A video clip is played (default is Windows clock.avi, but you can replace it with your longer one to see overlay is really in a loop).…/VmrMixerBitmapSample01/…

VMR9AlphaBitmap AlphaBitmap;
ZeroMemory(&AlphaBitmap, sizeof AlphaBitmap);
AlphaBitmap.dwFlags = VMR9AlphaBitmap_hDC;
AlphaBitmap.hdc = Dc;
AlphaBitmap.rSrc = CRect(0, 0, 32, 32);
AlphaBitmap.rDest.left = (FLOAT) 0.75; = (FLOAT) 0.75;
AlphaBitmap.rDest.right = (FLOAT) 0.95;
AlphaBitmap.rDest.bottom = (FLOAT) 0.95;
AlphaBitmap.fAlpha = 0.75;
const HRESULT nSetAlphaBitmapResult = pVmrMixerBitmap->SetAlphaBitmap(&AlphaBitmap);

With a low FPS clip like clock.avi it is clear that the overlaid image is only updated with the next “main” video frame.

IVMRMixerBitmap9 Usage Sample

Visual C++ .NET 2008 source code is available from SVN, release binary included.

YV12, Extended Video Renderer Strides, Private DMO and more

Recently it was the time to sort out an issue with a video DMO, which outputs YV12 video and in the same time is capable of supporting extended video strides in order to efficiently make a direct connection to Video Mixing Renderer Filters.

From past experience, I already knew that some bugs are definitely involved but their effect was yet unexplored. For a testbed application, I took good old FrameRateSample02 application, which generates multiple video feeds and routes it to video renderers:

FrameRateSample02 Application with New Choices

With new source video choices the application is capable of constructing filter graphs that use a private DMO (that is hosted inside the executable) wrapped with DMO Wrapper Filter, with a graph topology shown below:

Filter Graph with a Private DMO


Multiple Windowless Video Mixing Renderers (VMR9) Sample

This is a begged MFC code for multiple windowless video renderers. MFC project, two independent video renderers hosted by the same parent window (actually through owned controls but this makes no major difference), VMR9 in windowless mode.


(this expects C:\Windows\clock.avi file to be available which is no longer the case after Windows XP – simply copy any AVI there as a replacement)

There are no WM_PAINT/WM_ERASEBKGND handlers, IVMRWindowlessControl9::RepaintVideo calls and other basically required code, instead a minimalistic snippet to make video rendered the requested way.

A Visual C++ .NET 2008 source code is available from SVN/Trac, release binary included.

How To: Save image to BMP file from IBasicVideo or VMR windowless interface

A simple question being asked all over again. Given IBasicVideo, IBasicVideo2, IVMRWindowlessControl or IVMRWindowlessControl9, how to save image to file? It is easy. It is a bit easier with IBasicVideo because it is possible to query this interface directly from graph’s interface, such as IGraphBuilder, and the call will be forwarded to video renderer. This code assumes internal bitmap format is non-paletted, which I believe is always the case.

LONG nBufferSize = 0;
ATLENSURE_SUCCEEDED(pBasicVideo->GetCurrentImage(&nBufferSize, NULL));
CHeapPtr<BITMAPINFO> pBitmapInfo;
ATLENSURE_THROW(pBitmapInfo.AllocateBytes(nBufferSize), E_OUTOFMEMORY);
ATLENSURE_SUCCEEDED(pBasicVideo->GetCurrentImage(&nBufferSize, (LONG*) (BITMAPINFO*) pBitmapInfo));
const BYTE* pnData = (const BYTE*) (&pBitmapInfo->bmiHeader + 1);
// NOTE: You might wish to handle <=8 bpp bitmaps here
ATLASSERT(pBitmapInfo->bmiHeader.biBitCount > 8);
ATLASSERT(pBitmapInfo->bmiHeader.biCompression == BI_RGB);
ZeroMemory(&BitmapFileHeader, sizeof BitmapFileHeader);
BitmapFileHeader.bfType = 'MB';
BitmapFileHeader.bfSize = (DWORD) (sizeof (BITMAPFILEHEADER) + pBitmapInfo->bmiHeader.biSize + pBitmapInfo->bmiHeader.biSizeImage);
BitmapFileHeader.bfOffBits = (DWORD) (sizeof (BITMAPFILEHEADER) + pBitmapInfo->bmiHeader.biSize);
ATLENSURE_SUCCEEDED(File.Write(&BitmapFileHeader, sizeof BitmapFileHeader));
ATLENSURE_SUCCEEDED(File.Write(&pBitmapInfo->bmiHeader, pBitmapInfo->bmiHeader.biSize));
ATLENSURE_SUCCEEDED(File.Write(pnData, (DWORD) pBitmapInfo->bmiHeader.biSizeImage));