Files
crossdesk/src/screen_capturer/windows/screen_capturer_wgc.cpp
2024-05-17 17:55:57 +08:00

234 lines
6.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "screen_capturer_wgc.h"
#include <Windows.h>
#include <d3d11_4.h>
#include <winrt/Windows.Foundation.Metadata.h>
#include <winrt/Windows.Graphics.Capture.h>
#include <iostream>
#include "libyuv.h"
BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, HDC hdc, LPRECT lprc,
LPARAM data) {
MONITORINFOEX info_ex;
info_ex.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(hmonitor, &info_ex);
if (info_ex.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true;
if (info_ex.dwFlags & MONITORINFOF_PRIMARY) {
*(HMONITOR *)data = hmonitor;
}
return true;
}
HMONITOR GetPrimaryMonitor() {
HMONITOR hmonitor = nullptr;
::EnumDisplayMonitors(NULL, NULL, EnumMonitorProc, (LPARAM)&hmonitor);
return hmonitor;
}
ScreenCapturerWgc::ScreenCapturerWgc() {}
ScreenCapturerWgc::~ScreenCapturerWgc() {}
bool ScreenCapturerWgc::IsWgcSupported() {
try {
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
return winrt::Windows::Foundation::Metadata::ApiInformation::
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8);
} catch (const winrt::hresult_error &) {
return false;
} catch (...) {
return false;
}
}
int ScreenCapturerWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
cb_desktop_data cb) {
int error = 0;
if (_inited == true) return error;
int r = rect.right;
int b = rect.bottom;
nv12_frame_ = new unsigned char[rect.right * rect.bottom * 3 / 2];
nv12_frame_scaled_ = new unsigned char[1280 * 720 * 3 / 2];
_fps = fps;
_on_data = cb;
do {
if (!IsWgcSupported()) {
std::cout << "AE_UNSUPPORT" << std::endl;
error = 2;
break;
}
session_ = new WgcSessionImpl();
if (!session_) {
error = -1;
std::cout << "AE_WGC_CREATE_CAPTURER_FAILED" << std::endl;
break;
}
session_->RegisterObserver(this);
error = session_->Initialize(GetPrimaryMonitor());
_inited = true;
} while (0);
if (error != 0) {
}
return error;
}
int ScreenCapturerWgc::Destroy() {
if (nv12_frame_) {
delete nv12_frame_;
nv12_frame_ = nullptr;
}
if (nv12_frame_scaled_) {
delete nv12_frame_scaled_;
nv12_frame_scaled_ = nullptr;
}
Stop();
CleanUp();
return 0;
}
int ScreenCapturerWgc::Start() {
if (_running == true) {
std::cout << "record desktop duplication is already running" << std::endl;
return 0;
}
if (_inited == false) {
std::cout << "AE_NEED_INIT" << std::endl;
return 4;
}
_running = true;
session_->Start();
return 0;
}
int ScreenCapturerWgc::Pause() {
_paused = true;
if (session_) session_->Pause();
return 0;
}
int ScreenCapturerWgc::Resume() {
_paused = false;
if (session_) session_->Resume();
return 0;
}
int ScreenCapturerWgc::Stop() {
_running = false;
if (session_) session_->Stop();
return 0;
}
void ConvertABGRtoBGRA(const uint8_t *abgr_data, uint8_t *bgra_data, int width,
int height, int abgr_stride, int bgra_stride) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
// ABGR<47><52>BGRA<52><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>
int abgr_index = (i * abgr_stride + j) * 4;
int bgra_index = (i * bgra_stride + j) * 4;
// ֱ<>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD>ͺ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD>Alphaͨ<61><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bgra_data[bgra_index + 0] = abgr_data[abgr_index + 2]; // <20><>ɫ
bgra_data[bgra_index + 1] = abgr_data[abgr_index + 1]; // <20><>ɫ
bgra_data[bgra_index + 2] = abgr_data[abgr_index + 0]; // <20><>ɫ
bgra_data[bgra_index + 3] = abgr_data[abgr_index + 3]; // Alpha
}
}
}
void ConvertBGRAtoABGR(const uint8_t *bgra_data, uint8_t *abgr_data, int width,
int height, int bgra_stride, int abgr_stride) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
// BGRA<52><41>ABGR<47><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>
int bgra_index = (i * bgra_stride + j) * 4;
int abgr_index = (i * abgr_stride + j) * 4;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD>Alphaͨ<61><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0>
abgr_data[abgr_index + 0] = bgra_data[bgra_index + 3]; // Alpha
abgr_data[abgr_index + 1] = bgra_data[bgra_index + 0]; // Blue
abgr_data[abgr_index + 2] = bgra_data[bgra_index + 1]; // Green
abgr_data[abgr_index + 3] = bgra_data[bgra_index + 2]; // Red
}
}
}
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame) {
if (_on_data) {
int width = 1280;
int height = 720;
// libyuv::ARGBToI420(frame.data, frame.width * 4, yuv420_frame_,
// frame.width,
// yuv420_frame_ + frame.width * frame.height,
// frame.width / 2,
// yuv420_frame_ + frame.width * frame.height * 5 / 4,
// frame.width / 2, frame.width, frame.height);
// libyuv::I420Scale(
// (const uint8_t *)yuv420_frame_, frame.width,
// (const uint8_t *)(yuv420_frame_ + frame.width * frame.height),
// frame.width / 2,
// (const uint8_t *)(yuv420_frame_ + frame.width * frame.height * 5 /
// 4), frame.width / 2, frame.width, frame.height, (uint8_t
// *)yuv420_frame_, width, (uint8_t *)(yuv420_frame_ + width * height),
// width / 2, (uint8_t *)(yuv420_frame_ + width * height * 5 / 4), width
// / 2, width, height, libyuv::FilterMode::kFilterLinear);
// libyuv::I420ToNV12(
// (const uint8_t *)yuv420_frame_, width,
// (const uint8_t *)(yuv420_frame_ + width * height), width / 2,
// (const uint8_t *)(yuv420_frame_ + width * height * 5 / 4), width / 2,
// nv12_frame_, width, nv12_frame_ + width * height, width, width,
// height);
libyuv::ARGBToNV12(frame.data, frame.width * 4, nv12_frame_, frame.width,
nv12_frame_ + frame.width * frame.height,
frame.width / 2, frame.width, frame.height);
libyuv::NV12Scale(
(const uint8_t *)nv12_frame_, frame.width,
(const uint8_t *)(nv12_frame_ + frame.width * frame.height),
frame.width / 2, frame.width, frame.height,
(uint8_t *)nv12_frame_scaled_, width,
(uint8_t *)(nv12_frame_scaled_ + width * height), width / 2, width,
height, libyuv::FilterMode::kFilterLinear);
_on_data(nv12_frame_scaled_, width * height * 3 / 2, width, height);
}
}
void ScreenCapturerWgc::CleanUp() {
_inited = false;
if (session_) session_->Release();
session_ = nullptr;
}