#include "video_capturer.h" #include "capturer/finder.h" bool VideoCapturer::Open(HWND hwnd, Method method) { Close(); __CheckBool(hwnd); m_srcHwnd = hwnd; __CheckBool(_GetHwndSize(m_srcHwnd)); m_usingMethod = method; m_type = WINDOW; switch (method) { case WGC: { m_wgcCapturer = WgcCapturer::New(); __CheckBool(m_wgcCapturer->StartCapturerWindow(hwnd, m_width, m_height)); break; } default: { // GDI m_gdiCapturer = new GdiCapturer; __CheckBool(m_gdiCapturer->Open(hwnd, m_width, m_height)); break; } } return true; } bool VideoCapturer::Open(int monitorIdx, Method method) { Close(); auto&& monitorInfo = MonitorFinder::GetList()[monitorIdx]; m_rect = monitorInfo.rect; m_borderHeight = 0; m_borderWidth = 0; m_width = m_rect.right - m_rect.left; m_height = m_rect.bottom - m_rect.top; m_usingMethod = method; m_type = MONITOR; switch (method) { case WGC: { auto monitor = monitorInfo.monitor; m_wgcCapturer = WgcCapturer::New(); __CheckBool(m_wgcCapturer->StartCapturerMonitor(monitor, m_width, m_height)); break; } default: { // DXGI m_dxgiCapturer = new DxgiCapturer; __CheckBool(m_dxgiCapturer->Open(m_rect.left, m_rect.top, m_width, m_height)); break; } } return true; } AVFrame* VideoCapturer::GetFrame() { switch (m_usingMethod) { case WGC: // 该捕获方式自动就将鼠标画好了,我们不需要再自己画鼠标 return m_wgcCapturer->GetFrame(); case DXGI: { auto hdc = m_dxgiCapturer->GetHdc(); if (m_isDrawCursor && hdc) { _DrawCursor(hdc); } return m_dxgiCapturer->GetFrame(); } default: // GDI auto hdc = m_gdiCapturer->GetHdc(m_borderWidth, m_borderHeight); if (m_isDrawCursor && hdc) { _DrawCursor(hdc); } return m_gdiCapturer->GetFrame(); } } void VideoCapturer::SetDrawCursor(bool isDrawCursor) { m_isDrawCursor = isDrawCursor; if (m_usingMethod == WGC) { m_wgcCapturer->SetDrawCursor(m_isDrawCursor); } } void VideoCapturer::Close() { Free(m_dxgiCapturer, [this] { m_dxgiCapturer->Close(); delete m_dxgiCapturer; }); Free(m_gdiCapturer, [this] { m_gdiCapturer->Close(); delete m_gdiCapturer; }); Free(m_wgcCapturer, [this] { m_wgcCapturer->Close(); }); } VideoCapturer::~VideoCapturer() { Close(); } int VideoCapturer::GetWidth() const { return m_width; } int VideoCapturer::GetHeight() const { return m_height; } bool VideoCapturer::_GetHwndSize(HWND hwnd) { RECT rect; __CheckBool(GetClientRect(hwnd, &rect)); m_rect = rect; m_width = (rect.right - rect.left); m_height = (rect.bottom - rect.top); __CheckBool(GetWindowRect(hwnd, &rect)); m_borderHeight = rect.bottom - rect.top - m_height; m_borderWidth = rect.right - rect.left - m_width; if (m_borderHeight < 0) { m_borderHeight = 0; } if (m_borderWidth < 0) { m_borderWidth = 0; } return true; } void VideoCapturer::_DrawCursor(HDC hdc) { CURSORINFO ci; ci.cbSize = sizeof(CURSORINFO); __CheckNo(GetCursorInfo(&ci)); int cursorX = ci.ptScreenPos.x; int cursorY = ci.ptScreenPos.y; if (cursorX > m_rect.right || cursorX < m_rect.left || cursorY > m_rect.bottom || cursorY < m_rect.top) { return; // 超出显示范围 } if (ci.flags == CURSOR_SHOWING) { // 将光标画到屏幕所在位置 int x = cursorX - m_rect.left; int y = cursorY - m_rect.top; __CheckNo(DrawIconEx(hdc, x, y, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT)); } }