Skip to main content
Email Password   helpLost your password?

Sample Image - DirectShowVMR91.jpg

Introduction

This article shows the steps involved in creating and configuring DirectShow�s Video Mixing Renderer Filter 9 (VMR9). The two video streams, one on top of the other, are rendered on a single surface. This surface, in our case, is a PictureBox control. Each stream's alpha value, position and height/width can be adjusted at runtime.

How VMR9 is different

The following diagrams show the difference between rendering two videos with VMR9 and without VMR9.

Without VMR9

Rendering without VMR9

We notice that simply rendering two videos will result in two separate Video Renderers, which means that the videos are being played on two separate surfaces.

With VMR9

Rendering with VMR9

In this case, the VMR9 filter directs both video streams into its own input pins. This means there is only one renderer, and thus a single rendering surface for both video streams.

The Working

To enhance reusability and readability factors, the functionality of the VMR9 filter has been encapsulated inside a class named myVMR9.

The myVMR9 class

This class has the following private data members:

The constructor

The constructor receives a PictureBox's coordinates of type System::Drawing::Rectangle, along with its handler of type HWND. These two attributes are used by VMR9 for rendering purposes.

public: myVMR9(System::Drawing::Rectangle rect, HWND hwnd)
{
    // initialize video coordinates with normal values

    r = new VMR9NormalizedRect;
    r->left = 0;
    r->top = 0;
    r->right = 1;
    r->bottom = 1;

    pWC = NULL;
    pMix = NULL;
    pGB = NULL;
    pVmr = NULL;
    pConfig = NULL;
    pMC = NULL;
    pMS = NULL;
    // create an instance of the Filter Graph Manager

    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
        IID_IGraphBuilder, (void **)&pGB);
    // create an instance of the VMR9 filter

    CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC,
        IID_IBaseFilter, (void**)&pVmr);
    // add the VMR9 filter to the Graph Manager

    pGB->AddFilter(pVmr, L"Video");    
    // get a pointer to the IVMRFilterConfig9 interface

    pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig);
    // make sure VMR9 is in windowless mode

    pConfig->SetRenderingMode(VMR9Mode_Windowless);
    // get a pointer to the IVMRWindowlessControl9 interface 

    pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC);
    // explicitly convert System::Drawing::Rectangle type to RECT type

    RECT rcDest = {0};
    rcDest.bottom = rect.Bottom;
    rcDest.left = rect.Left;
    rcDest.right = rect.Right;
    rcDest.top = rect.Top;

    // set destination rectangle for the video

    pWC->SetVideoPosition(NULL, &rcDest);

    // specify the container window that the video should be clipped to    

    pWC->SetVideoClippingWindow(hwnd);
    // IVMRMixerControl manipulates video streams

    pVmr->QueryInterface(IID_IVMRMixerControl9, (void**)&pMix);
    // IMediaSeeking seeks to a position in the video stream

    pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS);
    // IMediaControl controls flow of data through the graph

    pGB->QueryInterface(IID_IMediaControl, (void **)&pMC);
}

The methods

HRESULT play()
{
    pMC->Run(); return
    S_OK;
}

HRESULT pause()
{
    pMC->Pause();
    return S_OK;
}

HRESULT stop()
{
    LONGLONG pos = 0;
    pMC->Stop();
    pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, 
                      NULL,AM_SEEKING_NoPositioning);
    pMC->Pause();
    return S_OK;
}

HRESULT close()
{
    // make sure resources are freed

    SAFE_RELEASE(pWC);
    SAFE_RELEASE(pMix);
    SAFE_RELEASE(pGB);
    SAFE_RELEASE(pVmr);
    SAFE_RELEASE(pConfig);
    SAFE_RELEASE(pMC);
    SAFE_RELEASE(pMS);
    return S_OK;
}

HRESULT setAlpha(DWORD stream, float alpha)
{
    // set alpha of specified video stream

    pMix->SetAlpha(stream, alpha);
    return S_OK;
}

HRESULT setX(DWORD stream, float x)
{
    // video displacement along x-axis

    r->right = x + (r->right - r->left);
    r->left = x;
    pMix->SetOutputRect(stream, r);
    return S_OK;
}

HRESULT setY(DWORD stream, float y)
{
    // video displacement along y-axis

    r->bottom = y + (r->bottom - r->top);
    r->top = y;
    pMix->SetOutputRect(stream, r);
    return S_OK;
}

