[DirectShow] 034 - Using Windowless Mode

来源:互联网 发布:搜附近的网络 编辑:程序博客网 时间:2024/06/06 02:46

The Video Mixing Renderer filters (VMR-7 andVMR-9) both support windowless mode, which represents a majorimprovement over the IVideoWindow interface. This article describes the differences betweenwindowless mode and windowed mode, and how to use windowless mode.

Video Mixing Renderer filterVMR-7 VMR-9)都支持windowless模式,这是在IVideoWindwo接口上的主要提高。这篇文章描述windowless模式和windowed模式的不同,以及如何使用windowless模式。

To remain backward-compatible with existing applications, the VMR defaultsto windowed mode. In windowed mode, the renderer creates its own window todisplay the video. Typically the application sets the video window to be achild of the application window. The existence of a separate video windowcauses some problems, however:

为了兼容现有的程序,VMR默认windowed模式。在windowed模式中,renderer创建属于它自己的窗口显示视频。应用程序设置视频窗口为应用程序窗口的子窗口。分离视频窗口会产生一些问题:

·        Most importantly, there is a potential fordeadlocks if window messages are sent between threads.

·        如果窗口消息在两个线程之间发送会产生潜在的死锁。

·        The Filter Graph Manager must forwardcertain window messages, such as WM_PAINT, to the Video Renderer. Theapplication must use the Filter Graph Manager's implementation of IVideoWindow(and not the Video Renderer's), so that the Filter Graph Manager maintains thecorrect internal state.

·        Filter Graph Manager 必须发送类似WM_PAINTwindows消息到Video Renderer。应用程序必须使用Filter Graph Manager IVideoWindow执行(不是Video RendererIVideoWindow),以至于Filter Graph Mnager保持正确的内部状态。

·        To receive mouse or keyboard events fromthe video window, the application must set a "message drain," causingthe video window to forward these messages to the application.

·        为了从视频窗口接收鼠标和键盘事件,应用程序必须设置一个”message drain”,使视频窗口向应用程序发送消息。

·        To prevent clipping problems, the videowindow must have the right window styles.

·        为了避免出现遮挡问题,视频窗口必须设置正确的样式。

Windowless mode avoids these problems by having the VMR draw directly onthe application window's client area, using DirectDraw to clip the videorectangle. Windowless mode significantly reduces the chance of deadlocks. Also,the application does not have to set the owner window or the window styles. Infact, when the VMR is in windowless mode, it does not even expose the IVideoWindowinterface, which is no longer needed.

windowless模式利用DirectDraw剪切视频区域,直接画在应用程序窗口的客户区域来避免这些问题。windowless模式减少了死锁的几率。应用程序也不需要设置窗口的归属和风格。事实上,当VMR使用windowless模式的时候,并不暴露IVideoWindow接口,这个接口不在需要。

To use windowless mode, you must explicitly configure the VMR. However,you will find that is more flexible and easier to use than windowed mode.

为了使用windowless模式,必须明确的配置VMR。不过,你将发现使用windowless模式比windowed模式方便和灵活。

Configure the VMR for Windowless Mode

To override the VMR's default behavior, configure the VMR before buildingthe filter graph:

 要忽略VMR的默认行为,生成filter graph之前先配置VMR

6.Create the Filter Graph Manager.

7.创建Filter Graph Manager

8.Create the VMR and add it to the filter graph.

9.创建VMR并添加到filter graph中。

10.Call IVMRFilterConfig::SetRenderingMode on the VMR with the VMRMode_Windowless flag.

11.VMR上调用IVMRFilterConfig::SetRenderingMode,参数是VMRMode_Windowless

12.Call IVMRWindowlessControl::SetVideoClippingWindow on the VMR. Specify a handle to the window where the video should appear.

13.VMR上调用IVMRWindowlessControl::SetVideoClippingWindow。指定一个显示视频的窗口句柄。

Now build the rest of the filter graph by calling IGraphBuilder::RenderFile or other graph-building methods. The Filter Graph Manager automaticallyuses the instance of the VMR that you added to the graph. (For details on whythis happens, see Intelligent Connect.)

然后调用IGraphBuilder::RenderFile或者其他的方法生成filter graph的其他部分。Filter Graph Manager自动使用你添加到graph中的VMR实例。

The following code shows a helper function that creates the VMR, adds itto the graph, and sets up windowless mode.

