From 2fc89923ae84af4ffbd2a1c6dda2a111f7bfe22c Mon Sep 17 00:00:00 2001 From: dijunkun Date: Fri, 15 Dec 2023 17:29:17 +0800 Subject: [PATCH] Use factory method to create screen capturer --- .../device_controller_factory.h | 2 +- src/gui/main.cpp | 175 ++++-------------- .../linux/screen_capturer_x11.cpp} | 34 ++-- .../linux/screen_capturer_x11.h} | 30 ++- .../linux/x11_session.h | 0 .../linux/x11_session_impl.cpp | 0 .../linux/x11_session_impl.h | 0 .../macosx/screen_capturer_avf.cpp} | 34 ++-- .../macosx/screen_capturer_avf.h} | 30 ++- src/screen_capturer/screen_capturer.h | 33 ++++ src/screen_capturer/screen_capturer_factory.h | 37 ++++ .../windows/screen_capturer_wgc.cpp} | 76 ++++++-- .../windows/screen_capturer_wgc.h} | 32 ++-- .../windows/wgc_session.h | 0 .../windows/wgc_session_impl.cpp | 0 .../windows/wgc_session_impl.h | 0 xmake.lua | 33 ++-- 17 files changed, 256 insertions(+), 260 deletions(-) rename src/{screen_capture/linux/screen_capture_x11.cpp => screen_capturer/linux/screen_capturer_x11.cpp} (86%) rename src/{screen_capture/linux/screen_capture_x11.h => screen_capturer/linux/screen_capturer_x11.h} (71%) rename src/{screen_capture => screen_capturer}/linux/x11_session.h (100%) rename src/{screen_capture => screen_capturer}/linux/x11_session_impl.cpp (100%) rename src/{screen_capture => screen_capturer}/linux/x11_session_impl.h (100%) rename src/{screen_capture/macosx/screen_capture_avf.cpp => screen_capturer/macosx/screen_capturer_avf.cpp} (86%) rename src/{screen_capture/macosx/screen_capture_avf.h => screen_capturer/macosx/screen_capturer_avf.h} (72%) create mode 100644 src/screen_capturer/screen_capturer.h create mode 100644 src/screen_capturer/screen_capturer_factory.h rename src/{screen_capture/windows/screen_capture_wgc.cpp => screen_capturer/windows/screen_capturer_wgc.cpp} (52%) rename src/{screen_capture/windows/screen_capture_wgc.h => screen_capturer/windows/screen_capturer_wgc.h} (52%) rename src/{screen_capture => screen_capturer}/windows/wgc_session.h (100%) rename src/{screen_capture => screen_capturer}/windows/wgc_session_impl.cpp (100%) rename src/{screen_capture => screen_capturer}/windows/wgc_session_impl.h (100%) diff --git a/src/device_controller/device_controller_factory.h b/src/device_controller/device_controller_factory.h index c6e0494..eb48d9e 100644 --- a/src/device_controller/device_controller_factory.h +++ b/src/device_controller/device_controller_factory.h @@ -12,7 +12,7 @@ class DeviceControllerFactory { public: - enum Device { Mouse, Keyboard }; + enum Device { Mouse = 0, Keyboard }; public: virtual ~DeviceControllerFactory() {} diff --git a/src/gui/main.cpp b/src/gui/main.cpp index 96ad442..5136431 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -28,33 +28,20 @@ #include extern "C" { -#include #include -#include -#include -#include -#include -#include -#include #include #include }; #include +#include "../../thirdparty/projectx/src/interface/x.h" +#include "device_controller_factory.h" #include "imgui.h" #include "imgui_impl_sdl2.h" #include "imgui_impl_sdlrenderer2.h" #include "log.h" -#ifdef _WIN32 -#include "screen_capture_wgc.h" -#elif __linux__ -#include "screen_capture_x11.h" -#elif __APPLE__ -#include "screen_capture_avf.h" -#endif -#include "../../thirdparty/projectx/src/interface/x.h" -#include "device_controller_factory.h" +#include "screen_capturer_factory.h" #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 @@ -161,13 +148,8 @@ static char mac_addr[16]; static bool is_create_connection = false; static bool done = false; -#ifdef _WIN32 -ScreenCaptureWgc *screen_capture = nullptr; -#elif __linux__ -ScreenCaptureX11 *screen_capture = nullptr; -#elif __APPLE__ -ScreenCaptureAvf *screen_capture = nullptr; -#endif +ScreenCapturerFactory *screen_capturer_factory = nullptr; +ScreenCapturer *screen_capturer = nullptr; DeviceControllerFactory *device_controller_factory = nullptr; MouseController *mouse_controller = nullptr; @@ -176,43 +158,16 @@ char *nv12_buffer = nullptr; #ifdef __linux__ std::chrono::_V2::system_clock::time_point last_frame_time_; -static int uinput_fd; -static struct uinput_user_dev uinput_dev; -#define KEY_CUSTOM_UP 0x20 -#define KEY_CUSTOM_DOWN 0x30 -static int fd_mouse = -1; -static int fd_kbd = -1; -static std::atomic mouse_pos_x_last = -65535; -static std::atomic mouse_pos_y_last = -65535; #else std::chrono::steady_clock::time_point last_frame_time_; #endif -// typedef enum { mouse = 0, keyboard } ControlType; -// typedef enum { move = 0, left_down, left_up, right_down, right_up } -// MouseFlag; typedef enum { key_down = 0, key_up } KeyFlag; typedef struct { -// size_t x; -// size_t y; -// MouseFlag flag; -// } Mouse; - -// typedef struct { -// size_t key_value; -// KeyFlag flag; -// } Key; - -// typedef struct { -// ControlType type; -// union { -// Mouse m; -// Key k; -// }; -// } RemoteAction; - inline int ProcessMouseKeyEven(SDL_Event &ev) { - float ratio = 1280.0 / window_w; + float ratio = (float)(1280.0 / window_w); RemoteAction remote_action; + remote_action.m.x = (size_t)(ev.button.x * ratio); + remote_action.m.y = (size_t)(ev.button.y * ratio); if (SDL_KEYDOWN == ev.type) // SDL_KEYUP { @@ -230,49 +185,24 @@ inline int ProcessMouseKeyEven(SDL_Event &ev) { // printf("SDLK_RIGHT \n"); } } else if (SDL_MOUSEBUTTONDOWN == ev.type) { + remote_action.type = ControlType::mouse; if (SDL_BUTTON_LEFT == ev.button.button) { - remote_action.type = ControlType::mouse; remote_action.m.flag = MouseFlag::left_down; - remote_action.m.x = ev.button.x * ratio; - remote_action.m.y = ev.button.y * ratio; - - SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action, - sizeof(remote_action)); - } else if (SDL_BUTTON_RIGHT == ev.button.button) { - remote_action.type = ControlType::mouse; remote_action.m.flag = MouseFlag::right_down; - remote_action.m.x = ev.button.x * ratio; - remote_action.m.y = ev.button.y * ratio; - - SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action, - sizeof(remote_action)); } + SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action, + sizeof(remote_action)); } else if (SDL_MOUSEBUTTONUP == ev.type) { if (SDL_BUTTON_LEFT == ev.button.button) { - remote_action.type = ControlType::mouse; remote_action.m.flag = MouseFlag::left_up; - remote_action.m.x = ev.button.x * ratio; - remote_action.m.y = ev.button.y * ratio; - - SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action, - sizeof(remote_action)); - } else if (SDL_BUTTON_RIGHT == ev.button.button) { - remote_action.type = ControlType::mouse; remote_action.m.flag = MouseFlag::right_up; - remote_action.m.x = ev.button.x * ratio; - remote_action.m.y = ev.button.y * ratio; - - SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action, - sizeof(remote_action)); } + SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action, + sizeof(remote_action)); } else if (SDL_MOUSEMOTION == ev.type) { - remote_action.type = ControlType::mouse; remote_action.m.flag = MouseFlag::move; - remote_action.m.x = ev.button.x * ratio; - remote_action.m.y = ev.button.y * ratio; - SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action, sizeof(remote_action)); } else if (SDL_QUIT == ev.type) { @@ -288,8 +218,8 @@ inline int ProcessMouseKeyEven(SDL_Event &ev) { void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len) { int64_t delay = swr_get_delay(swr_ctx, src_rate); - dst_nb_samples = - av_rescale_rnd(delay + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); + dst_nb_samples = (int)av_rescale_rnd(delay + src_nb_samples, dst_rate, + src_rate, AV_ROUND_UP); if (dst_nb_samples > max_dst_nb_samples) { av_freep(&dst_data[0]); ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, @@ -392,11 +322,12 @@ void ServerReceiveDataBuffer(const char *data, size_t size, const char *user_id, RemoteAction remote_action; memcpy(&remote_action, data, sizeof(remote_action)); - std::cout << "remote_action: " << remote_action.type << " " - << remote_action.m.flag << " " << remote_action.m.x << " " - << remote_action.m.y << std::endl; - + // std::cout << "remote_action: " << remote_action.type << " " + // << remote_action.m.flag << " " << remote_action.m.x << " " + // << remote_action.m.y << std::endl; +#if MOUSE_CONTROL mouse_controller->SendCommand(remote_action); +#endif } void ClientReceiveDataBuffer(const char *data, size_t size, const char *user_id, @@ -627,30 +558,6 @@ std::string GetMac(char *mac_addr) { return mac_addr; } -int BGRAToNV12FFmpeg(unsigned char *src_buffer, int width, int height, - unsigned char *dst_buffer) { - AVFrame *Input_pFrame = av_frame_alloc(); - AVFrame *Output_pFrame = av_frame_alloc(); - struct SwsContext *img_convert_ctx = - sws_getContext(width, height, AV_PIX_FMT_BGRA, 1280, 720, AV_PIX_FMT_NV12, - SWS_FAST_BILINEAR, nullptr, nullptr, nullptr); - - av_image_fill_arrays(Input_pFrame->data, Input_pFrame->linesize, src_buffer, - AV_PIX_FMT_BGRA, width, height, 1); - av_image_fill_arrays(Output_pFrame->data, Output_pFrame->linesize, dst_buffer, - AV_PIX_FMT_NV12, 1280, 720, 1); - - sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data, - Input_pFrame->linesize, 0, height, Output_pFrame->data, - Output_pFrame->linesize); - - if (Input_pFrame) av_free(Input_pFrame); - if (Output_pFrame) av_free(Output_pFrame); - if (img_convert_ctx) sws_freeContext(img_convert_ctx); - - return 0; -} - int main() { LOG_INFO("Remote desk"); @@ -721,30 +628,18 @@ int main() { nv12_buffer = new char[NV12_BUFFER_SIZE]; - RECORD_DESKTOP_RECT rect; + // Screen capture + screen_capturer_factory = new ScreenCapturerFactory(); + screen_capturer = (ScreenCapturer *)screen_capturer_factory->Create(); + + last_frame_time_ = std::chrono::high_resolution_clock::now(); + ScreenCapturer::RECORD_DESKTOP_RECT rect; rect.left = 0; rect.top = 0; - -#ifdef _WIN32 rect.right = GetSystemMetrics(SM_CXSCREEN); rect.bottom = GetSystemMetrics(SM_CYSCREEN); - screen_capture = new ScreenCaptureWgc(); -#elif __linux__ - rect.right = 0; - rect.bottom = 0; - screen_capture = new ScreenCaptureX11(); -#elif __APPLE__ - rect.right = 0; - rect.bottom = 0; - screen_capture = new ScreenCaptureAvf(); -#endif - device_controller_factory = new DeviceControllerFactory(); - mouse_controller = (MouseController *)device_controller_factory->Create( - DeviceControllerFactory::Device::Mouse); - mouse_controller->Init(screen_w, screen_h); - last_frame_time_ = std::chrono::high_resolution_clock::now(); - screen_capture->Init( + screen_capturer->Init( rect, 60, [](unsigned char *data, int size, int width, int height) -> void { auto now_time = std::chrono::high_resolution_clock::now(); @@ -753,21 +648,19 @@ int main() { auto tc = duration.count() * 1000; if (tc >= 0) { -#ifdef _WIN32 - BGRAToNV12FFmpeg(data, width, height, - (unsigned char *)nv12_buffer); - SendData(peer_server, DATA_TYPE::VIDEO, (const char *)nv12_buffer, - NV12_BUFFER_SIZE); -#else SendData(peer_server, DATA_TYPE::VIDEO, (const char *)data, NV12_BUFFER_SIZE); last_frame_time_ = now_time; -#endif - last_frame_time_ = now_time; } }); - screen_capture->Start(); + screen_capturer->Start(); + + // Mouse control + device_controller_factory = new DeviceControllerFactory(); + mouse_controller = (MouseController *)device_controller_factory->Create( + DeviceControllerFactory::Device::Mouse); + mouse_controller->Init(screen_w, screen_h); } }); diff --git a/src/screen_capture/linux/screen_capture_x11.cpp b/src/screen_capturer/linux/screen_capturer_x11.cpp similarity index 86% rename from src/screen_capture/linux/screen_capture_x11.cpp rename to src/screen_capturer/linux/screen_capturer_x11.cpp index fcc80f7..990ebf6 100644 --- a/src/screen_capture/linux/screen_capture_x11.cpp +++ b/src/screen_capturer/linux/screen_capturer_x11.cpp @@ -1,4 +1,4 @@ -#include "screen_capture_x11.h" +#include "screen_capturer_x11.h" #include @@ -7,16 +7,12 @@ #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 unsigned char nv12_buffer_[NV12_BUFFER_SIZE]; -ScreenCaptureX11::ScreenCaptureX11() {} +ScreenCapturerX11::ScreenCapturerX11() {} -ScreenCaptureX11::~ScreenCaptureX11() { - if (capture_thread_->joinable()) { - capture_thread_->join(); - } -} +ScreenCapturerX11::~ScreenCapturerX11() {} -int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps, - cb_desktop_data cb) { +int ScreenCapturerX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps, + cb_desktop_data cb) { if (cb) { _on_data = cb; } @@ -98,7 +94,15 @@ int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps, return 0; } -int ScreenCaptureX11::Start() { +int ScreenCapturerX11::Destroy() { + if (capture_thread_->joinable()) { + capture_thread_->join(); + } + + return 0; +} + +int ScreenCapturerX11::Start() { capture_thread_.reset(new std::thread([this]() { while (1) { if (av_read_frame(pFormatCtx_, packet_) >= 0) { @@ -128,12 +132,12 @@ int ScreenCaptureX11::Start() { return 0; } -int ScreenCaptureX11::Pause() { return 0; } +int ScreenCapturerX11::Pause() { return 0; } -int ScreenCaptureX11::Resume() { return 0; } +int ScreenCapturerX11::Resume() { return 0; } -int ScreenCaptureX11::Stop() { return 0; } +int ScreenCapturerX11::Stop() { return 0; } -void ScreenCaptureX11::OnFrame() {} +void ScreenCapturerX11::OnFrame() {} -void ScreenCaptureX11::CleanUp() {} +void ScreenCapturerX11::CleanUp() {} diff --git a/src/screen_capture/linux/screen_capture_x11.h b/src/screen_capturer/linux/screen_capturer_x11.h similarity index 71% rename from src/screen_capture/linux/screen_capture_x11.h rename to src/screen_capturer/linux/screen_capturer_x11.h index 8229236..b95994e 100644 --- a/src/screen_capture/linux/screen_capture_x11.h +++ b/src/screen_capturer/linux/screen_capturer_x11.h @@ -1,11 +1,12 @@ -#ifndef _SCREEN_CAPTURE_X11_H_ -#define _SCREEN_CAPTURE_X11_H_ +#ifndef _SCREEN_CAPTURER_X11_H_ +#define _SCREEN_CAPTURER_X11_H_ #include #include #include #include +#include "screen_capturer.h" #ifdef __cplusplus extern "C" { #endif @@ -18,25 +19,19 @@ extern "C" { }; #endif -typedef struct { - int left; - int top; - int right; - int bottom; -} RECORD_DESKTOP_RECT; - -typedef std::function cb_desktop_data; -typedef std::function cb_desktop_error; - -class ScreenCaptureX11 { +class ScreenCapturerX11 : public ScreenCapturer { public: - ScreenCaptureX11(); - ~ScreenCaptureX11(); + ScreenCapturerX11(); + ~ScreenCapturerX11(); public: - int Init(const RECORD_DESKTOP_RECT &rect, const int fps, cb_desktop_data cb); + virtual int Init(const RECORD_DESKTOP_RECT &rect, const int fps, + cb_desktop_data cb); + + virtual int Destroy(); + + virtual int Start(); - int Start(); int Pause(); int Resume(); int Stop(); @@ -60,7 +55,6 @@ class ScreenCaptureX11 { int _fps; cb_desktop_data _on_data; - cb_desktop_error _on_error; private: int i_ = 0; diff --git a/src/screen_capture/linux/x11_session.h b/src/screen_capturer/linux/x11_session.h similarity index 100% rename from src/screen_capture/linux/x11_session.h rename to src/screen_capturer/linux/x11_session.h diff --git a/src/screen_capture/linux/x11_session_impl.cpp b/src/screen_capturer/linux/x11_session_impl.cpp similarity index 100% rename from src/screen_capture/linux/x11_session_impl.cpp rename to src/screen_capturer/linux/x11_session_impl.cpp diff --git a/src/screen_capture/linux/x11_session_impl.h b/src/screen_capturer/linux/x11_session_impl.h similarity index 100% rename from src/screen_capture/linux/x11_session_impl.h rename to src/screen_capturer/linux/x11_session_impl.h diff --git a/src/screen_capture/macosx/screen_capture_avf.cpp b/src/screen_capturer/macosx/screen_capturer_avf.cpp similarity index 86% rename from src/screen_capture/macosx/screen_capture_avf.cpp rename to src/screen_capturer/macosx/screen_capturer_avf.cpp index 6a7e881..765342f 100644 --- a/src/screen_capture/macosx/screen_capture_avf.cpp +++ b/src/screen_capturer/macosx/screen_capturer_avf.cpp @@ -1,4 +1,4 @@ -#include "screen_capture_avf.h" +#include "screen_capturer_avf.h" #include @@ -7,16 +7,12 @@ #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 unsigned char nv12_buffer_[NV12_BUFFER_SIZE]; -ScreenCaptureAvf::ScreenCaptureAvf() {} +ScreenCapturerAvf::ScreenCapturerAvf() {} -ScreenCaptureAvf::~ScreenCaptureAvf() { - if (capture_thread_->joinable()) { - capture_thread_->join(); - } -} +ScreenCapturerAvf::~ScreenCapturerAvf() {} -int ScreenCaptureAvf::Init(const RECORD_DESKTOP_RECT &rect, const int fps, - cb_desktop_data cb) { +int ScreenCapturerAvf::Init(const RECORD_DESKTOP_RECT &rect, const int fps, + cb_desktop_data cb) { if (cb) { _on_data = cb; } @@ -99,7 +95,15 @@ int ScreenCaptureAvf::Init(const RECORD_DESKTOP_RECT &rect, const int fps, return 0; } -int ScreenCaptureAvf::Start() { +int ScreenCapturerAvf::Destroy() { + if (capture_thread_->joinable()) { + capture_thread_->join(); + } + + return 0; +} + +int ScreenCapturerAvf::Start() { capture_thread_.reset(new std::thread([this]() { while (1) { if (av_read_frame(pFormatCtx_, packet_) >= 0) { @@ -129,12 +133,12 @@ int ScreenCaptureAvf::Start() { return 0; } -int ScreenCaptureAvf::Pause() { return 0; } +int ScreenCapturerAvf::Pause() { return 0; } -int ScreenCaptureAvf::Resume() { return 0; } +int ScreenCapturerAvf::Resume() { return 0; } -int ScreenCaptureAvf::Stop() { return 0; } +int ScreenCapturerAvf::Stop() { return 0; } -void ScreenCaptureAvf::OnFrame() {} +void ScreenCapturerAvf::OnFrame() {} -void ScreenCaptureAvf::CleanUp() {} +void ScreenCapturerAvf::CleanUp() {} diff --git a/src/screen_capture/macosx/screen_capture_avf.h b/src/screen_capturer/macosx/screen_capturer_avf.h similarity index 72% rename from src/screen_capture/macosx/screen_capture_avf.h rename to src/screen_capturer/macosx/screen_capturer_avf.h index 03f8f57..82a2bc0 100644 --- a/src/screen_capture/macosx/screen_capture_avf.h +++ b/src/screen_capturer/macosx/screen_capturer_avf.h @@ -4,14 +4,16 @@ * Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. */ -#ifndef _SCREEN_CAPTURE_AVF_H_ -#define _SCREEN_CAPTURE_AVF_H_ +#ifndef _SCREEN_CAPTURER_AVF_H_ +#define _SCREEN_CAPTURER_AVF_H_ #include #include #include #include +#include "screen_capturer.h" + #ifdef __cplusplus extern "C" { #endif @@ -24,25 +26,18 @@ extern "C" { }; #endif -typedef struct { - int left; - int top; - int right; - int bottom; -} RECORD_DESKTOP_RECT; - -typedef std::function cb_desktop_data; -typedef std::function cb_desktop_error; - -class ScreenCaptureAvf { +class ScreenCapturerAvf : public ScreenCapturer { public: - ScreenCaptureAvf(); - ~ScreenCaptureAvf(); + ScreenCapturerAvf(); + ~ScreenCapturerAvf(); public: - int Init(const RECORD_DESKTOP_RECT &rect, const int fps, cb_desktop_data cb); + virtual int Init(const RECORD_DESKTOP_RECT &rect, const int fps, + cb_desktop_data cb); + virtual int Destroy(); + + virtual int Start(); - int Start(); int Pause(); int Resume(); int Stop(); @@ -66,7 +61,6 @@ class ScreenCaptureAvf { int _fps; cb_desktop_data _on_data; - cb_desktop_error _on_error; private: int i_ = 0; diff --git a/src/screen_capturer/screen_capturer.h b/src/screen_capturer/screen_capturer.h new file mode 100644 index 0000000..731159d --- /dev/null +++ b/src/screen_capturer/screen_capturer.h @@ -0,0 +1,33 @@ +/* + * @Author: DI JUNKUN + * @Date: 2023-12-15 + * Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _SCREEN_CAPTURER_H_ +#define _SCREEN_CAPTURER_H_ + +#include + +class ScreenCapturer { + public: + typedef struct { + int left; + int top; + int right; + int bottom; + } RECORD_DESKTOP_RECT; + typedef std::function cb_desktop_data; + + public: + virtual ~ScreenCapturer() {} + + public: + virtual int Init(const RECORD_DESKTOP_RECT &rect, const int fps, + cb_desktop_data cb) = 0; + virtual int Destroy() = 0; + + virtual int Start() = 0; +}; + +#endif \ No newline at end of file diff --git a/src/screen_capturer/screen_capturer_factory.h b/src/screen_capturer/screen_capturer_factory.h new file mode 100644 index 0000000..55c0fad --- /dev/null +++ b/src/screen_capturer/screen_capturer_factory.h @@ -0,0 +1,37 @@ +/* + * @Author: DI JUNKUN + * @Date: 2023-12-15 + * Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _SCREEN_CAPTURER_FACTORY_H_ +#define _SCREEN_CAPTURER_FACTORY_H_ + +#ifdef _WIN32 + +#include "screen_capturer_wgc.h" +#elif __linux__ +#include "screen_capturer_x11.h" +#elif __APPLE__ +#include "screen_capturer_avf.h" +#endif + +class ScreenCapturerFactory { + public: + virtual ~ScreenCapturerFactory() {} + + public: + ScreenCapturer* Create() { +#ifdef _WIN32 + return new ScreenCapturerWgc(); +#elif __linux__ + return new ScreenCapturerX11(); +#elif __APPLE__ + return new ScreenCapturerAvf(); +#else + return nullptr; +#endif + } +}; + +#endif \ No newline at end of file diff --git a/src/screen_capture/windows/screen_capture_wgc.cpp b/src/screen_capturer/windows/screen_capturer_wgc.cpp similarity index 52% rename from src/screen_capture/windows/screen_capture_wgc.cpp rename to src/screen_capturer/windows/screen_capturer_wgc.cpp index 1bc0227..79a9960 100644 --- a/src/screen_capture/windows/screen_capture_wgc.cpp +++ b/src/screen_capturer/windows/screen_capturer_wgc.cpp @@ -1,12 +1,41 @@ -#include "screen_capture_wgc.h" +#include "screen_capturer_wgc.h" #include #include #include #include +extern "C" { +#include +#include +}; + #include +int BGRAToNV12FFmpeg(unsigned char *src_buffer, int width, int height, + unsigned char *dst_buffer) { + AVFrame *Input_pFrame = av_frame_alloc(); + AVFrame *Output_pFrame = av_frame_alloc(); + struct SwsContext *img_convert_ctx = + sws_getContext(width, height, AV_PIX_FMT_BGRA, 1280, 720, AV_PIX_FMT_NV12, + SWS_FAST_BILINEAR, nullptr, nullptr, nullptr); + + av_image_fill_arrays(Input_pFrame->data, Input_pFrame->linesize, src_buffer, + AV_PIX_FMT_BGRA, width, height, 1); + av_image_fill_arrays(Output_pFrame->data, Output_pFrame->linesize, dst_buffer, + AV_PIX_FMT_NV12, 1280, 720, 1); + + sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data, + Input_pFrame->linesize, 0, height, Output_pFrame->data, + Output_pFrame->linesize); + + if (Input_pFrame) av_free(Input_pFrame); + if (Output_pFrame) av_free(Output_pFrame); + if (img_convert_ctx) sws_freeContext(img_convert_ctx); + + return 0; +} + BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, HDC hdc, LPRECT lprc, LPARAM data) { MONITORINFOEX info_ex; @@ -31,14 +60,11 @@ HMONITOR GetPrimaryMonitor() { return hmonitor; } -ScreenCaptureWgc::ScreenCaptureWgc() {} +ScreenCapturerWgc::ScreenCapturerWgc() {} -ScreenCaptureWgc::~ScreenCaptureWgc() { - Stop(); - CleanUp(); -} +ScreenCapturerWgc::~ScreenCapturerWgc() {} -bool ScreenCaptureWgc::IsWgcSupported() { +bool ScreenCapturerWgc::IsWgcSupported() { try { /* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */ return winrt::Windows::Foundation::Metadata::ApiInformation:: @@ -50,11 +76,13 @@ bool ScreenCaptureWgc::IsWgcSupported() { } } -int ScreenCaptureWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps, - cb_desktop_data cb) { +int ScreenCapturerWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps, + cb_desktop_data cb) { int error = 0; if (_inited == true) return error; + nv12_frame_ = new unsigned char[rect.right * rect.bottom * 4]; + _fps = fps; _on_data = cb; @@ -86,7 +114,19 @@ int ScreenCaptureWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps, return error; } -int ScreenCaptureWgc::Start() { +int ScreenCapturerWgc::Destroy() { + if (nv12_frame_) { + delete nv12_frame_; + nv12_frame_ = nullptr; + } + + Stop(); + CleanUp(); + + return 0; +} + +int ScreenCapturerWgc::Start() { if (_running == true) { std::cout << "record desktop duplication is already running" << std::endl; return 0; @@ -103,19 +143,19 @@ int ScreenCaptureWgc::Start() { return 0; } -int ScreenCaptureWgc::Pause() { +int ScreenCapturerWgc::Pause() { _paused = true; if (session_) session_->Pause(); return 0; } -int ScreenCaptureWgc::Resume() { +int ScreenCapturerWgc::Resume() { _paused = false; if (session_) session_->Resume(); return 0; } -int ScreenCaptureWgc::Stop() { +int ScreenCapturerWgc::Stop() { _running = false; if (session_) session_->Stop(); @@ -123,13 +163,15 @@ int ScreenCaptureWgc::Stop() { return 0; } -void ScreenCaptureWgc::OnFrame(const WgcSession::wgc_session_frame &frame) { +void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame) { if (_on_data) - _on_data((unsigned char *)frame.data, frame.width * frame.height * 4, - frame.width, frame.height); + BGRAToNV12FFmpeg((unsigned char *)frame.data, frame.width, frame.height, + nv12_frame_); + _on_data(nv12_frame_, frame.width * frame.height * 4, frame.width, + frame.height); } -void ScreenCaptureWgc::CleanUp() { +void ScreenCapturerWgc::CleanUp() { _inited = false; if (session_) session_->Release(); diff --git a/src/screen_capture/windows/screen_capture_wgc.h b/src/screen_capturer/windows/screen_capturer_wgc.h similarity index 52% rename from src/screen_capture/windows/screen_capture_wgc.h rename to src/screen_capturer/windows/screen_capturer_wgc.h index 99610e7..21b9c13 100644 --- a/src/screen_capture/windows/screen_capture_wgc.h +++ b/src/screen_capturer/windows/screen_capturer_wgc.h @@ -1,35 +1,30 @@ -#ifndef _SCREEN_CAPTURE_WGC_H_ -#define _SCREEN_CAPTURE_WGC_H_ +#ifndef _SCREEN_CAPTURER_WGC_H_ +#define _SCREEN_CAPTURER_WGC_H_ #include #include #include #include +#include "screen_capturer.h" #include "wgc_session.h" #include "wgc_session_impl.h" -typedef struct { - int left; - int top; - int right; - int bottom; -} RECORD_DESKTOP_RECT; - -typedef std::function cb_desktop_data; -typedef std::function cb_desktop_error; - -class ScreenCaptureWgc : public WgcSession::wgc_session_observer { +class ScreenCapturerWgc : public ScreenCapturer, + public WgcSession::wgc_session_observer { public: - ScreenCaptureWgc(); - ~ScreenCaptureWgc(); + ScreenCapturerWgc(); + ~ScreenCapturerWgc(); public: bool IsWgcSupported(); - int Init(const RECORD_DESKTOP_RECT &rect, const int fps, cb_desktop_data cb); + virtual int Init(const RECORD_DESKTOP_RECT &rect, const int fps, + cb_desktop_data cb); + virtual int Destroy(); + + virtual int Start(); - int Start(); int Pause(); int Resume(); int Stop(); @@ -55,7 +50,8 @@ class ScreenCaptureWgc : public WgcSession::wgc_session_observer { int _fps; cb_desktop_data _on_data; - cb_desktop_error _on_error; + + unsigned char *nv12_frame_ = nullptr; }; #endif \ No newline at end of file diff --git a/src/screen_capture/windows/wgc_session.h b/src/screen_capturer/windows/wgc_session.h similarity index 100% rename from src/screen_capture/windows/wgc_session.h rename to src/screen_capturer/windows/wgc_session.h diff --git a/src/screen_capture/windows/wgc_session_impl.cpp b/src/screen_capturer/windows/wgc_session_impl.cpp similarity index 100% rename from src/screen_capture/windows/wgc_session_impl.cpp rename to src/screen_capturer/windows/wgc_session_impl.cpp diff --git a/src/screen_capture/windows/wgc_session_impl.h b/src/screen_capturer/windows/wgc_session_impl.h similarity index 100% rename from src/screen_capture/windows/wgc_session_impl.h rename to src/screen_capturer/windows/wgc_session_impl.h diff --git a/xmake.lua b/xmake.lua index a65c51c..3ef384f 100644 --- a/xmake.lua +++ b/xmake.lua @@ -5,8 +5,8 @@ set_license("LGPL-3.0") add_rules("mode.release", "mode.debug") set_languages("c++17") --- set_policy("build.warning", true) --- set_warnings("all", "extra") +set_policy("build.warning", true) +set_warnings("all", "extra") add_defines("UNICODE") if is_mode("debug") then @@ -53,40 +53,39 @@ target("log") add_headerfiles("src/log/log.h") add_includedirs("src/log", {public = true}) -target("screen_capture") +target("screen_capturer") set_kind("object") add_deps("log") + add_includedirs("src/screen_capturer", {public = true}) if is_os("windows") then - add_files("src/screen_capture/windows/*.cpp") - add_includedirs("src/screen_capture/windows", {public = true}) + add_files("src/screen_capturer/windows/*.cpp") + add_includedirs("src/screen_capturer/windows", {public = true}) elseif is_os("macosx") then - add_files("src/screen_capture/macosx/*.cpp") - add_includedirs("src/screen_capture/macosx", {public = true}) + add_files("src/screen_capturer/macosx/*.cpp") + add_includedirs("src/screen_capturer/macosx", {public = true}) elseif is_os("linux") then - add_files("src/screen_capture/linux/*.cpp") - add_includedirs("src/screen_capture/linux", {public = true}) + add_files("src/screen_capturer/linux/*.cpp") + add_includedirs("src/screen_capturer/linux", {public = true}) end target("device_controller") set_kind("object") add_deps("log") + add_includedirs("src/device_controller", {public = true}) if is_os("windows") then add_files("src/device_controller/mouse/windows/*.cpp") add_includedirs("src/device_controller/mouse/windows", {public = true}) - add_includedirs("src/device_controller", {public = true}) elseif is_os("macosx") then add_files("src/device_controller/mouse/mac/*.cpp") add_includedirs("src/device_controller/mouse/mac", {public = true}) - add_includedirs("src/device_controller", {public = true}) elseif is_os("linux") then add_files("src/device_controller/mouse/linux/*.cpp") add_includedirs("src/device_controller/mouse/linux", {public = true}) - add_includedirs("src/device_controller", {public = true}) end target("remote_desk") set_kind("binary") - add_deps("log", "screen_capture", "device_controller", "projectx") + add_deps("log", "screen_capturer", "device_controller", "projectx") add_files("src/gui/main.cpp") -- after_install(function (target) @@ -97,20 +96,20 @@ target("remote_desk") -- os.rm("$(projectdir)/out/lib") -- end) --- target("screen_capture") +-- target("screen_capturer") -- set_kind("binary") -- add_packages("sdl2", "imgui", "ffmpeg", "openh264") --- add_files("test/screen_capture/linux_capture.cpp") +-- add_files("test/screen_capturer/linux_capture.cpp") -- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec", -- "-lswscale", "-lavutil", "-lswresample", -- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb", -- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264", -- "-ldl", {force = true}) --- target("screen_capture") +-- target("screen_capturer") -- set_kind("binary") -- add_packages("sdl2", "imgui", "ffmpeg", "openh264") --- add_files("test/screen_capture/mac_capture.cpp") +-- add_files("test/screen_capturer/mac_capture.cpp") -- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec", -- "-lswscale", "-lavutil", "-lswresample", -- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",