HRESULT setW(DWORD stream, float w)
{
    // video stretching/shrinking along x-axis

    r->right = r->left + w;
    pMix->SetOutputRect(stream, r);
    return S_OK;
}

HRESULT setH(DWORD stream, float h)
{
    // video stretching/shrinking along y-axis

    r->bottom = r->top + h;
    pMix->SetOutputRect(stream, r);
    return S_OK;
}

HRESULT renderFiles(String* file1, String* file2)
{
    // convert String type to LPCSTR type and render the videos

    LPCTSTR lFile;
    lFile = 
      static_cast<LPCTSTR>(const_cast<void*>(static_cast<const void*>
      (System::Runtime::InteropServices::Marshal::StringToHGlobalAuto(file1))));
    pGB->RenderFile((LPCWSTR)lFile, NULL);
    lFile = 
      static_cast<LPCTSTR>(const_cast<void*>(static_cast<const void*>
      (System::Runtime::InteropServices::Marshal::StringToHGlobalAuto(file2))));
    pGB->RenderFile((LPCWSTR)lFile, NULL);
    System::Runtime::InteropServices::Marshal::FreeHGlobal
      (static_cast<IntPtr>(const_cast<void*>
      (static_cast<const void*>(lFile))));
    pMC->StopWhenReady();
    return S_OK;
}

Now that the VMR9's functionality has been separated from the GUI, Button and TrackBar handlers can simply create a pointer to a myVMR9 object and call the required methods.

Sample screenshot

Additional Information

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralDraw rubberband rectangle on anywhere in the video? Pin
$uresh $hanmugam
22:00 29 Sep '09  
GeneralLIVEVIDEO ROTATION or FLIP H/V FILTER Pin
giuegiu
22:14 6 Jul '09  
General3D object on video Pin
deepakpansheriya
0:02 12 Jun '09  
GeneralRe: 3D object on video Pin
Sameer Ahmed
5:11 12 Jun '09  
GeneralError on building in Visual studio team System 2008 Pin
codiebank
1:06 5 Jun '09  
GeneralRe: Error on building in Visual studio team System 2008 Pin
Sameer Ahmed
4:58 5 Jun '09  
GeneralVFW Video Capture Format Dialog Box Pin
vikasneedu
3:51 22 Oct '08  
GeneralCan you make your code to a wmp plugin? Pin
sunny_chn
3:47 1 Jun '08  
GeneralRe: Can you make your code to a wmp plugin? Pin
Sameer Ahmed
3:54 1 Jun '08  
Questionhi,Sameer Ahmed Pin
owen9924
17:06 19 Oct '08  
AnswerRe: hi,Sameer Ahmed Pin
Sameer Ahmed
18:15 19 Oct '08  
GeneralRe: hi,Sameer Ahmed Pin
owen9924
20:01 19 Oct '08  
GeneralVideo cropping Pin
Member 2427149
2:44 26 Dec '07  
GeneralRe: Video cropping Pin
Sameer Ahmed
18:57 30 Mar '08  
GeneralVB6 or VB.NET? Pin
Xristos2000
23:20 21 Aug '07  
GeneralRe: VB6 or VB.NET? Pin
Sameer Ahmed
1:32 22 Aug '07  
GeneralRe: VB6 or VB.NET? Pin
Xristos2000
2:55 22 Aug '07  
GeneralRe: VB6 or VB.NET? Pin
Sameer Ahmed
11:53 22 Aug '07  
GeneralRe: VB6 or VB.NET? Pin
Xristos2000
11:11 3 Sep '07  
GeneralRe: VB6 or VB.NET? Pin
Sameer Ahmed
13:28 3 Sep '07  
GeneralRe: VB6 or VB.NET? Pin
Xristos2000
13:31 3 Sep '07  
GeneralRe: VB6 or VB.NET? Pin
Sameer Ahmed
13:39 3 Sep '07  
GeneralRe: VB6 or VB.NET? Pin
Xristos2000
1:56 4 Sep '07  
Questionlnk error: _check_commonlanguageruntime_version Pin
jz.tan
0:51 16 Aug '07  
AnswerRe: lnk error: _check_commonlanguageruntime_version Pin
Sameer Ahmed
11:48 16 Aug '07  


Last Updated 1 Feb 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009