天天看點

[DirectShow] 033 - Using Windowed Mode

·         Note    The legacy Video Renderer Filter always uses windowed mode. The VMR-7 and VMR-9 filters use windowed mode by default, but also support windowless mode.

·         Video Renderer Filter 總是使用 windowed 模式。 VMR-7 和 VMR-9 預設使用 windowed 模式,也支援 windowless 模式。

In windowed mode, the video renderer creates its own window where it paints the video frames. Unless you specify otherwise, this window is a top-level window with its own borders and title bar.  Most of the time, however, you will attach the video window to an application window, so that the video is integrated into your application UI. This requires the following steps:

在 windowed 模式中, video renderer 建立一個屬于自己的視窗,并在這個視窗上繪制視訊幀。除非你指定其他的,否則這個視窗是一個擁有邊看和标題欄的頂層視窗。不過,絕大多數情況下,你将視訊視窗貼到程式視窗上,以至于視訊合并到你的應用程式 UI 上。這樣做需要以下步驟:

1.    Query for IVideoWindow .

2.    Set the parent window.

3.    Set new window styles.

4.    Position the video window inside the owner window.

5.    Notify the video window of WM_MOVE messages.

1.    詢問 IVideoWindow 。

2.    設定父視窗

3.    設定新的視窗風格。

4.    把視訊視窗放置在程式視窗上。

5.    通知視訊視窗 WM_MOVE 消息。

Query for IVideoWindow

Before starting playback, query the Filter Graph Manager for the IVideoWindow interface:

回放之前,向 Filter Graph Manager 詢問 IVideoWindow 接口:

IVideoWindow *pVidWin = NULL;

pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);

Set the Parent Window

To set the parent window, call the IVideoWindow::put_Owner method with a handle to your application window. This method takes a variable of type OAHWND , so cast the handle to this type:

. 調用 IVideoWindow::put_Owner 函數設定父視窗,參數就是父視窗的句柄。函數需要 OAHWND 類型的參數,是以要把句柄轉換成這個類型:

pVidWin->put_Owner((OAHWND)hwnd);

Set New Window Styles

Change the style of the video window by calling the IVideoWindow::put_WindowStyle method:

調用 IVideoWindow::put_WindowStyle 函數改變視訊視窗的風格:

pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);

The WS_CHILD flag sets the window to be a child window, and the WS_CLIPSIBLINGS flag prevents the window from drawing inside the client area of another child window.

WS_CHILD 标記設定視窗為一個子視窗。 WS_CLIPSIBLINGS 标記防止畫到其他視窗的客戶區域。

Position the Video Window

To set the position of the video relative to the application window's client area, call the IVideoWindow::SetWindowPosition method. This method takes a rectangle that specifies the left edge, top edge, width, and height of the video window. For example, the following code stretches the video window to fit the entire client area of the parent window:

調用 IVideoWindow::SetWindowPosition 函數設定視訊相對于應用程式視窗客戶區域的位置。函數的參數代表視訊視窗的左邊,上邊,寬和高。例如下面的代碼拉伸視訊視窗來适應整個父視窗的客戶區域:

RECT rc;

GetClientRect(hwnd, &rc);

pVidWin->SetWindowPosition(0, 0, rc.right, rc.bottom);

To get the native size of the video, call the IBasicVideo::GetVideoSize method on the Filter Graph Manager. You can use that information to scale the video and keep the correct aspect ratio.

在 Filter Graph Manager 上調用 IBasicVideo::GetVideoSize 方法獲得視訊的原始大小。你可以使用這些資訊來調整視訊以保證正确的高寬比。

Respond to WM_MOVE Messages

For best performance, you should notify the video renderer whenever the window moves while the graph is paused. Call the IVideoWindow::NotifyOwnerMessage method to forward the WM_MOVE message:

為達到最佳效果,在 graph 暫停期間,隻要視窗移動,就要通知 video renderer 。調用 IVideoWindow::NotifyOwnerMessage 函數發送 WM_MOVE 消息:

// (Inside your WindowProc)

case WM_MOVE:

    pVidWin->NotifyOwnerMessage((OAHWND)hWnd, msg, wParam, lParam);

    break;

If the renderer is using a hardware overlay, this notification causes the renderer to update the overlay position. (The VMR-9 does not use overlays, so you do not need to call this method if you are using the VMR-9.)

如果 renderer 使用了硬體 overlay ,這個通知消息就會導緻 renderer 更新 overlay 的位置。( VMR-9 沒有使用 overlay ,是以如果使用 VMR-9 就不需要調用這個函數。)

Clean Up

Before the application exits, stop the graph and reset the video window's owner to NULL. Otherwise, window messages might be sent to the wrong window, which is likely to cause errors. Also, hide video window, or else you might see a video image flicker on the screen momentarily:

程式退出之前,停止 graph 并重新設定視訊視窗的擁有者為 NULL 。否則,視窗消息将發送到錯誤的視窗,有可能産生錯誤。而且,隐藏視訊視窗,否則可能會看到一個視訊圖像在螢幕上閃爍。

pControl->Stop();

pVidWin->put_Visible(OAFALSE);

pVidWin->put_Owner(NULL);  

·         Note    If the parent of the video window is a child of your main application window (in other words, if the video window is a child of a child), you should create the video window using CoCreateInstance and add it to the graph, instead of letting the Filter Graph Manager add the video renderer during Intelligent Connect . This ensures that the video window and your child window are repainted at the same time. Otherwise, the child window may paint over the video window.

·         Note 如果視訊視窗的父視窗是程式主視窗的子視窗(換句話說,如果視訊視窗是子視窗的子視窗),你應該使用 CoCreateInstance 建立一個視訊視窗,把它加入到 graph 中,而不是在智能連接配接的時候由 Filter Graph Manager 添加 video renderer 。這可以確定視訊視窗和你的子視窗在同一時刻被重繪。否則,子視窗的繪制會覆寫掉視訊視窗。

繼續閱讀