Use factory method to create screen capturer

This commit is contained in:
dijunkun
2023-12-15 17:29:17 +08:00
parent 9276d5bfec
commit 2fc89923ae
17 changed files with 256 additions and 260 deletions

View File

@@ -12,7 +12,7 @@
class DeviceControllerFactory { class DeviceControllerFactory {
public: public:
enum Device { Mouse, Keyboard }; enum Device { Mouse = 0, Keyboard };
public: public:
virtual ~DeviceControllerFactory() {} virtual ~DeviceControllerFactory() {}

View File

@@ -28,33 +28,20 @@
#include <thread> #include <thread>
extern "C" { extern "C" {
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h> #include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h> #include <libswresample/swresample.h>
#include <libswscale/swscale.h> #include <libswscale/swscale.h>
}; };
#include <stdio.h> #include <stdio.h>
#include "../../thirdparty/projectx/src/interface/x.h"
#include "device_controller_factory.h"
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_sdl2.h" #include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer2.h" #include "imgui_impl_sdlrenderer2.h"
#include "log.h" #include "log.h"
#ifdef _WIN32 #include "screen_capturer_factory.h"
#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"
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 #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 is_create_connection = false;
static bool done = false; static bool done = false;
#ifdef _WIN32 ScreenCapturerFactory *screen_capturer_factory = nullptr;
ScreenCaptureWgc *screen_capture = nullptr; ScreenCapturer *screen_capturer = nullptr;
#elif __linux__
ScreenCaptureX11 *screen_capture = nullptr;
#elif __APPLE__
ScreenCaptureAvf *screen_capture = nullptr;
#endif
DeviceControllerFactory *device_controller_factory = nullptr; DeviceControllerFactory *device_controller_factory = nullptr;
MouseController *mouse_controller = nullptr; MouseController *mouse_controller = nullptr;
@@ -176,43 +158,16 @@ char *nv12_buffer = nullptr;
#ifdef __linux__ #ifdef __linux__
std::chrono::_V2::system_clock::time_point last_frame_time_; 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<int> mouse_pos_x_last = -65535;
static std::atomic<int> mouse_pos_y_last = -65535;
#else #else
std::chrono::steady_clock::time_point last_frame_time_; std::chrono::steady_clock::time_point last_frame_time_;
#endif #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) { inline int ProcessMouseKeyEven(SDL_Event &ev) {
float ratio = 1280.0 / window_w; float ratio = (float)(1280.0 / window_w);
RemoteAction remote_action; 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 if (SDL_KEYDOWN == ev.type) // SDL_KEYUP
{ {
@@ -230,49 +185,24 @@ inline int ProcessMouseKeyEven(SDL_Event &ev) {
// printf("SDLK_RIGHT \n"); // printf("SDLK_RIGHT \n");
} }
} else if (SDL_MOUSEBUTTONDOWN == ev.type) { } else if (SDL_MOUSEBUTTONDOWN == ev.type) {
remote_action.type = ControlType::mouse;
if (SDL_BUTTON_LEFT == ev.button.button) { if (SDL_BUTTON_LEFT == ev.button.button) {
remote_action.type = ControlType::mouse;
remote_action.m.flag = MouseFlag::left_down; 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) { } else if (SDL_BUTTON_RIGHT == ev.button.button) {
remote_action.type = ControlType::mouse;
remote_action.m.flag = MouseFlag::right_down; 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, SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action,
sizeof(remote_action)); sizeof(remote_action));
}
} else if (SDL_MOUSEBUTTONUP == ev.type) { } else if (SDL_MOUSEBUTTONUP == ev.type) {
if (SDL_BUTTON_LEFT == ev.button.button) { if (SDL_BUTTON_LEFT == ev.button.button) {
remote_action.type = ControlType::mouse;
remote_action.m.flag = MouseFlag::left_up; 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) { } else if (SDL_BUTTON_RIGHT == ev.button.button) {
remote_action.type = ControlType::mouse;
remote_action.m.flag = MouseFlag::right_up; 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, SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action,
sizeof(remote_action)); sizeof(remote_action));
}
} else if (SDL_MOUSEMOTION == ev.type) { } else if (SDL_MOUSEMOTION == ev.type) {
remote_action.type = ControlType::mouse;
remote_action.m.flag = MouseFlag::move; 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, SendData(peer_client, DATA_TYPE::DATA, (const char *)&remote_action,
sizeof(remote_action)); sizeof(remote_action));
} else if (SDL_QUIT == ev.type) { } else if (SDL_QUIT == ev.type) {
@@ -288,8 +218,8 @@ inline int ProcessMouseKeyEven(SDL_Event &ev) {
void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len) { void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len) {
int64_t delay = swr_get_delay(swr_ctx, src_rate); int64_t delay = swr_get_delay(swr_ctx, src_rate);
dst_nb_samples = dst_nb_samples = (int)av_rescale_rnd(delay + src_nb_samples, dst_rate,
av_rescale_rnd(delay + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); src_rate, AV_ROUND_UP);
if (dst_nb_samples > max_dst_nb_samples) { if (dst_nb_samples > max_dst_nb_samples) {
av_freep(&dst_data[0]); av_freep(&dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, 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; RemoteAction remote_action;
memcpy(&remote_action, data, sizeof(remote_action)); memcpy(&remote_action, data, sizeof(remote_action));
std::cout << "remote_action: " << remote_action.type << " " // std::cout << "remote_action: " << remote_action.type << " "
<< remote_action.m.flag << " " << remote_action.m.x << " " // << remote_action.m.flag << " " << remote_action.m.x << " "
<< remote_action.m.y << std::endl; // << remote_action.m.y << std::endl;
#if MOUSE_CONTROL
mouse_controller->SendCommand(remote_action); mouse_controller->SendCommand(remote_action);
#endif
} }
void ClientReceiveDataBuffer(const char *data, size_t size, const char *user_id, 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; 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() { int main() {
LOG_INFO("Remote desk"); LOG_INFO("Remote desk");
@@ -721,30 +628,18 @@ int main() {
nv12_buffer = new char[NV12_BUFFER_SIZE]; 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.left = 0;
rect.top = 0; rect.top = 0;
#ifdef _WIN32
rect.right = GetSystemMetrics(SM_CXSCREEN); rect.right = GetSystemMetrics(SM_CXSCREEN);
rect.bottom = GetSystemMetrics(SM_CYSCREEN); 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(); screen_capturer->Init(
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(
rect, 60, rect, 60,
[](unsigned char *data, int size, int width, int height) -> void { [](unsigned char *data, int size, int width, int height) -> void {
auto now_time = std::chrono::high_resolution_clock::now(); auto now_time = std::chrono::high_resolution_clock::now();
@@ -753,21 +648,19 @@ int main() {
auto tc = duration.count() * 1000; auto tc = duration.count() * 1000;
if (tc >= 0) { 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, SendData(peer_server, DATA_TYPE::VIDEO, (const char *)data,
NV12_BUFFER_SIZE); NV12_BUFFER_SIZE);
last_frame_time_ = now_time; 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);
} }
}); });

View File

@@ -1,4 +1,4 @@
#include "screen_capture_x11.h" #include "screen_capturer_x11.h"
#include <iostream> #include <iostream>
@@ -7,15 +7,11 @@
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
unsigned char nv12_buffer_[NV12_BUFFER_SIZE]; unsigned char nv12_buffer_[NV12_BUFFER_SIZE];
ScreenCaptureX11::ScreenCaptureX11() {} ScreenCapturerX11::ScreenCapturerX11() {}
ScreenCaptureX11::~ScreenCaptureX11() { ScreenCapturerX11::~ScreenCapturerX11() {}
if (capture_thread_->joinable()) {
capture_thread_->join();
}
}
int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps, int ScreenCapturerX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
cb_desktop_data cb) { cb_desktop_data cb) {
if (cb) { if (cb) {
_on_data = cb; _on_data = cb;
@@ -98,7 +94,15 @@ int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
return 0; 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]() { capture_thread_.reset(new std::thread([this]() {
while (1) { while (1) {
if (av_read_frame(pFormatCtx_, packet_) >= 0) { if (av_read_frame(pFormatCtx_, packet_) >= 0) {
@@ -128,12 +132,12 @@ int ScreenCaptureX11::Start() {
return 0; 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() {}

View File

@@ -1,11 +1,12 @@
#ifndef _SCREEN_CAPTURE_X11_H_ #ifndef _SCREEN_CAPTURER_X11_H_
#define _SCREEN_CAPTURE_X11_H_ #define _SCREEN_CAPTURER_X11_H_
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <string> #include <string>
#include <thread> #include <thread>
#include "screen_capturer.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -18,25 +19,19 @@ extern "C" {
}; };
#endif #endif
typedef struct { class ScreenCapturerX11 : public ScreenCapturer {
int left;
int top;
int right;
int bottom;
} RECORD_DESKTOP_RECT;
typedef std::function<void(unsigned char *, int, int, int)> cb_desktop_data;
typedef std::function<void(int)> cb_desktop_error;
class ScreenCaptureX11 {
public: public:
ScreenCaptureX11(); ScreenCapturerX11();
~ScreenCaptureX11(); ~ScreenCapturerX11();
public: 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 Pause();
int Resume(); int Resume();
int Stop(); int Stop();
@@ -60,7 +55,6 @@ class ScreenCaptureX11 {
int _fps; int _fps;
cb_desktop_data _on_data; cb_desktop_data _on_data;
cb_desktop_error _on_error;
private: private:
int i_ = 0; int i_ = 0;

View File

@@ -1,4 +1,4 @@
#include "screen_capture_avf.h" #include "screen_capturer_avf.h"
#include <iostream> #include <iostream>
@@ -7,15 +7,11 @@
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
unsigned char nv12_buffer_[NV12_BUFFER_SIZE]; unsigned char nv12_buffer_[NV12_BUFFER_SIZE];
ScreenCaptureAvf::ScreenCaptureAvf() {} ScreenCapturerAvf::ScreenCapturerAvf() {}
ScreenCaptureAvf::~ScreenCaptureAvf() { ScreenCapturerAvf::~ScreenCapturerAvf() {}
if (capture_thread_->joinable()) {
capture_thread_->join();
}
}
int ScreenCaptureAvf::Init(const RECORD_DESKTOP_RECT &rect, const int fps, int ScreenCapturerAvf::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
cb_desktop_data cb) { cb_desktop_data cb) {
if (cb) { if (cb) {
_on_data = cb; _on_data = cb;
@@ -99,7 +95,15 @@ int ScreenCaptureAvf::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
return 0; 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]() { capture_thread_.reset(new std::thread([this]() {
while (1) { while (1) {
if (av_read_frame(pFormatCtx_, packet_) >= 0) { if (av_read_frame(pFormatCtx_, packet_) >= 0) {
@@ -129,12 +133,12 @@ int ScreenCaptureAvf::Start() {
return 0; 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() {}

View File

@@ -4,14 +4,16 @@
* Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. * Copyright (c) 2023 by DI JUNKUN, All Rights Reserved.
*/ */
#ifndef _SCREEN_CAPTURE_AVF_H_ #ifndef _SCREEN_CAPTURER_AVF_H_
#define _SCREEN_CAPTURE_AVF_H_ #define _SCREEN_CAPTURER_AVF_H_
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <string> #include <string>
#include <thread> #include <thread>
#include "screen_capturer.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -24,25 +26,18 @@ extern "C" {
}; };
#endif #endif
typedef struct { class ScreenCapturerAvf : public ScreenCapturer {
int left;
int top;
int right;
int bottom;
} RECORD_DESKTOP_RECT;
typedef std::function<void(unsigned char *, int, int, int)> cb_desktop_data;
typedef std::function<void(int)> cb_desktop_error;
class ScreenCaptureAvf {
public: public:
ScreenCaptureAvf(); ScreenCapturerAvf();
~ScreenCaptureAvf(); ~ScreenCapturerAvf();
public: 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 Pause();
int Resume(); int Resume();
int Stop(); int Stop();
@@ -66,7 +61,6 @@ class ScreenCaptureAvf {
int _fps; int _fps;
cb_desktop_data _on_data; cb_desktop_data _on_data;
cb_desktop_error _on_error;
private: private:
int i_ = 0; int i_ = 0;

View File

@@ -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 <functional>
class ScreenCapturer {
public:
typedef struct {
int left;
int top;
int right;
int bottom;
} RECORD_DESKTOP_RECT;
typedef std::function<void(unsigned char *, int, int, int)> 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

View File

@@ -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

View File

@@ -1,12 +1,41 @@
#include "screen_capture_wgc.h" #include "screen_capturer_wgc.h"
#include <Windows.h> #include <Windows.h>
#include <d3d11_4.h> #include <d3d11_4.h>
#include <winrt/Windows.Foundation.Metadata.h> #include <winrt/Windows.Foundation.Metadata.h>
#include <winrt/Windows.Graphics.Capture.h> #include <winrt/Windows.Graphics.Capture.h>
extern "C" {
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
};
#include <iostream> #include <iostream>
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, BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, HDC hdc, LPRECT lprc,
LPARAM data) { LPARAM data) {
MONITORINFOEX info_ex; MONITORINFOEX info_ex;
@@ -31,14 +60,11 @@ HMONITOR GetPrimaryMonitor() {
return hmonitor; return hmonitor;
} }
ScreenCaptureWgc::ScreenCaptureWgc() {} ScreenCapturerWgc::ScreenCapturerWgc() {}
ScreenCaptureWgc::~ScreenCaptureWgc() { ScreenCapturerWgc::~ScreenCapturerWgc() {}
Stop();
CleanUp();
}
bool ScreenCaptureWgc::IsWgcSupported() { bool ScreenCapturerWgc::IsWgcSupported() {
try { try {
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */ /* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
return winrt::Windows::Foundation::Metadata::ApiInformation:: return winrt::Windows::Foundation::Metadata::ApiInformation::
@@ -50,11 +76,13 @@ bool ScreenCaptureWgc::IsWgcSupported() {
} }
} }
int ScreenCaptureWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps, int ScreenCapturerWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
cb_desktop_data cb) { cb_desktop_data cb) {
int error = 0; int error = 0;
if (_inited == true) return error; if (_inited == true) return error;
nv12_frame_ = new unsigned char[rect.right * rect.bottom * 4];
_fps = fps; _fps = fps;
_on_data = cb; _on_data = cb;
@@ -86,7 +114,19 @@ int ScreenCaptureWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
return error; 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) { if (_running == true) {
std::cout << "record desktop duplication is already running" << std::endl; std::cout << "record desktop duplication is already running" << std::endl;
return 0; return 0;
@@ -103,19 +143,19 @@ int ScreenCaptureWgc::Start() {
return 0; return 0;
} }
int ScreenCaptureWgc::Pause() { int ScreenCapturerWgc::Pause() {
_paused = true; _paused = true;
if (session_) session_->Pause(); if (session_) session_->Pause();
return 0; return 0;
} }
int ScreenCaptureWgc::Resume() { int ScreenCapturerWgc::Resume() {
_paused = false; _paused = false;
if (session_) session_->Resume(); if (session_) session_->Resume();
return 0; return 0;
} }
int ScreenCaptureWgc::Stop() { int ScreenCapturerWgc::Stop() {
_running = false; _running = false;
if (session_) session_->Stop(); if (session_) session_->Stop();
@@ -123,13 +163,15 @@ int ScreenCaptureWgc::Stop() {
return 0; return 0;
} }
void ScreenCaptureWgc::OnFrame(const WgcSession::wgc_session_frame &frame) { void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame) {
if (_on_data) if (_on_data)
_on_data((unsigned char *)frame.data, frame.width * frame.height * 4, BGRAToNV12FFmpeg((unsigned char *)frame.data, frame.width, frame.height,
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; _inited = false;
if (session_) session_->Release(); if (session_) session_->Release();

View File

@@ -1,35 +1,30 @@
#ifndef _SCREEN_CAPTURE_WGC_H_ #ifndef _SCREEN_CAPTURER_WGC_H_
#define _SCREEN_CAPTURE_WGC_H_ #define _SCREEN_CAPTURER_WGC_H_
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <string> #include <string>
#include <thread> #include <thread>
#include "screen_capturer.h"
#include "wgc_session.h" #include "wgc_session.h"
#include "wgc_session_impl.h" #include "wgc_session_impl.h"
typedef struct { class ScreenCapturerWgc : public ScreenCapturer,
int left; public WgcSession::wgc_session_observer {
int top;
int right;
int bottom;
} RECORD_DESKTOP_RECT;
typedef std::function<void(unsigned char *, int, int, int)> cb_desktop_data;
typedef std::function<void(int)> cb_desktop_error;
class ScreenCaptureWgc : public WgcSession::wgc_session_observer {
public: public:
ScreenCaptureWgc(); ScreenCapturerWgc();
~ScreenCaptureWgc(); ~ScreenCapturerWgc();
public: public:
bool IsWgcSupported(); 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 Pause();
int Resume(); int Resume();
int Stop(); int Stop();
@@ -55,7 +50,8 @@ class ScreenCaptureWgc : public WgcSession::wgc_session_observer {
int _fps; int _fps;
cb_desktop_data _on_data; cb_desktop_data _on_data;
cb_desktop_error _on_error;
unsigned char *nv12_frame_ = nullptr;
}; };
#endif #endif

View File

@@ -5,8 +5,8 @@ set_license("LGPL-3.0")
add_rules("mode.release", "mode.debug") add_rules("mode.release", "mode.debug")
set_languages("c++17") set_languages("c++17")
-- set_policy("build.warning", true) set_policy("build.warning", true)
-- set_warnings("all", "extra") set_warnings("all", "extra")
add_defines("UNICODE") add_defines("UNICODE")
if is_mode("debug") then if is_mode("debug") then
@@ -53,40 +53,39 @@ target("log")
add_headerfiles("src/log/log.h") add_headerfiles("src/log/log.h")
add_includedirs("src/log", {public = true}) add_includedirs("src/log", {public = true})
target("screen_capture") target("screen_capturer")
set_kind("object") set_kind("object")
add_deps("log") add_deps("log")
add_includedirs("src/screen_capturer", {public = true})
if is_os("windows") then if is_os("windows") then
add_files("src/screen_capture/windows/*.cpp") add_files("src/screen_capturer/windows/*.cpp")
add_includedirs("src/screen_capture/windows", {public = true}) add_includedirs("src/screen_capturer/windows", {public = true})
elseif is_os("macosx") then elseif is_os("macosx") then
add_files("src/screen_capture/macosx/*.cpp") add_files("src/screen_capturer/macosx/*.cpp")
add_includedirs("src/screen_capture/macosx", {public = true}) add_includedirs("src/screen_capturer/macosx", {public = true})
elseif is_os("linux") then elseif is_os("linux") then
add_files("src/screen_capture/linux/*.cpp") add_files("src/screen_capturer/linux/*.cpp")
add_includedirs("src/screen_capture/linux", {public = true}) add_includedirs("src/screen_capturer/linux", {public = true})
end end
target("device_controller") target("device_controller")
set_kind("object") set_kind("object")
add_deps("log") add_deps("log")
add_includedirs("src/device_controller", {public = true})
if is_os("windows") then if is_os("windows") then
add_files("src/device_controller/mouse/windows/*.cpp") add_files("src/device_controller/mouse/windows/*.cpp")
add_includedirs("src/device_controller/mouse/windows", {public = true}) add_includedirs("src/device_controller/mouse/windows", {public = true})
add_includedirs("src/device_controller", {public = true})
elseif is_os("macosx") then elseif is_os("macosx") then
add_files("src/device_controller/mouse/mac/*.cpp") add_files("src/device_controller/mouse/mac/*.cpp")
add_includedirs("src/device_controller/mouse/mac", {public = true}) add_includedirs("src/device_controller/mouse/mac", {public = true})
add_includedirs("src/device_controller", {public = true})
elseif is_os("linux") then elseif is_os("linux") then
add_files("src/device_controller/mouse/linux/*.cpp") add_files("src/device_controller/mouse/linux/*.cpp")
add_includedirs("src/device_controller/mouse/linux", {public = true}) add_includedirs("src/device_controller/mouse/linux", {public = true})
add_includedirs("src/device_controller", {public = true})
end end
target("remote_desk") target("remote_desk")
set_kind("binary") 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") add_files("src/gui/main.cpp")
-- after_install(function (target) -- after_install(function (target)
@@ -97,20 +96,20 @@ target("remote_desk")
-- os.rm("$(projectdir)/out/lib") -- os.rm("$(projectdir)/out/lib")
-- end) -- end)
-- target("screen_capture") -- target("screen_capturer")
-- set_kind("binary") -- set_kind("binary")
-- add_packages("sdl2", "imgui", "ffmpeg", "openh264") -- 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", -- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec",
-- "-lswscale", "-lavutil", "-lswresample", -- "-lswscale", "-lavutil", "-lswresample",
-- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb", -- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",
-- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264", -- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264",
-- "-ldl", {force = true}) -- "-ldl", {force = true})
-- target("screen_capture") -- target("screen_capturer")
-- set_kind("binary") -- set_kind("binary")
-- add_packages("sdl2", "imgui", "ffmpeg", "openh264") -- 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", -- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec",
-- "-lswscale", "-lavutil", "-lswresample", -- "-lswscale", "-lavutil", "-lswresample",
-- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb", -- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",