[feat] use client_properties_ and server_properties_ to store streams properties

This commit is contained in:
dijunkun
2024-12-03 17:22:15 +08:00
parent 011919d0e7
commit 1a0c5e8b42
13 changed files with 546 additions and 439 deletions

View File

@@ -15,12 +15,12 @@
#include "rd_log.h"
#include "screen_capturer_factory.h"
// Refresh Event
#define REFRESH_EVENT (SDL_USEREVENT + 1)
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
#define MOUSE_GRAB_PADDING 5
const Uint32 STREAM_FRASH = SDL_RegisterEvents(29);
SDL_HitTestResult Render::HitTestCallback(SDL_Window* window,
const SDL_Point* area, void* data) {
Render* render = (Render*)data;
@@ -40,9 +40,9 @@ SDL_HitTestResult Render::HitTestCallback(SDL_Window* window,
return SDL_HITTEST_DRAGGABLE;
}
if (!render->streaming_) {
return SDL_HITTEST_NORMAL;
}
// if (!render->streaming_) {
// return SDL_HITTEST_NORMAL;
// }
if (area->y < MOUSE_GRAB_PADDING) {
if (area->x < MOUSE_GRAB_PADDING) {
@@ -69,7 +69,7 @@ SDL_HitTestResult Render::HitTestCallback(SDL_Window* window,
return SDL_HITTEST_NORMAL;
}
Render::Render() { memset(&net_traffic_stats_, 0, sizeof(net_traffic_stats_)); }
Render::Render() {}
Render::~Render() {}
@@ -198,7 +198,7 @@ int Render::StartScreenCapturer() {
std::chrono::steady_clock::now().time_since_epoch())
.count();
auto duration = now_time - last_frame_time_;
if (duration >= 0 && connection_established_) {
if (duration >= 0) {
XVideoFrame frame;
frame.data = (const char*)data;
frame.size = size;
@@ -238,9 +238,7 @@ int Render::StartSpeakerCapturer() {
speaker_capturer_ = (SpeakerCapturer*)speaker_capturer_factory_->Create();
int speaker_capturer_init_ret = speaker_capturer_->Init(
[this](unsigned char* data, size_t size) -> void {
if (connection_established_) {
SendAudioFrame(peer_, (const char*)data, size);
}
SendAudioFrame(peer_, (const char*)data, size);
});
if (0 != speaker_capturer_init_ret) {
@@ -518,16 +516,16 @@ int Render::CreateStreamWindow() {
}
stream_pixformat_ = SDL_PIXELFORMAT_NV12;
stream_texture_ = SDL_CreateTexture(stream_renderer_, stream_pixformat_,
SDL_TEXTUREACCESS_STREAMING,
texture_width_, texture_height_);
// stream_texture_ = SDL_CreateTexture(stream_renderer_, stream_pixformat_,
// SDL_TEXTUREACCESS_STREAMING,
// texture_width_, texture_height_);
SDL_SetWindowResizable(stream_window_, SDL_TRUE);
// for window region action
SDL_SetWindowHitTest(stream_window_, HitTestCallback, this);
// change stream_render_rect_
// change props->stream_render_rect_
SDL_Event event;
event.type = SDL_WINDOWEVENT;
event.window.windowID = SDL_GetWindowID(stream_window_);
@@ -733,7 +731,12 @@ int Render::DrawStreamWindow() {
// Rendering
ImGui::Render();
SDL_RenderClear(stream_renderer_);
SDL_RenderCopy(stream_renderer_, stream_texture_, NULL, &stream_render_rect_);
for (auto& it : client_properties_) {
auto props = it.second;
SDL_RenderCopy(stream_renderer_, props->stream_texture_, NULL,
&(props->stream_render_rect_));
}
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), stream_renderer_);
SDL_RenderPresent(stream_renderer_);
@@ -766,11 +769,6 @@ int Render::Run() {
screen_width_ = DM.w;
screen_height_ = DM.h;
stream_render_rect_.x = 0;
stream_render_rect_.y = (int)title_bar_height_;
stream_render_rect_.w = (int)stream_window_width_;
stream_render_rect_.h = (int)(stream_window_height_ - title_bar_height_);
// use linear filtering to render textures otherwise the graphics will be
// blurry
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
@@ -842,40 +840,47 @@ int Render::Run() {
ImGui_ImplSDL2_ProcessEvent(&event);
}
if (event.type == SDL_QUIT) {
if (streaming_) {
if (stream_window_inited_) {
LOG_INFO("Destroy stream window");
SDL_SetWindowGrab(stream_window_, SDL_FALSE);
DestroyStreamWindow();
DestroyStreamWindowContext();
if (dst_buffer_) {
thumbnail_->SaveToThumbnail(
(char*)dst_buffer_, video_width_, video_height_, remote_id_,
remote_host_name_, remember_password_ ? remote_password_ : "");
recent_connection_image_save_time_ = SDL_GetTicks();
}
for (auto& it : client_properties_) {
auto props = it.second;
if (props->dst_buffer_) {
thumbnail_->SaveToThumbnail(
(char*)props->dst_buffer_, props->video_width_,
props->video_height_, it.first, props->remote_host_name_,
props->remember_password_ ? props->remote_password_ : "");
}
LOG_INFO("[{}] Leave connection [{}]", client_id_, remote_id_);
LeaveConnection(peer_reserved_ ? peer_reserved_ : peer_,
remote_id_.c_str());
if (peer_reserved_) {
LOG_INFO("Destroy peer[reserved]");
DestroyPeer(&peer_reserved_);
}
LOG_INFO("[{}] Leave connection [{}]", client_id_, it.first);
LeaveConnection(peer_reserved_ ? peer_reserved_ : peer_,
it.first.c_str());
if (peer_reserved_) {
LOG_INFO("Destroy peer[reserved]");
DestroyPeer(&peer_reserved_);
}
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_, SDL_FALSE);
SDL_DestroyTexture(props->stream_texture_);
memset(audio_buffer_, 0, 720);
}
client_properties_.clear();
streaming_ = false;
rejoin_ = false;
connection_established_ = false;
is_client_mode_ = false;
audio_capture_button_pressed_ = false;
fullscreen_button_pressed_ = false;
reload_recent_connections_ = true;
remember_password_ = false;
memset(&net_traffic_stats_, 0, sizeof(net_traffic_stats_));
SDL_SetWindowFullscreen(main_window_, SDL_FALSE);
memset(audio_buffer_, 0, 720);
fullscreen_button_pressed_ = false;
recent_connection_image_save_time_ = SDL_GetTicks();
continue;
} else {
LOG_INFO("Quit program");
@@ -888,73 +893,101 @@ int Render::Run() {
} else if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED &&
stream_window_created_ &&
event.window.windowID == SDL_GetWindowID(stream_window_)) {
// to prevent cursor relocation
if (!reset_control_bar_pos_) {
mouse_diff_control_bar_pos_x_ = 0;
mouse_diff_control_bar_pos_y_ = 0;
}
for (auto& it : client_properties_) {
auto props = it.second;
reset_control_bar_pos_ = true;
int stream_window_width, stream_window_height;
SDL_GetWindowSize(stream_window_, &stream_window_width,
&stream_window_height);
stream_window_width_ = (float)stream_window_width;
stream_window_height_ = (float)stream_window_height;
// to prevent cursor relocation
if (!props->reset_control_bar_pos_) {
props->mouse_diff_control_bar_pos_x_ = 0;
props->mouse_diff_control_bar_pos_y_ = 0;
}
float video_ratio = (float)video_width_ / (float)video_height_;
float video_ratio_reverse = (float)video_height_ / (float)video_width_;
props->reset_control_bar_pos_ = true;
int stream_window_width, stream_window_height;
SDL_GetWindowSize(stream_window_, &stream_window_width,
&stream_window_height);
stream_window_width_ = (float)stream_window_width;
stream_window_height_ = (float)stream_window_height;
float render_area_width = stream_window_width_;
float render_area_height =
stream_window_height_ -
(fullscreen_button_pressed_ ? 0 : title_bar_height_);
float video_ratio =
(float)props->video_width_ / (float)props->video_height_;
float video_ratio_reverse =
(float)props->video_height_ / (float)props->video_width_;
stream_render_rect_last_ = stream_render_rect_;
if (render_area_width < render_area_height * video_ratio) {
stream_render_rect_.x = 0;
stream_render_rect_.y =
(int)(abs(render_area_height -
render_area_width * video_ratio_reverse) /
2 +
(fullscreen_button_pressed_ ? 0 : title_bar_height_));
stream_render_rect_.w = (int)render_area_width;
stream_render_rect_.h =
(int)(render_area_width * video_ratio_reverse);
} else if (render_area_width > render_area_height * video_ratio) {
stream_render_rect_.x =
(int)abs(render_area_width - render_area_height * video_ratio) /
2;
stream_render_rect_.y =
fullscreen_button_pressed_ ? 0 : (int)title_bar_height_;
stream_render_rect_.w = (int)(render_area_height * video_ratio);
stream_render_rect_.h = (int)render_area_height;
} else {
stream_render_rect_.x = 0;
stream_render_rect_.y =
fullscreen_button_pressed_ ? 0 : (int)title_bar_height_;
stream_render_rect_.w = (int)render_area_width;
stream_render_rect_.h = (int)render_area_height;
float render_area_width = stream_window_width_;
float render_area_height =
stream_window_height_ -
(fullscreen_button_pressed_ ? 0 : title_bar_height_);
props->stream_render_rect_last_ = props->stream_render_rect_;
if (render_area_width < render_area_height * video_ratio) {
props->stream_render_rect_.x = 0;
props->stream_render_rect_.y =
(int)(abs(render_area_height -
render_area_width * video_ratio_reverse) /
2 +
(fullscreen_button_pressed_ ? 0 : title_bar_height_));
props->stream_render_rect_.w = (int)render_area_width;
props->stream_render_rect_.h =
(int)(render_area_width * video_ratio_reverse);
} else if (render_area_width > render_area_height * video_ratio) {
props->stream_render_rect_.x =
(int)abs(render_area_width - render_area_height * video_ratio) /
2;
props->stream_render_rect_.y =
fullscreen_button_pressed_ ? 0 : (int)title_bar_height_;
props->stream_render_rect_.w =
(int)(render_area_height * video_ratio);
props->stream_render_rect_.h = (int)render_area_height;
} else {
props->stream_render_rect_.x = 0;
props->stream_render_rect_.y =
fullscreen_button_pressed_ ? 0 : (int)title_bar_height_;
props->stream_render_rect_.w = (int)render_area_width;
props->stream_render_rect_.h = (int)render_area_height;
}
}
} else if (event.type == SDL_WINDOWEVENT &&
event.window.event == SDL_WINDOWEVENT_CLOSE) {
if (connection_established_) {
if (event.window.windowID == SDL_GetWindowID(stream_window_)) {
continue;
} else {
exit_ = true;
}
} else if (event.type == REFRESH_EVENT) {
if (stream_texture_)
if (video_width_ != texture_width_ ||
video_height_ != texture_height_) {
texture_width_ = video_width_;
texture_height_ = video_height_;
} else if (event.type == STREAM_FRASH) {
SubStreamWindowProperties* props =
static_cast<SubStreamWindowProperties*>(event.user.data1);
if (!props) {
LOG_ERROR("Invalid stream window properties");
continue;
}
SDL_DestroyTexture(stream_texture_);
stream_texture_ = SDL_CreateTexture(
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_, stream_pixformat_,
SDL_TEXTUREACCESS_STREAMING, texture_width_, texture_height_);
SDL_TEXTUREACCESS_STREAMING, props->texture_width_,
props->texture_height_);
}
SDL_UpdateTexture(stream_texture_, NULL, dst_buffer_, texture_width_);
} else {
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_;
}
props->stream_texture_ = SDL_CreateTexture(
stream_renderer_, stream_pixformat_, SDL_TEXTUREACCESS_STREAMING,
props->texture_width_, props->texture_height_);
}
SDL_UpdateTexture(props->stream_texture_, NULL, props->dst_buffer_,
props->texture_width_);
}
}
@@ -965,6 +998,7 @@ int Render::Run() {
int ret = thumbnail_->LoadThumbnail(
main_renderer_, recent_connection_textures_,
&recent_connection_image_width_, &recent_connection_image_height_);
LOG_INFO("1 Load recent connection thumbnails");
if (!ret) {
LOG_INFO("Load recent connection thumbnails");
}
@@ -972,10 +1006,13 @@ int Render::Run() {
}
}
if (connection_established_ && streaming_) {
if (need_to_create_stream_window_) {
CreateStreamWindow();
SetupStreamWindow();
need_to_create_stream_window_ = false;
}
if (stream_window_inited_) {
if (!stream_window_grabbed_ && control_mouse_) {
SDL_SetWindowGrab(stream_window_, SDL_TRUE);
stream_window_grabbed_ = true;