Click here to Skip to main content
11,630,144 members (77,742 online)
Click here to Skip to main content

Using the DirectShow Video Mixing Renderer 9 filter

, 1 Feb 2005 336.8K 8.6K 92
Rate this:
Please Sign up or sign in to vote.
This article describes how to dynamically mix two video files (.mpeg, .mpg, .avi and .dat). Mixing involves alpha-blending and stretching/shrinking and positioning of the two video streams, individually, using DirectShow's VMR9 filter.

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

Share

About the Author

Sameer Ahmed
Software Developer
Pakistan Pakistan
No Biography provided

You may also be interested in...

Comments and Discussions

 
Generalgreenish lines on video using VMR9 Pin
shovit25-Oct-06 20:29
membershovit25-Oct-06 20:29 
GeneralFull Screen [modified] Pin
alanmark5-Oct-06 4:02
memberalanmark5-Oct-06 4:02 
Questionenumerate pins Pin
Fariha Atta1-Oct-06 17:57
memberFariha Atta1-Oct-06 17:57 
AnswerRe: enumerate pins Pin
Sameer Ahmed2-Oct-06 11:08
memberSameer Ahmed2-Oct-06 11:08 
GeneralSound Pin
Tharkunius26-Sep-06 23:38
memberTharkunius26-Sep-06 23:38 
GeneralRe: Sound Pin
Sameer Ahmed2-Oct-06 10:29
memberSameer Ahmed2-Oct-06 10:29 
QuestionUrgent !!! No errors in code but still cant see the video :-( [modified] Pin
~Jabeen~3-Sep-06 21:21
member~Jabeen~3-Sep-06 21:21 
Assalamoalikum!

i have tried your code as the way it is

It gives no errors but i cant see the video ... now i am stuck Confused | :confused:

My scenario is that i have a preview mode and a capture mode

I have implemented "preview mode" through VMR in the preview window.

It works fine through it.

Now about the problem i am facing i have a child window that starts showing the same preview on button click in it( say "capture window").

I had implemented this scenario through GRABBER but i want to do it through VMR although i am running an instance of appilication in the same application and on the same dialog


Through your code i got no errors through out i mean till
m_hr=pMC->Run();
i get no errors still i cant preview the video

more over i am getting the rectangle of the child window as


RECT rcDest;
::GetClientRect (hWnd,&rcDest);



still i cant preview it Frown | :( how to proceed???





Thanks and regards



if you want to look through Code then its like


/*

m_DlghWnd: the handle of the dialog which have both child windows that is preview (for which i have written the code through VMR) and the capture window which will show the image stream on button click


hWnd: it is the handle of the child window in which i want to start the preview stream


Requirement: Both windows should be previewed after the button click

*/

HRESULT CCameraPreview::TestVideo(HWND m_DlghWnd,HWND hWnd)
{

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
m_hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGB);
// create an instance of the VMR9 filter
m_hr=CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void**)&pVmr);
// add the VMR9 filter to the Graph Manager
m_hr=pGB->AddFilter(pVmr, L"Video");
// get a pointer to the IVMRFilterConfig9 interface
m_hr=pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig);
// make sure VMR9 is in windowless mode
m_hr=pConfig->SetRenderingMode(VMR9Mode_Windowless);
// get a pointer to the IVMRWindowlessControl9 interface
m_hr=pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC);
// explicitly convert System::Drawing::Rectangle type to RECT type


RECT rcDest;
::GetClientRect (hWnd,&rcDest);


// set destination rectangle for the video
m_hr=pWC->SetVideoPosition(NULL, &rcDest);

// specify the container window that the video should be clipped to
m_hr=pWC->SetVideoClippingWindow(hWnd);
// IVMRMixerControl manipulates video streams
m_hr=pVmr->QueryInterface(IID_IVMRMixerControl9, (void**)&pMix);
// IMediaSeeking seeks to a position in the video stream
m_hr=pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS);
// IMediaControl controls flow of data through the graph
m_hr=pGB->QueryInterface(IID_IMediaControl, (void **)&pMC);
m_hr=pMC->Run();
return m_hr;




-- modified at 3:45 Monday 4th September, 2006


Jabeen

