video_capturer.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include "video_capturer.h"
  2. #include "capturer/finder.h"
  3. bool VideoCapturer::Open(HWND hwnd, Method method)
  4. {
  5. Close();
  6. __CheckBool(hwnd);
  7. m_srcHwnd = hwnd;
  8. __CheckBool(_GetHwndSize(m_srcHwnd));
  9. m_usingMethod = method;
  10. m_type = WINDOW;
  11. switch (method) {
  12. case WGC: {
  13. m_wgcCapturer = WgcCapturer::New();
  14. __CheckBool(m_wgcCapturer->StartCapturerWindow(hwnd, m_width, m_height));
  15. break;
  16. }
  17. default: { // GDI
  18. m_gdiCapturer = new GdiCapturer;
  19. __CheckBool(m_gdiCapturer->Open(hwnd, m_width, m_height));
  20. break;
  21. }
  22. }
  23. return true;
  24. }
  25. bool VideoCapturer::Open(int monitorIdx, Method method)
  26. {
  27. Close();
  28. auto&& monitorInfo = MonitorFinder::GetList()[monitorIdx];
  29. m_rect = monitorInfo.rect;
  30. m_borderHeight = 0;
  31. m_borderWidth = 0;
  32. m_width = m_rect.right - m_rect.left;
  33. m_height = m_rect.bottom - m_rect.top;
  34. m_usingMethod = method;
  35. m_type = MONITOR;
  36. switch (method) {
  37. case WGC: {
  38. auto monitor = monitorInfo.monitor;
  39. m_wgcCapturer = WgcCapturer::New();
  40. __CheckBool(m_wgcCapturer->StartCapturerMonitor(monitor, m_width, m_height));
  41. break;
  42. }
  43. default: { // DXGI
  44. m_dxgiCapturer = new DxgiCapturer;
  45. __CheckBool(m_dxgiCapturer->Open(m_rect.left, m_rect.top, m_width, m_height));
  46. break;
  47. }
  48. }
  49. return true;
  50. }
  51. AVFrame* VideoCapturer::GetFrame()
  52. {
  53. switch (m_usingMethod) {
  54. case WGC: // 该捕获方式自动就将鼠标画好了,我们不需要再自己画鼠标
  55. return m_wgcCapturer->GetFrame();
  56. case DXGI: {
  57. auto hdc = m_dxgiCapturer->GetHdc();
  58. if (m_isDrawCursor && hdc) {
  59. _DrawCursor(hdc);
  60. }
  61. return m_dxgiCapturer->GetFrame();
  62. }
  63. default: // GDI
  64. auto hdc = m_gdiCapturer->GetHdc(m_borderWidth, m_borderHeight);
  65. if (m_isDrawCursor && hdc) {
  66. _DrawCursor(hdc);
  67. }
  68. return m_gdiCapturer->GetFrame();
  69. }
  70. }
  71. void VideoCapturer::SetDrawCursor(bool isDrawCursor)
  72. {
  73. m_isDrawCursor = isDrawCursor;
  74. if (m_usingMethod == WGC) {
  75. m_wgcCapturer->SetDrawCursor(m_isDrawCursor);
  76. }
  77. }
  78. void VideoCapturer::Close()
  79. {
  80. Free(m_dxgiCapturer, [this] { m_dxgiCapturer->Close(); delete m_dxgiCapturer; });
  81. Free(m_gdiCapturer, [this] { m_gdiCapturer->Close(); delete m_gdiCapturer; });
  82. Free(m_wgcCapturer, [this] { m_wgcCapturer->Close(); });
  83. }
  84. VideoCapturer::~VideoCapturer()
  85. {
  86. Close();
  87. }
  88. int VideoCapturer::GetWidth() const
  89. {
  90. return m_width;
  91. }
  92. int VideoCapturer::GetHeight() const
  93. {
  94. return m_height;
  95. }
  96. bool VideoCapturer::_GetHwndSize(HWND hwnd)
  97. {
  98. RECT rect;
  99. __CheckBool(GetClientRect(hwnd, &rect));
  100. m_rect = rect;
  101. m_width = (rect.right - rect.left);
  102. m_height = (rect.bottom - rect.top);
  103. __CheckBool(GetWindowRect(hwnd, &rect));
  104. m_borderHeight = rect.bottom - rect.top - m_height;
  105. m_borderWidth = rect.right - rect.left - m_width;
  106. if (m_borderHeight < 0) {
  107. m_borderHeight = 0;
  108. }
  109. if (m_borderWidth < 0) {
  110. m_borderWidth = 0;
  111. }
  112. return true;
  113. }
  114. void VideoCapturer::_DrawCursor(HDC hdc)
  115. {
  116. CURSORINFO ci;
  117. ci.cbSize = sizeof(CURSORINFO);
  118. __CheckNo(GetCursorInfo(&ci));
  119. int cursorX = ci.ptScreenPos.x;
  120. int cursorY = ci.ptScreenPos.y;
  121. if (cursorX > m_rect.right || cursorX < m_rect.left
  122. || cursorY > m_rect.bottom || cursorY < m_rect.top) {
  123. return; // 超出显示范围
  124. }
  125. if (ci.flags == CURSOR_SHOWING) {
  126. // 将光标画到屏幕所在位置
  127. int x = cursorX - m_rect.left;
  128. int y = cursorY - m_rect.top;
  129. __CheckNo(DrawIconEx(hdc, x, y, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT));
  130. }
  131. }