我们在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#的实现也非常简单,感兴趣的可自行研究。