AnswerRe: Urgent !!! No errors in code but still cant see the video :-( Pin
Sameer Ahmed5-Sep-06 1:58
memberSameer Ahmed5-Sep-06 1:58 
Questionvideo mixing problem [modified] Pin
fariha atta17-Aug-06 16:06
memberfariha atta17-Aug-06 16:06 
AnswerRe: video mixing problem [modified] Pin
Sameer Ahmed17-Aug-06 18:22
memberSameer Ahmed17-Aug-06 18:22 
GeneralRe: video mixing problem Pin
fariha atta18-Aug-06 5:04
memberfariha atta18-Aug-06 5:04 
GeneralRe: vmr9 Pin
Sameer Ahmed15-Aug-06 23:55
memberSameer Ahmed15-Aug-06 23:55 
Questionproblem in implementing a filter graph thru Filter Graph Manager Pin
fariha atta28-Jul-06 16:22
memberfariha atta28-Jul-06 16:22 
AnswerRe: problem in implementing a filter graph thru Filter Graph Manager Pin
Sameer Ahmed29-Jul-06 1:36
memberSameer Ahmed29-Jul-06 1:36 
GeneralFull screen switching mode Pin
gabrilestrimtu9-Jun-06 7:45
membergabrilestrimtu9-Jun-06 7:45 
GeneralRe: Full screen switching mode Pin
jimerino18-Apr-07 7:35
memberjimerino18-Apr-07 7:35 
Generalsir,i got some error complied in .net Pin
chenhuasheng8-May-06 18:44
memberchenhuasheng8-May-06 18:44 
GeneralText Mixing Pin
jeykumars27-Apr-06 23:11
memberjeykumars27-Apr-06 23:11 
GeneralRe: Text Mixing Pin
Sameer Ahmed28-Apr-06 2:06
memberSameer Ahmed28-Apr-06 2:06 
GeneralRe: AoA Sameer! Pin
Sameer Ahmed29-Jul-06 1:49
memberSameer Ahmed29-Jul-06 1:49 
GeneralGreat stuff Pin
RYoung4-Mar-06 7:36
memberRYoung4-Mar-06 7:36 
GeneralRe: Great stuff Pin
Sameer Ahmed4-Mar-06 8:14
memberSameer Ahmed4-Mar-06 8:14 
Generaloops Pin
GraceNetwork23-Feb-06 6:35
memberGraceNetwork23-Feb-06 6:35 
Questionoutput render video to file? Pin
GraceNetwork22-Feb-06 14:10
memberGraceNetwork22-Feb-06 14:10 
GeneralI am getting erros trying to compile/ Pin
GraceNetwork22-Feb-06 14:04
memberGraceNetwork22-Feb-06 14:04 
QuestionVideo looping Pin
el3gans26-Jan-06 5:19
memberel3gans26-Jan-06 5:19 
QuestionVideo synchronized ? Pin
tomprout23-Nov-05 6:35
membertomprout23-Nov-05 6:35 
AnswerRe: Video synchronized ? Pin
Sameer Ahmed2-Dec-05 23:33
memberSameer Ahmed2-Dec-05 23:33 
QuestionStreaming results? Pin
Geert van Horrik1-Oct-05 22:28
memberGeert van Horrik1-Oct-05 22:28 
AnswerRe: Streaming results? [modified] Pin
Sameer Ahmed2-Oct-05 6:04
memberSameer Ahmed2-Oct-05 6:04 
GeneralRe: Streaming results? Pin
Geert van Horrik2-Oct-05 9:02
memberGeert van Horrik2-Oct-05 9:02 
GeneralRe: Streaming results? Pin
Sameer Ahmed7-Oct-05 7:47
memberSameer Ahmed7-Oct-05 7:47 
GeneralRe: Streaming results? Pin
Geert van Horrik7-Oct-05 12:15
memberGeert van Horrik7-Oct-05 12:15 
Generalplease , i have an error in dshow.h Pin
dynamica12330-Aug-05 3:11
memberdynamica12330-Aug-05 3:11 
GeneralRe: please , i have an error in dshow.h Pin
Sameer Ahmed30-Aug-05 4:21
memberSameer Ahmed30-Aug-05 4:21 
Generalplease , i need dshow.h Pin
dynamica12330-Jul-05 1:59
memberdynamica12330-Jul-05 1:59 
GeneralRe: please , i need dshow.h Pin
Sameer Ahmed30-Jul-05 8:37
memberSameer Ahmed30-Jul-05 8:37 
GeneralProblem with Video Mixing Renderer 9 Pin
tl0825426-Sep-05 21:57
membertl0825426-Sep-05 21:57 
GeneralRe: Problem with Video Mixing Renderer 9 Pin
Sameer Ahmed27-Sep-05 7:55
memberSameer Ahmed27-Sep-05 7:55 
Generalcreating Video Mixing Renderer 9 Pin
veligeti15-Jun-05 6:09
memberveligeti15-Jun-05 6:09 
GeneralRe: creating Video Mixing Renderer 9 Pin
Sameer Ahmed15-Jun-05 12:15
memberSameer Ahmed15-Jun-05 12:15 
QuestionMixing with Texture ??? Pin
Anonymous21-Apr-05 2:25
sussAnonymous21-Apr-05 2:25 
AnswerRe: Mixing with Texture ??? Pin
Sameer Ahmed21-Apr-05 5:30
memberSameer Ahmed21-Apr-05 5:30 
GeneralRelease verson problem Pin
kifayatullah19-Apr-05 21:14
susskifayatullah19-Apr-05 21:14 
GeneralRe: Release verson problem Pin
Sameer Ahmed19-Apr-05 22:58
memberSameer Ahmed19-Apr-05 22:58 
GeneralNeed asistance Pin
Fahad N. Abbasi12-Apr-05 10:44
memberFahad N. Abbasi12-Apr-05 10:44 
GeneralRe: Need asistance Pin
Sameer Ahmed16-Apr-05 14:52
memberSameer Ahmed16-Apr-05 14:52 
GeneralRe: Need asistance Pin
Fahad N. Abbasi18-Apr-05 12:14
memberFahad N. Abbasi18-Apr-05 12:14 
GeneralWaterMark on Stream Pin
kifayatullah1-Apr-05 20:31
susskifayatullah1-Apr-05 20:31 
GeneralRe: WaterMark on Stream Pin
Sameer Ahmed16-Apr-05 14:37
memberSameer Ahmed16-Apr-05 14:37 

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.

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