GdiCapturer.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #include "GdiCapturer.h"
  2. #include <cassert>
  3. namespace avrecorder {
  4. namespace video {
  5. bool GdiCapturer::open(const CaptureTarget& target, int width, int height) {
  6. #ifdef PLATFORM_WINDOWS
  7. close();
  8. if (target.type != CaptureTargetType::Window) return false;
  9. m_hwnd = target.hwnd;
  10. m_width = width;
  11. m_height = height;
  12. _srcHdc = GetWindowDC(m_hwnd);
  13. _dstHdc = CreateCompatibleDC(_srcHdc);
  14. _bitmap = CreateCompatibleBitmap(_srcHdc, width, height);
  15. SelectObject(_dstHdc, _bitmap);
  16. _bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  17. _bitmapInfo.bmiHeader.biPlanes = 1;
  18. _bitmapInfo.bmiHeader.biBitCount = 24;
  19. _bitmapInfo.bmiHeader.biWidth = width;
  20. _bitmapInfo.bmiHeader.biHeight = height;
  21. _bitmapInfo.bmiHeader.biCompression = BI_RGB;
  22. _bitmapInfo.bmiHeader.biSizeImage = width * height;
  23. _frame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_BGR24, width, height);
  24. return true;
  25. #else
  26. return false;
  27. #endif
  28. }
  29. void GdiCapturer::close() {
  30. #ifdef PLATFORM_WINDOWS
  31. if (_frame) { av_frame_free(&_frame); _frame = nullptr; }
  32. if (_dstHdc) { DeleteObject(_dstHdc); _dstHdc = nullptr; }
  33. if (_bitmap) { DeleteObject(_bitmap); _bitmap = nullptr; }
  34. // _srcHdc 由系统管理,无需手动释放
  35. #endif
  36. }
  37. AVFrame* GdiCapturer::getFrame() {
  38. #ifdef PLATFORM_WINDOWS
  39. if (!_srcHdc || !_dstHdc || !_frame) return nullptr;
  40. BitBlt(_dstHdc, 0, 0, m_width, m_height, _srcHdc, 0, 0, SRCCOPY);
  41. auto linesize = _frame->linesize[0];
  42. for (int row = 0; row < m_height; ++row) {
  43. GetDIBits(_dstHdc, _bitmap, m_height - 1 - row, 1, _frame->data[0] + row * linesize, &_bitmapInfo, DIB_RGB_COLORS);
  44. }
  45. if (m_drawCursor) {
  46. drawCursor(_dstHdc);
  47. }
  48. return _frame;
  49. #else
  50. return nullptr;
  51. #endif
  52. }
  53. void GdiCapturer::drawCursor(HDC hdc)
  54. {
  55. CURSORINFO ci = {sizeof(CURSORINFO)};
  56. if (!GetCursorInfo(&ci))
  57. return;
  58. if (ci.flags != CURSOR_SHOWING)
  59. return;
  60. RECT rect;
  61. GetWindowRect(m_hwnd, &rect);
  62. POINT pos = {ci.ptScreenPos.x - rect.left, ci.ptScreenPos.y - rect.top};
  63. DrawIconEx(hdc, pos.x, pos.y, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT);
  64. }
  65. } // namespace video
  66. } // namespace avrecorder