Click here to Skip to main content
Click here to Skip to main content

Using the DirectShow Video Mixing Renderer 9 filter

By , 1 Feb 2005
 

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:

  • VMR9NormalizedRect *r;
  • IVMRWindowlessControl9 *pWC;
  • IVMRMixerControl9 *pMix;
  • IGraphBuilder *pGB;
  • IBaseFilter *pVmr;
  • IVMRFilterConfig9 *pConfig;
  • IMediaControl *pMC;
  • IMediaSeeking *pMS;

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

  • The second video stream opened is on top of the first one, i.e., file-2 video is rendered on top of file-1 video. Therefore, if the first video's alpha value is a 100% and the second video's alpha value is 50%, then both videos will be equally (50%) visible.
  • It should be noted that the values of Width and Height of trackbars can run into negative values. So when a video stream's width is -100%, it is laterally inverted. Similarly, when a video stream's height is -100%, the video is upside down.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Sameer Ahmed
Software Developer
Pakistan Pakistan
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionhello PinmemberMember 353456823 Sep '12 - 0:23 
GeneralCompiles with VS2010 Pinmembermerano8 Dec '10 - 12:27 
QuestionDraw rubberband rectangle on anywhere in the video? Pinmember$uresh $hanmugam29 Sep '09 - 21:00 
GeneralLIVEVIDEO ROTATION or FLIP H/V FILTER Pinmembergiuegiu6 Jul '09 - 21:14 
General3D object on video Pinmemberdeepakpansheriya11 Jun '09 - 23:02 
GeneralRe: 3D object on video PinmemberSameer Ahmed12 Jun '09 - 4:11 
GeneralError on building in Visual studio team System 2008 Pinmembercodiebank5 Jun '09 - 0:06 
GeneralRe: Error on building in Visual studio team System 2008 PinmemberSameer Ahmed5 Jun '09 - 3:58 
GeneralRe: Error on building in Visual studio team System 2008 PinmemberLinnnat2 Jan '11 - 20:57 
GeneralVFW Video Capture Format Dialog Box Pinmembervikasneedu22 Oct '08 - 2:51 
QuestionCan you make your code to a wmp plugin? Pinmembersunny_chn1 Jun '08 - 2:47 
AnswerRe: Can you make your code to a wmp plugin? PinmemberSameer Ahmed1 Jun '08 - 2:54 
Questionhi,Sameer Ahmed Pinmemberowen992419 Oct '08 - 16:06 
AnswerRe: hi,Sameer Ahmed PinmemberSameer Ahmed19 Oct '08 - 17:15 
GeneralRe: hi,Sameer Ahmed Pinmemberowen992419 Oct '08 - 19:01 
GeneralVideo cropping PinmemberMember 242714926 Dec '07 - 1:44 
GeneralRe: Video cropping PinmemberSameer Ahmed30 Mar '08 - 17:57 
QuestionVB6 or VB.NET? PinmemberXristos200021 Aug '07 - 22:20 
AnswerRe: VB6 or VB.NET? PinmemberSameer Ahmed22 Aug '07 - 0:32 
GeneralRe: VB6 or VB.NET? PinmemberXristos200022 Aug '07 - 1:55 
GeneralRe: VB6 or VB.NET? PinmemberSameer Ahmed22 Aug '07 - 10:53 
GeneralRe: VB6 or VB.NET? PinmemberXristos20003 Sep '07 - 10:11 
GeneralRe: VB6 or VB.NET? PinmemberSameer Ahmed3 Sep '07 - 12:28 
GeneralRe: VB6 or VB.NET? PinmemberXristos20003 Sep '07 - 12:31 
GeneralRe: VB6 or VB.NET? PinmemberSameer Ahmed3 Sep '07 - 12:39 
GeneralRe: VB6 or VB.NET? PinmemberXristos20004 Sep '07 - 0:56 
Questionlnk error: _check_commonlanguageruntime_version Pinmemberjz.tan15 Aug '07 - 23:51 
AnswerRe: lnk error: _check_commonlanguageruntime_version PinmemberSameer Ahmed16 Aug '07 - 10:48 
GeneralRe: lnk error: _check_commonlanguageruntime_version Pinmemberjz.tan16 Aug '07 - 15:40 
GeneralRe: lnk error: _check_commonlanguageruntime_version PinmemberSameer Ahmed17 Aug '07 - 0:07 
GeneralRe: lnk error: _check_commonlanguageruntime_version Pinmemberjz.tan23 Aug '07 - 20:04 
GeneralMerit Pinmemberjdsc5 Jun '07 - 0:16 
GeneralRe: Merit PinmemberSameer Ahmed6 Jun '07 - 4:45 
GeneralLINKER errors in VC++6.0 Pinmembermanas_hit30 May '07 - 23:49 
GeneralRe: LINKER errors in VC++6.0 PinmemberSameer Ahmed31 May '07 - 1:10 
QuestionCan a filter graph both VMR7 and VMR9? PinmemberManu Ranjana7 Jan '07 - 18:59 
QuestionIssue with continuously adding and deleting VMR9s PinmemberManu Ranjana5 Jan '07 - 22:30 
AnswerRe: Issue with continuously adding and deleting VMR9s PinmemberManu Ranjana7 Jan '07 - 18:54 
GeneralSend the result of VMR9 to an .avi file PinmemberMember #187253427 Dec '06 - 8:01 
GeneralRe: Send the result of VMR9 to an .avi file Pinmembertanvon malik25 Sep '07 - 2:09 
QuestionRe: Send the result of VMR9 to an .avi file PinmemberBoopathi S25 Sep '07 - 20:04 
AnswerRe: Send the result of VMR9 to an .avi file Pinmembertanvon malik25 Sep '07 - 21:14 
Generalgreenish lines on video using VMR9 Pinmembershovit25 Oct '06 - 20:29 
GeneralFull Screen [modified] Pinmemberalanmark5 Oct '06 - 4:02 
Questionenumerate pins PinmemberFariha Atta1 Oct '06 - 17:57 
AnswerRe: enumerate pins PinmemberSameer Ahmed2 Oct '06 - 11:08 
GeneralSound PinmemberTharkunius26 Sep '06 - 23:38 
GeneralRe: Sound PinmemberSameer Ahmed2 Oct '06 - 10:29 
QuestionUrgent !!! No errors in code but still cant see the video :-( [modified] Pinmember~Jabeen~3 Sep '06 - 21:21 
AnswerRe: Urgent !!! No errors in code but still cant see the video :-( PinmemberSameer Ahmed5 Sep '06 - 1:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 1 Feb 2005
Article Copyright 2005 by Sameer Ahmed
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid