none
IVMRWindowlessControl9::SetVideoClippingWindow and his Handle

Respuestas

  • Here is some preview code from my app.

     

    Code Snippet

    preview_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.

     

    martes, 18 de noviembre de 2008 23:57
  •  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 9:26
  •  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:07

Todas las respuestas

  • 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 22:57
  • I 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:20
  • 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.

     

    viernes, 14 de noviembre de 2008 23:43
  • 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 Snippet

     

           private 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);
            }

     

     

     

     

    sábado, 15 de noviembre de 2008 0:16
  • I 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 0:52
  • That 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 1:43
  • Could 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 15:20
  • I 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 19:45
  • nop that doesn´t work
    I get an unexpected error at

    pWc->SetVideoClippingWindow(hwndApp);

    I don´t know anymore what to do now...
    martes, 18 de noviembre de 2008 21:45
  • 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 Snippet

     

    HRESULT 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 22:10
  • I 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:24
  • Here is some preview code from my app.

     

    Code Snippet

    preview_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.

     

    martes, 18 de noviembre de 2008 23:57
  • I´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 0:53
  • 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 1:16
  •  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 9:26
  • Thanks 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:44
  • It's great that Roman wrote this sample to help you   The steps for implementing the VMR's' windowless mode are described here:

     

    Using Windowless Mode

     

    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 19:50
  • I 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 20:43
  •  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:16
  • 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 21:46
  •  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:07
  • 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.

     

     

    miércoles, 19 de noviembre de 2008 22:13
  • 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!

    jueves, 20 de noviembre de 2008 5:59
  • 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
    miércoles, 25 de noviembre de 2009 21:48