下列的代码展示如何创建VMR并添加到graph中,设置成windowless模式。

HRESULTInitWindowlessVMR(

    HWND hwndApp,                  // Window to hold the video.

    IGraphBuilder* pGraph,         // Pointer to the Filter GraphManager.

    IVMRWindowlessControl** ppWc   // Receives a pointer to the VMR.

    )

{

    if (!pGraph || !ppWc)

    {

        return E_POINTER;

    }

    IBaseFilter* pVmr = NULL;

    IVMRWindowlessControl* pWc = NULL;

    // Create the VMR.

    HRESULT hr =CoCreateInstance(CLSID_VideoMixingRenderer, NULL,

        CLSCTX_INPROC, IID_IBaseFilter,(void**)&pVmr);

    if (FAILED(hr))

    {

        return hr;

    }

   

    // Add the VMR to the filter graph.

    hr = pGraph->AddFilter(pVmr,L"Video Mixing Renderer");

    if (FAILED(hr))

    {

        pVmr->Release();

        return hr;

    }

    // Set the rendering mode. 

    IVMRFilterConfig* pConfig;

    hr =pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);

    if (SUCCEEDED(hr))

    {

        hr =pConfig->SetRenderingMode(VMRMode_Windowless);

        pConfig->Release();

    }

    if (SUCCEEDED(hr))

    {

        // Set the window.

        hr =pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);

        if( SUCCEEDED(hr))

        {

            hr =pWc->SetVideoClippingWindow(hwndApp);

            if (SUCCEEDED(hr))

            {

                *ppWc = pWc; // Return this asan AddRef'd pointer.

            }

            else

            {

                // An error occurred, sorelease the interface.

                pWc->Release();

            }

        }

    }

    pVmr->Release();

    return hr;

}

This function assumes that are displaying only one video stream and are notmixing a static bitmap over the video. For details, see VMR Windowless Mode. You would call this function as follows:

这个函数假设只有一个视频流,且没有混合静态图片覆盖视频:

IVMRWindowlessControl*pWc = NULL;

hr= InitWindowlessVMR(hwnd, pGraph, &g_pWc);

if(SUCCEEDED(hr))

{

    // Build the graph. For example:

    pGraph->RenderFile(wszMyFileName, 0);

    // Release the VMR interface when you aredone.

    pWc->Release();

}

Position the Video

After configuring the VMR, the next step is to set the position of thevideo. There are two rectangles to consider, the source rectangle andthe destination rectangle. The source rectangle defines which portion ofthe video to display. The destination rectangle specifies the region in thewindow's client area that will contain the video. The VMR crops the video imageto the source rectangle and stretches the cropped image to fit the destinationrectangle.

配置完VMR之后,下一步就是设置视频的位置。这里有两个矩形需要考虑,源矩形和目标矩形。源矩形定义视频显示的部分。目标矩形指定窗口中包含视频的矩形。VMR裁减图像到源矩形并拉伸裁减的图片以适应目标矩形。

Call the IVMRWindowlessControl::SetVideoPosition method to specify both rectangles. The source rectangle must be equal toor smaller than the native video size; you can use the IVMRWindowlessControl::GetNativeVideoSize method to get the native video size. 

调用IVMRWindowlessControl::SetVideoPosition方法 指定这两个矩形。源矩形必须等于后者小于原始视频尺寸。可以调用IVMRWindowlessControl::GetNativeVideoSize或者原始视频尺寸。

For example, the following code sets the source rectangle equal to theentire video image and the destination rectangle equal to the entire windowclient area:

例如,接下来的代码设置源矩形等于整个视频图像,设置目标矩形等于整个窗口客户区域。

//Find the native video size.

longlWidth, lHeight;

HRESULThr = 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, modifythe rcSrc parameter.

如果想让视频占据客户区域中的一小块,修改rcDest参数,如果想裁减视频图像,修改rcSrc参数。

Handle Window Messages

Because the VMR does not have its own window, you must inform it when thevideo needs to be repainted or modified.

因为 VMR没有自己的窗口,当视频需要重绘或者修改的时候,你必须通知他。

·        When you receive a WM_PAINT message, call IVMRWindowlessControl::RepaintVideo to repaint the image.

·        当接收到WM_PAINT消息时,调用IVMRWindowlessControl::RepaintVideo重绘图像。

