mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-27 04:35:34 +08:00
[feat] use SDL_WaitEventTimeout to refresh frames and reduce CPU usage
This commit is contained in:
@@ -982,8 +982,12 @@ void Render::MainLoop() {
|
|||||||
CreateConnectionPeer();
|
CreateConnectionPeer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
if (SDL_WaitEventTimeout(&event, sdl_refresh_ms_)) {
|
||||||
|
ProcessSdlEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateLabels();
|
UpdateLabels();
|
||||||
ProcessSdlEvent();
|
|
||||||
HandleRecentConnections();
|
HandleRecentConnections();
|
||||||
HandleStreamWindow();
|
HandleStreamWindow();
|
||||||
|
|
||||||
@@ -1229,176 +1233,174 @@ void Render::UpdateRenderRect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render::ProcessSdlEvent() {
|
void Render::ProcessSdlEvent(const SDL_Event& event) {
|
||||||
SDL_Event event;
|
if (main_ctx_) {
|
||||||
while (SDL_PollEvent(&event)) {
|
ImGui::SetCurrentContext(main_ctx_);
|
||||||
if (main_ctx_) {
|
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||||
ImGui::SetCurrentContext(main_ctx_);
|
} else {
|
||||||
|
LOG_ERROR("Main context is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_window_inited_) {
|
||||||
|
if (stream_ctx_) {
|
||||||
|
ImGui::SetCurrentContext(stream_ctx_);
|
||||||
ImGui_ImplSDL3_ProcessEvent(&event);
|
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("Main context is null");
|
LOG_ERROR("Stream context is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stream_window_inited_) {
|
switch (event.type) {
|
||||||
if (stream_ctx_) {
|
case SDL_EVENT_QUIT:
|
||||||
ImGui::SetCurrentContext(stream_ctx_);
|
if (stream_window_inited_) {
|
||||||
ImGui_ImplSDL3_ProcessEvent(&event);
|
LOG_INFO("Destroy stream window");
|
||||||
} else {
|
SDL_SetWindowMouseGrab(stream_window_, false);
|
||||||
LOG_ERROR("Stream context is null");
|
DestroyStreamWindow();
|
||||||
return;
|
DestroyStreamWindowContext();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event.type) {
|
for (auto& [host_name, props] : client_properties_) {
|
||||||
case SDL_EVENT_QUIT:
|
thumbnail_->SaveToThumbnail(
|
||||||
if (stream_window_inited_) {
|
(char*)props->dst_buffer_, props->video_width_,
|
||||||
LOG_INFO("Destroy stream window");
|
props->video_height_, host_name, props->remote_host_name_,
|
||||||
SDL_SetWindowMouseGrab(stream_window_, false);
|
props->remember_password_ ? props->remote_password_ : "");
|
||||||
DestroyStreamWindow();
|
|
||||||
DestroyStreamWindowContext();
|
|
||||||
|
|
||||||
for (auto& [host_name, props] : client_properties_) {
|
if (props->peer_) {
|
||||||
thumbnail_->SaveToThumbnail(
|
std::string client_id = (host_name == client_id_)
|
||||||
(char*)props->dst_buffer_, props->video_width_,
|
? "C-" + std::string(client_id_)
|
||||||
props->video_height_, host_name, props->remote_host_name_,
|
: client_id_;
|
||||||
props->remember_password_ ? props->remote_password_ : "");
|
LOG_INFO("[{}] Leave connection [{}]", client_id, host_name);
|
||||||
|
LeaveConnection(props->peer_, host_name.c_str());
|
||||||
if (props->peer_) {
|
LOG_INFO("Destroy peer [{}]", client_id);
|
||||||
std::string client_id = (host_name == client_id_)
|
DestroyPeer(&props->peer_);
|
||||||
? "C-" + std::string(client_id_)
|
|
||||||
: client_id_;
|
|
||||||
LOG_INFO("[{}] Leave connection [{}]", client_id, host_name);
|
|
||||||
LeaveConnection(props->peer_, host_name.c_str());
|
|
||||||
LOG_INFO("Destroy peer [{}]", client_id);
|
|
||||||
DestroyPeer(&props->peer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
props->streaming_ = false;
|
|
||||||
props->remember_password_ = false;
|
|
||||||
props->connection_established_ = false;
|
|
||||||
props->audio_capture_button_pressed_ = false;
|
|
||||||
|
|
||||||
memset(&props->net_traffic_stats_, 0,
|
|
||||||
sizeof(props->net_traffic_stats_));
|
|
||||||
SDL_SetWindowFullscreen(main_window_, false);
|
|
||||||
SDL_FlushEvents(STREAM_REFRESH_EVENT, STREAM_REFRESH_EVENT);
|
|
||||||
memset(audio_buffer_, 0, 720);
|
|
||||||
}
|
}
|
||||||
client_properties_.clear();
|
|
||||||
|
|
||||||
rejoin_ = false;
|
props->streaming_ = false;
|
||||||
is_client_mode_ = false;
|
props->remember_password_ = false;
|
||||||
reload_recent_connections_ = true;
|
props->connection_established_ = false;
|
||||||
fullscreen_button_pressed_ = false;
|
props->audio_capture_button_pressed_ = false;
|
||||||
just_created_ = false;
|
|
||||||
recent_connection_image_save_time_ = SDL_GetTicks();
|
memset(&props->net_traffic_stats_, 0,
|
||||||
|
sizeof(props->net_traffic_stats_));
|
||||||
|
SDL_SetWindowFullscreen(main_window_, false);
|
||||||
|
SDL_FlushEvents(STREAM_REFRESH_EVENT, STREAM_REFRESH_EVENT);
|
||||||
|
memset(audio_buffer_, 0, 720);
|
||||||
|
}
|
||||||
|
client_properties_.clear();
|
||||||
|
|
||||||
|
rejoin_ = false;
|
||||||
|
is_client_mode_ = false;
|
||||||
|
reload_recent_connections_ = true;
|
||||||
|
fullscreen_button_pressed_ = false;
|
||||||
|
just_created_ = false;
|
||||||
|
recent_connection_image_save_time_ = SDL_GetTicks();
|
||||||
|
} else {
|
||||||
|
LOG_INFO("Quit program");
|
||||||
|
exit_ = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||||
|
if (event.window.windowID != SDL_GetWindowID(stream_window_)) {
|
||||||
|
exit_ = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||||
|
if (stream_window_created_ &&
|
||||||
|
event.window.windowID == SDL_GetWindowID(stream_window_)) {
|
||||||
|
UpdateRenderRect();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||||
|
if (stream_window_ &&
|
||||||
|
SDL_GetWindowID(stream_window_) == event.window.windowID) {
|
||||||
|
foucs_on_stream_window_ = true;
|
||||||
|
} else if (main_window_ &&
|
||||||
|
SDL_GetWindowID(main_window_) == event.window.windowID) {
|
||||||
|
foucs_on_main_window_ = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||||
|
if (stream_window_ &&
|
||||||
|
SDL_GetWindowID(stream_window_) == event.window.windowID) {
|
||||||
|
foucs_on_stream_window_ = false;
|
||||||
|
} else if (main_window_ &&
|
||||||
|
SDL_GetWindowID(main_window_) == event.window.windowID) {
|
||||||
|
foucs_on_main_window_ = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
|
case SDL_EVENT_MOUSE_WHEEL:
|
||||||
|
if (foucs_on_stream_window_) {
|
||||||
|
ProcessMouseEvent(event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (event.type == STREAM_REFRESH_EVENT) {
|
||||||
|
auto* props = static_cast<SubStreamWindowProperties*>(event.user.data1);
|
||||||
|
if (!props) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (props->video_width_ <= 0 || props->video_height_ <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!props->dst_buffer_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use libyuv to convert NV12 to ARGB in order to fix SDL3 NV12 texture
|
||||||
|
// display issue
|
||||||
|
if (props->stream_texture_) {
|
||||||
|
if (props->video_width_ != props->texture_width_ ||
|
||||||
|
props->video_height_ != props->texture_height_) {
|
||||||
|
props->texture_width_ = props->video_width_;
|
||||||
|
props->texture_height_ = props->video_height_;
|
||||||
|
|
||||||
|
SDL_DestroyTexture(props->stream_texture_);
|
||||||
|
props->stream_texture_ = SDL_CreateTexture(
|
||||||
|
stream_renderer_, SDL_PIXELFORMAT_ARGB8888,
|
||||||
|
SDL_TEXTUREACCESS_STREAMING, props->texture_width_,
|
||||||
|
props->texture_height_);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("Quit program");
|
|
||||||
exit_ = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
|
||||||
if (event.window.windowID != SDL_GetWindowID(stream_window_)) {
|
|
||||||
exit_ = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
|
||||||
if (stream_window_created_ &&
|
|
||||||
event.window.windowID == SDL_GetWindowID(stream_window_)) {
|
|
||||||
UpdateRenderRect();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
|
||||||
if (stream_window_ &&
|
|
||||||
SDL_GetWindowID(stream_window_) == event.window.windowID) {
|
|
||||||
foucs_on_stream_window_ = true;
|
|
||||||
} else if (main_window_ &&
|
|
||||||
SDL_GetWindowID(main_window_) == event.window.windowID) {
|
|
||||||
foucs_on_main_window_ = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
|
||||||
if (stream_window_ &&
|
|
||||||
SDL_GetWindowID(stream_window_) == event.window.windowID) {
|
|
||||||
foucs_on_stream_window_ = false;
|
|
||||||
} else if (main_window_ &&
|
|
||||||
SDL_GetWindowID(main_window_) == event.window.windowID) {
|
|
||||||
foucs_on_main_window_ = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_EVENT_MOUSE_MOTION:
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
|
||||||
case SDL_EVENT_MOUSE_WHEEL:
|
|
||||||
if (foucs_on_stream_window_) {
|
|
||||||
ProcessMouseEvent(event);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.type == STREAM_REFRESH_EVENT) {
|
|
||||||
auto* props = static_cast<SubStreamWindowProperties*>(event.user.data1);
|
|
||||||
if (!props) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (props->video_width_ <= 0 || props->video_height_ <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!props->dst_buffer_) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use libyuv to convert NV12 to ARGB in order to fix SDL3 NV12 texture
|
|
||||||
// display issue
|
|
||||||
if (props->stream_texture_) {
|
|
||||||
if (props->video_width_ != props->texture_width_ ||
|
|
||||||
props->video_height_ != props->texture_height_) {
|
|
||||||
props->texture_width_ = props->video_width_;
|
props->texture_width_ = props->video_width_;
|
||||||
props->texture_height_ = props->video_height_;
|
props->texture_height_ = props->video_height_;
|
||||||
|
|
||||||
SDL_DestroyTexture(props->stream_texture_);
|
|
||||||
props->stream_texture_ =
|
props->stream_texture_ =
|
||||||
SDL_CreateTexture(stream_renderer_, SDL_PIXELFORMAT_ARGB8888,
|
SDL_CreateTexture(stream_renderer_, SDL_PIXELFORMAT_ARGB8888,
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
props->texture_width_, props->texture_height_);
|
props->texture_width_, props->texture_height_);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
props->texture_width_ = props->video_width_;
|
|
||||||
props->texture_height_ = props->video_height_;
|
|
||||||
props->stream_texture_ =
|
|
||||||
SDL_CreateTexture(stream_renderer_, SDL_PIXELFORMAT_ARGB8888,
|
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
|
||||||
props->texture_width_, props->texture_height_);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t argb_stride = props->texture_width_ * 4;
|
size_t argb_stride = props->texture_width_ * 4;
|
||||||
size_t argb_size = argb_stride * props->texture_height_;
|
size_t argb_size = argb_stride * props->texture_height_;
|
||||||
if (!props->argb_buffer_ || props->argb_buffer_size_ != argb_size) {
|
if (!props->argb_buffer_ || props->argb_buffer_size_ != argb_size) {
|
||||||
if (props->argb_buffer_) {
|
if (props->argb_buffer_) {
|
||||||
delete[] props->argb_buffer_;
|
delete[] props->argb_buffer_;
|
||||||
|
}
|
||||||
|
props->argb_buffer_ = new uint8_t[argb_size];
|
||||||
|
props->argb_buffer_size_ = argb_size;
|
||||||
}
|
}
|
||||||
props->argb_buffer_ = new uint8_t[argb_size];
|
|
||||||
props->argb_buffer_size_ = argb_size;
|
uint8_t* src_y = reinterpret_cast<uint8_t*>(props->dst_buffer_);
|
||||||
|
int src_stride_y = props->texture_width_;
|
||||||
|
uint8_t* src_uv = src_y + src_stride_y * props->texture_height_;
|
||||||
|
int src_stride_uv = props->texture_width_;
|
||||||
|
|
||||||
|
libyuv::NV12ToARGB(src_y, src_stride_y, src_uv, src_stride_uv,
|
||||||
|
props->argb_buffer_, static_cast<int>(argb_stride),
|
||||||
|
props->texture_width_, props->texture_height_);
|
||||||
|
|
||||||
|
SDL_UpdateTexture(props->stream_texture_, NULL, props->argb_buffer_,
|
||||||
|
static_cast<int>(argb_stride));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* src_y = reinterpret_cast<uint8_t*>(props->dst_buffer_);
|
|
||||||
int src_stride_y = props->texture_width_;
|
|
||||||
uint8_t* src_uv = src_y + src_stride_y * props->texture_height_;
|
|
||||||
int src_stride_uv = props->texture_width_;
|
|
||||||
|
|
||||||
libyuv::NV12ToARGB(src_y, src_stride_y, src_uv, src_stride_uv,
|
|
||||||
props->argb_buffer_, static_cast<int>(argb_stride),
|
|
||||||
props->texture_width_, props->texture_height_);
|
|
||||||
|
|
||||||
SDL_UpdateTexture(props->stream_texture_, NULL, props->argb_buffer_,
|
|
||||||
static_cast<int>(argb_stride));
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ class Render {
|
|||||||
void CleanSubStreamWindowProperties(
|
void CleanSubStreamWindowProperties(
|
||||||
std::shared_ptr<SubStreamWindowProperties> props);
|
std::shared_ptr<SubStreamWindowProperties> props);
|
||||||
void UpdateRenderRect();
|
void UpdateRenderRect();
|
||||||
void ProcessSdlEvent();
|
void ProcessSdlEvent(const SDL_Event &event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int CreateStreamRenderWindow();
|
int CreateStreamRenderWindow();
|
||||||
@@ -213,7 +213,7 @@ class Render {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
int SendKeyCommand(int key_code, bool is_down);
|
int SendKeyCommand(int key_code, bool is_down);
|
||||||
int ProcessMouseEvent(SDL_Event &event);
|
int ProcessMouseEvent(const SDL_Event &event);
|
||||||
|
|
||||||
static void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len);
|
static void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len);
|
||||||
static void SdlCaptureAudioOut(void *userdata, Uint8 *stream, int len);
|
static void SdlCaptureAudioOut(void *userdata, Uint8 *stream, int len);
|
||||||
@@ -290,6 +290,7 @@ class Render {
|
|||||||
SDL_Renderer *main_renderer_ = nullptr;
|
SDL_Renderer *main_renderer_ = nullptr;
|
||||||
ImGuiContext *main_ctx_ = nullptr;
|
ImGuiContext *main_ctx_ = nullptr;
|
||||||
bool exit_ = false;
|
bool exit_ = false;
|
||||||
|
const int sdl_refresh_ms_ = 16; // ~60 FPS
|
||||||
|
|
||||||
// main window properties
|
// main window properties
|
||||||
bool start_mouse_controller_ = false;
|
bool start_mouse_controller_ = false;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ int Render::SendKeyCommand(int key_code, bool is_down) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Render::ProcessMouseEvent(SDL_Event &event) {
|
int Render::ProcessMouseEvent(const SDL_Event &event) {
|
||||||
controlled_remote_id_ = "";
|
controlled_remote_id_ = "";
|
||||||
int video_width, video_height = 0;
|
int video_width, video_height = 0;
|
||||||
int render_width, render_height = 0;
|
int render_width, render_height = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user