IVMRWindowlessControl9::SetVideoClippingWindow and his Handle
-
viernes, 14 de noviembre de 2008 22:31How can I get the handle from my panel (windows-form) for the IVMRWindowlessControl9:
etVideoClippingWindow?
Todas las respuestas
-
viernes, 14 de noviembre de 2008 22:57Moderador
Since a Panel is a Control, can you use a the Control.Handle property?
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.handle.aspx
Just a guess here since I don't use Windows Forms
-
viernes, 14 de noviembre de 2008 23:20I tried all, nothing works with this ******** windows-form.
I thought I could try rapidly my code to test the setvideoClippingWindow, before changing to MFC or QT4!
This whole sh... is to blow up. Nobody in the internet use that (only the lazy C# programmers)! Now I understand why!
If I could buy a gun I would finished that windows form program with a good bye clic!
Then how can I get the handle of a panel in MFC? I think I´m not gonna sleep this night... again...
What would I do without you The March Hare? -
viernes, 14 de noviembre de 2008 23:43Moderador
Virtually all the controls in MFC are derived from CWnd so you can get a window handle using:
CWnd::GetSafeHwnd
Returns m_hWnd, or NULL if the this pointer is NULL.
HWND GetSafeHwnd( ) const;
Returns the window handle for a window. Returns NULL if the CWnd is not attached to a window or if it is used with a NULL CWnd pointer.
-
sábado, 15 de noviembre de 2008 0:16Moderador
BTW, I looked at the BitmapMixer C# sample on the DirectShow.NET site and it uses "this.Handle" to set the clipping window. Code snippet below:
Code Snippetprivate void ConfigureVMR9InWindowlessMode()
{
int hr = 0;IVMRFilterConfig9 filterConfig = (IVMRFilterConfig9) vmr9;
// Not really needed for VMR9 but don't forget calling it with VMR7
hr = filterConfig.SetNumberOfStreams(1);
DsError.ThrowExceptionForHR(hr);// Change VMR9 mode to Windowless
hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless);
DsError.ThrowExceptionForHR(hr);windowlessCtrl = (IVMRWindowlessControl9) vmr9;
// Set "Parent" window
hr = windowlessCtrl.SetVideoClippingWindow(this.Handle);
DsError.ThrowExceptionForHR(hr);// Set Aspect-Ratio
hr = windowlessCtrl.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox);
DsError.ThrowExceptionForHR(hr);// Add delegates for Windowless operations
AddHandlers();// Call the resize handler to configure the output size
MainForm_ResizeMove(null, null);
} -
martes, 18 de noviembre de 2008 0:52I will try that on my Window-Form project tomorrow. I tried a lot with that and I got often a InPtr to handle conversion problem. There was nothing to do even with recast... But that was not the only thing...
The code you show give me doubts. It seems that the vmr get it´s own framewindow. It´s remember me a little Amcap where there is no dialog to see in the ressouce. But I use a dialog based app with 2 edges, where each vmr9 has to go. So only a "this.Handle" will give the main dialog handle, that will not be a big help in this case.
My appliation will look more like this one: http://www.codeproject.com/KB/audio-video/DXCapture/DXCapture.jpg
from krssagar in the code project site. But I can´t use what he did. I can´t use IVideoWindow like he did.
As I change for MFC, because with window-form it was really a pain in the ***; it seems I can get a handle from a picture control with ::GetDlgItem(m_hWnd, IDC_PANEL); So I will try that tomorrow too! -
martes, 18 de noviembre de 2008 1:43ModeradorThat should work from MFC. There's probably a way to do it in .NET too but I'm not a Windows Forms guy
-
martes, 18 de noviembre de 2008 15:20Could you show me how you would do it in MFC? I think this will be a big help for the Worldwideweb, because there is no info about that! Believe me I looked everywhere!
-
martes, 18 de noviembre de 2008 19:45ModeradorI don't have time to work on another sample this week but your idea of using ::GetDlgItem(m_hWnd, IDC_PANEL) should work, IIRC. I re-worked the Dump sample for laloka this morning.
-
martes, 18 de noviembre de 2008 21:45nop that doesn´t work
I get an unexpected error atpWc->SetVideoClippingWindow(hwndApp);
I don´t know anymore what to do now... -
martes, 18 de noviembre de 2008 22:10Moderador
When in doubt, post a code snippet
Also look at the windowless sample and compare it to what you're doing (bad use of globals though
)
Code SnippetHRESULT InitializeWindowlessVMR(IBaseFilter **ppVmr9)
{
IBaseFilter* pVmr = NULL;if (!ppVmr9)
return E_POINTER;
*ppVmr9 = NULL;// Create the VMR and add it to the filter graph.
HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL,
CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
if (SUCCEEDED(hr))
{
hr = pGB->AddFilter(pVmr, L"Video Mixing Renderer 9");
if (SUCCEEDED(hr))
{
// Set the rendering mode and number of streams
SmartPtr <IVMRFilterConfig9> pConfig;JIF(pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig));
JIF(pConfig->SetRenderingMode(VMR9Mode_Windowless));hr = pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC);
if( SUCCEEDED(hr))
{
JIF(pWC->SetVideoClippingWindow(ghApp));
JIF(pWC->SetBorderColor(RGB(0,0,0)));
}
}// Don't release the pVmr interface because we are copying it into
// the caller's ppVmr9 pointer
*ppVmr9 = pVmr;
}return hr;
} -
martes, 18 de noviembre de 2008 23:24I tried that but I think the problem is less the code but more the setting of the picture control.
Do I have to add an event handler or a variable for my picture control which I called IDC_PANEL?
I put the all the code in an initialize button.
Here is the part with the problem:
HWND hwndPanel = ::GetDlgItem(m_hWnd, IDC_PANEL);
if(hwndPanel==NULL)
{
::AfxMessageBox(_T("no pointer!"),0,0);
}
IVMRFilterConfig9* pConfig1;hr = pRendererFilter->QueryInterface(IID_IVMRFilterConfig9, (LPVOID *)&pConfig1);
hr = pConfig1->SetNumberOfStreams(1);
hr = pConfig1->SetRenderingMode(VMR9Mode_Windowless);
pConfig1->Release();
IVMRWindowlessControl9 *m_Wc1;
hr = pVmrcapture->QueryInterface(IID_IVMRWindowlessControl9, (LPVOID *)&m_Wc1);
m_Wc1->SetVideoClippingWindow(hwndPanel);
I can´t put the whole code here it´s to much! -
martes, 18 de noviembre de 2008 23:57Moderador
Here is some preview code from my app.
Code Snippetpreview_window[0] = IDC_CAPTURE_DEVICE_PREVIEW_WINDOW_1_2;
.
.
.
CAMERA_FAIL_RETURN(m_dx[stream].vmr_config->SetRenderingMode(VMR9Mode_Windowless));
CAMERA_FAIL_RETURN(m_dx[stream].vmr_config->SetNumberOfStreams(num_streams));
CAMERA_FAIL_RETURN(m_dx[stream].vmr_config->SetRenderingPrefs(0));.
.
.
m_dx[stream].vmr_mixer = m_dx[stream].video_renderer;
m_dx[stream].vmr_bitmap = m_dx[stream].video_renderer;CWnd* wnd = GetDlgItem(preview_window[i]);
ASSERT(wnd);m_dx[stream].windowless_control = m_dx[stream].video_renderer;
if (m_dx[stream].windowless_control) {
CAMERA_FAIL_RETURN(m_dx[stream].windowless_control->SetVideoClippingWindow(wnd->GetSafeHwnd());
CAMERA_FAIL_RETURN(m_dx[stream].windowless_control->SetBorderColor(RGB_DARK_BLUE));
}My panels are "Static" controls in the .rc file and have Type "Frame" in the Properties window. Note I am calling this->GetDlgItem(<id>), not the one you are calling.
-
miércoles, 19 de noviembre de 2008 0:53I´m not sure what type m_dx[stream] is, but it´s maybe not so important here.
I will try:
CWnd* wnd = GetDlgItem(IDC_PANEL);
ASSERT(wnd);
m_Wc1->SetVideoClippingWindow(wnd->GetSafeHwnd());
Note I am calling this->GetDlgItem(<id>), not the one you are calling.
I don´t see a difference between these functions because when I call it within a Dialog (with the Dialogframe pointer as first argument), it should give the same element!?
What for is this statement:
CAMERA_FAIL_RETURN(m_dx[stream].vmr_config->SetRenderingPrefs(0)) ? I never understood from the MSDN doc what SetRenderingPrefs() should be good for.
In the properties I set Border, Client Edge and visible to True. The rest is set to false.
The (name) is IDC_PANEL1 and the ID is IDC_PANEL. I reset the type to frame like you did.
Did you create your panel with the "picture contol" from the toolbox?
Did you add a variable, a class or an event handler for the panel? -
miércoles, 19 de noviembre de 2008 1:16Moderador
The "m_dx" is a struct that contains the dshow interfaces for presenting a stream. That way I only have to let this go out of scope and all the CComPtr's and other objects associated with it are automatically taken care of; "stream" is just the stream number.
Your ::GetDlgItem is probably equivalent but it's always better to use the member methods when you can.The only preference for VMR9 is:
RenderPrefs9_DoNotRenderBorder
Just setting it to the value which is probably the default (off).
The only property I have set to True is "Sunken".I did create my panel using the Picture Control. I do not have a variable, class or handler for it. This is the beauty of the windowless mode. I do call RepaintVideo for each of the VMRs from my dialog's OnPaint.
-
miércoles, 19 de noviembre de 2008 9:26
Mister-Zorg wrote: I´m not sure what...
Here is minimalistic sample code/project for you: http://trac2.assembla.com/roatl-utilities/browser/trunk/MfcWindowlessVideoRenderer01 http://alax.info/blog/711, release binary included
Make sure to look at CMainDialog::CreateGraph in http://trac2.assembla.com/roatl-utilities/browser/trunk/MfcWindowlessVideoRenderer01/MainDialog.cpp
Because it's minimal code for windowless mode without handling WM_ERASEBKGND, it has some flickering where static text paints in place of video. -
miércoles, 19 de noviembre de 2008 19:44Thanks that was very usefull!
It seems the big missing in my code was:
CRect Position;
wnd1->GetClientRect(Position);
m_Wc2->SetVideoPosition(NULL, Position);
I thought this was the job of m_Wc2->SetVideoClippingWindow(wnd1->GetSafeHwnd());
That´s funny you create the video panel with a text box
Is there an advantage of doing this?
Why is the application blocked when I display the video! I can´t even move the dialog based app. -
miércoles, 19 de noviembre de 2008 19:50Moderador
It's great that Roman wrote this sample to help you
The steps for implementing the VMR's' windowless mode are described here:
In particular:
Position the video
After configuring the VMR, the next step is to set the position of the video. There are two rectangles to consider, the source rectangle and the destination rectangle. The source rectangle defines which portion of the video to display. The destination rectangle specifies the region in the window's client area that will contain the video. The VMR crops the video image to the source rectangle and stretches the cropped image to fit the destination rectangle.
Call the IVMRWindowlessControl::SetVideoPosition method to specify both rectangles. The source rectangle must be equal to or smaller than the native video size; you can use the IVMRWindowlessControl::GetNativeVideoSize method to get the native video size.
For example, the following code sets the source rectangle equal to the entire video image and the destination rectangle equal to the entire window client area:
// Find the native video size. long lWidth, lHeight; HRESULT hr = g_pWc->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL); if (SUCCEEDED(hr)) { RECT rcSrc, rcDest; // Set the source rectangle. SetRect(&rcSrc, 0, 0, lWidth, lHeight); // Get the window client area. GetClientRect(hwnd, &rcDest); // Set the destination rectangle. SetRect(&rcDest, 0, 0, rcDest.right, rcDest.bottom); // Set the video position. hr = g_pWc->SetVideoPosition(&rcSrc, &rcDest); }If you want to video to occupy a smaller portion of the client area, modify the rcDest parameter. If you want to crop the video image, modify the rcSrc parameter.
-
miércoles, 19 de noviembre de 2008 20:43I tried that but it didn´t work! Like I already said: you understand the explanations in the MSDN when you already succeed in what you wanted to do. The opposite is really rare! Btw. it didn´t explain the way you have to set a picture control.
It still don´t really know why one have to set a client area, as I set a picture control with a specific dimension where I get a handle for SetVideoClippingWindow(). It´s a bit redundant to me!
And I even don´t know why the video is adapting itself to the picture control dimension without clipping like the SetVideoClippingWindow() lets hear; but may be it´s because I didn´t set GetNativeVideoSize.
Regrettably Roman´s code didn´t compile. I just get a lot of error:
..\microsoft visual studio 9.0\vc\atlmfc\include\afxusertoolsmanager.h(73) : error C2146: syntax error : missing ';' before identifier 'CUserToolsManager'
..\microsoft visual studio 9.0\vc\atlmfc\include\afxusertoolsmanager.h(73) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
..\microsoft visual studio 9.0\vc\atlmfc\include\afxcontrolbarutil.h(56) : error C2144: syntax error : 'int' should be preceded by ';'
[...]
Anyway, looking at the code was very interesting as I discovered things like ATLVERIFY, ATLENSURE_SUCCEEDED,...
The exe works fine and I discover that one can move the app while the video is running. It´s not the case for mine. I´ve to spend a bit work to understand why. Next stage will be to undersatnd how to use the WM_PAINT and WM_ERASEBKGND handlers. -
miércoles, 19 de noviembre de 2008 21:16
Mister-Zorg wrote: That´s funny you create the video panel with a text box
Is there an advantage of doing this?
You can have it as a regular static control when you don't have video available. If this is what you need then you can use it as an advantage. Or you can subclass to display a logo instead of static text to show when video is not available. Another potential advantage of this approach is that you can mark position for your video directly in the dialog template and avoid calculations in code.
Mister-Zorg wrote: Regrettably Roman´s code didn´t compile. I just get a lot of error:
This is a bit wierd because it is actually a wizard-created MFC project with a just a few lines of code added. Maybe you shuffled include directories and changed default directory order. The code is not using afxusertoolsmanager.h or CUserToolsManager directly, so the problem is somewhere inside MFC includes. -
miércoles, 19 de noviembre de 2008 21:46
Or you can subclass to display a logo instead of static text to show when video is not available.
But then it make no difference to a picture control ?!
Another potential advantage of this approach is that you can mark position for your video directly in the dialog template and avoid calculations in code.
One can have a video displayed without marking the position on the dialog? But you don´t even get a handle to something for the SetClippingVideoWindow()?!?
I just install the last VC2008 Feature Pack, maybe it´s a reason for the lot of errors. -
miércoles, 19 de noviembre de 2008 22:07
Mister-Zorg wrote: Or you can subclass to display a logo instead of static text to show when video is not available.
But then it make no difference to a picture control ?!
Sure. It can be any control, it can be even parent window.
Mister-Zorg wrote:
Another potential advantage of this approach is that you can mark position for your video directly in the dialog template and avoid calculations in code.
One can have a video displayed without marking the position on the dialog? But you don´t even get a handle to something for the SetClippingVideoWindow()?!?
It's:
CWnd* pWindow = GetDlgItem(nControlIdentifier);
ASSERT(pWindow);
...
ATLENSURE_SUCCEEDED(pVmrWindowlessControl9->SetVideoClippingWindow(pWindow->GetSafeHwnd()));
Mister-Zorg wrote: I just install the last VC2008 Feature Pack, maybe it´s a reason for the lot of errors.
You'd rather install VS2008 Service Pack 1. -
miércoles, 19 de noviembre de 2008 22:13Moderador
In some cases, I use both a picture control and a static text field and show and hide the controls as necessary.
Code Snippet// Show the control
void
CMyDialog::ShowControl(UINT id){
CWnd* w; w = GetDlgItem(id); if (w) {
w->ModifyStyle(0, WS_VISIBLE); w->Invalidate(); }}
// Hide the control
void
CMyDialog::HideControl(UINT id){
CWnd* w; w = GetDlgItem(id); if (w) {
w->ModifyStyle(WS_VISIBLE, 0); Invalidate();}
}
VS2k8 SP1 superceded the Feature Pack.
Here's some good advice I got from a person at MS about the install order for SP1:
Installing VC9 SP1, then the Windows SDK 6.1 including its compilers, will
stomp VC's headers back to their RTM versions. The symptoms of this are
having original recipe <memory> (RTM, not mentioning shared_ptr) but extra
crispy <regex> (added by SP1; the stomping doesn't remove new headers).
<regex> isn't even usable, because <yvals.h> gets stomped back to its RTM
version, removing centralized machinery that was added by SP1.If you installed the Windows SDK 6.1 before VC9 SP1, you're fine. You can
even install it afterwards, if you manually uncheck the accompanying
compilers (which you already have). It's the bundled compilers that do the
stomping, not the SDK proper. -
jueves, 20 de noviembre de 2008 5:59
You'd rather install VS2008 Service Pack 1
You was right! I installed the Service Pack 1 and it works!
Very cool! Thanks for providing this code! I´m sure a lot of other people will be happy about that! -
miércoles, 25 de noviembre de 2009 21:48
Regrettably Roman´s code didn´t compile. I just get a lot of error:
..\microsoft visual studio 9.0\vc\atlmfc\include\afxusertoolsmanager.h(73) : error C2146: syntax error : missing ';' before identifier 'CUserToolsManager'
..\microsoft visual studio 9.0\vc\atlmfc\include\afxusertoolsmanager.h(73) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
..\microsoft visual studio 9.0\vc\atlmfc\include\afxcontrolbarutil.h(56) : error C2144: syntax error : 'int' should be preceded by ';'
[...]
In afxusertoolsmanager.h, when using Static MFC libraries, the .h files from Visual Studio 2008 SP1 seem to behave incorrectly. I had the same problem (in another project) and had to add in afxusertoolsmanager.h, just before the error:
#ifndef AFX_IMPORT_DATA
#define AFX_IMPORT_DATA
#endif