·        When you receive a WM_DISPLAYCHANGEmessage, call IVMRWindowlessControl::DisplayModeChanged. The VMR takes any actions that are needed to display the video at thenew resolution or color depth.

·        当接收到WM_DISPLAYCHANGE消息,调用IVMRWindowlessControl::DisplayModeChanged。在新的分辨率或颜色深度上VMR需要花费一些动作显示视频。

·        When you receive a WM_SIZE message,recalculate the position of the video and call SetVideoPosition again ifnecessary.

·        当接收到WM_SIZE消息,如果需要的话,重新计算视频的位置并调用SetVideoPosition

The following example shows a WM_PAINT message handler. It paints a regiondefined by the client rectangle minus the video rectangle. Do not draw onto thevideo rectangle, because the VMR will paint over it, causing flickering. Forthe same reason, do not set a background brush in your window class.

下面的例子显示了一个WM_PAINT消息的处理。它重画客户区域减去视频区域剩下的部分。不要在视频矩形上绘制,因为VMR将覆盖它,产生闪烁。同样的道理,在窗口类中不要设置背景刷。

voidOnPaint(HWND hwnd)

{

    PAINTSTRUCT ps;

    HDC        hdc;

    RECT       rcClient;

    GetClientRect(hwnd, &rcClient);

    hdc = BeginPaint(hwnd, &ps);

    if (g_pWc != NULL)

    {

        // Find the region where theapplication can paint by subtracting

        // the video destination rectangle fromthe client area.

        // (Assume that g_rcDest was calculatedpreviously.)

        HRGN rgnClient =CreateRectRgnIndirect(&rcClient);

        HRGN rgnVideo  = CreateRectRgnIndirect(&g_rcDest); 

        CombineRgn(rgnClient, rgnClient,rgnVideo, RGN_DIFF); 

       

        // Paint on window.

        HBRUSH hbr =GetSysColorBrush(COLOR_BTNFACE);

        FillRgn(hdc, rgnClient, hbr);

 

        // Clean up.

        DeleteObject(hbr);

        DeleteObject(rgnClient);

        DeleteObject(rgnVideo);

 

        // Request the VMR to paint the video.

        HRESULT hr =g_pWc->RepaintVideo(hwnd, hdc); 

    }

    else // There is no video, so paint the whole client area.

    {

        FillRect(hdc, &rc2,(HBRUSH)(COLOR_BTNFACE + 1));

    }

    EndPaint(hwnd, &ps);

}

Although you must respond to WM_PAINT messages, there is nothing you needto do between WM_PAINT messages to update the video. As this example shows,windowless mode lets you treat the video image simply as a self-drawing regionon the window.

尽管你必须响应WM_PAINT消息,但是在WM_PAINT消息与更新视频之间你不需要做任何事情。就像例子展示的那样,windowless模式让你可以把视频图像简单的当成在窗口上自绘区域一样。

 

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大学选课选漏了怎么办 高德地图不能琦跨城导航怎么办 水痘预防针间隔时间太久怎么办 车载导航被删了怎么办 高德地图gps信号弱怎么办 ai里面图片太多文件太大怎么办 ai文件太大怎么办1个G 文件写错了字怎么办 戒指弄不下来了怎么办 高德地图反应慢怎么办 白色印花t恤染色怎么办 印花t恤图案掉了怎么办 衣服上印花掉了怎么办 ps cs 3图标太小怎么办 ai cs6图标太小怎么办 su界面太小怎么办win10 华为p9手机gps信号弱怎么办 小米手机导航gps信号弱怎么办 安卓手机gps信号弱怎么办 苹果6导航gps信号弱怎么办 苹果6plus反应慢怎么办 手机文件打开是乱码怎么办 手机wps文件打开是乱码怎么办 腾讯视频vip账号被盗怎么办 附单据数错了 怎么办 橡胶的回弹性差怎么办 自己喷漆喷坏了怎么办 透明塑料磨花了怎么办 包包金属刮花了怎么办 鞋子刮了黑印子怎么办 黑色鞋跟磨白了怎么办 脚穿鞋子磨起泡怎么办 脚被鞋子磨红了怎么办 脚被鞋子磨黑了怎么办 白鞋皮鞋磨了皮怎么办 小脚趾磨肿了怎么办 穿鞋小拇指磨脚怎么办 高铁东西忘了怎么办 人故意去撞车死了怎么办? 新货车上户超重怎么办 车险出保单车号填错怎么办