我们在Windows平台实现RTSP或者RTMP播放的时候,有个功能是绕不开的,那就是播放窗口全屏。本文就以大牛直播SDK(官方)的Windows播放器为例,大概讲下大概实现:
全屏播放需要考虑的点不多:
第一:视频播放后,全屏的意义;
第二:全屏后,是否等比例显示,我们的设计原则是,之前等比例显示的,继续等比例显示,之前铺满的,继续铺满;
第三:ESC退出全屏。
本文以C++的demo为例,具体实现如下:
void nt_wrapper_render_wnd::FullScreenSwitch()
{if ( !::IsWindow(m_hWnd) )return;if (player_handle_ != nullptr){player_api_.SetRenderARGBLogo(player_handle_, nullptr, 0, 0, 0, 0, 0, 0, 0);}if ( !IsFullScreen() ){if ( !IsCanFullScreen() )return;auto old_wnd = GetParent();if ( old_wnd == NULL )return;old_parent_wnd_ = old_wnd->m_hWnd;ASSERT(::IsWindow(old_parent_wnd_));GetWindowRect(&old_rect_);old_wnd->ScreenToClient(old_rect_);HMONITOR hMonitor = ::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);if (hMonitor == NULL)return;MONITORINFOEX mi;mi.cbSize = sizeof(mi);if ( !GetMonitorInfo(hMonitor, &mi) )return;::SetParent(m_hWnd, NULL);auto wnd_styles = GetWindowLongPtr(m_hWnd, GWL_STYLE);wnd_styles = wnd_styles & (~WS_CHILD); wnd_styles |= WS_POPUP;::SetWindowLongPtr(m_hWnd, GWL_STYLE, wnd_styles);// 隐藏老窗口::ShowWindow(old_parent_wnd_, SW_HIDE);is_full_screen_ = true;::SetWindowPos(m_hWnd, HWND_TOP, mi.rcMonitor.left,mi.rcMonitor.top,mi.rcMonitor.right - mi.rcMonitor.left,mi.rcMonitor.bottom - mi.rcMonitor.top,SWP_FRAMECHANGED);::SetForegroundWindow(m_hWnd);::RedrawWindow(m_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW| RDW_ERASE);::RedrawWindow(NULL, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW| RDW_ERASE);}else{::ShowWindow(old_parent_wnd_, SW_SHOW);auto wnd_styles = GetWindowLongPtr(m_hWnd, GWL_STYLE);wnd_styles = wnd_styles & (~WS_POPUP);wnd_styles |= WS_CHILD;auto ret = SetWindowLongPtr(m_hWnd, GWL_STYLE, wnd_styles);::SetParent(m_hWnd, old_parent_wnd_);is_full_screen_ = false;MoveWindow(old_rect_, TRUE);}
}
ESC处理:
void nt_wrapper_render_wnd::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{// TODO: Add your message handler code here and/or call default// 全屏的时候,按ESC将退出全屏if ( nChar == VK_ESCAPE ){if ( IsFullScreen() ){FullScreenSwitch();}}CWnd::OnChar(nChar, nRepCnt, nFlags);
}
C#的实现也非常简单,感兴趣的可自行研究。