diff --git a/src/device_controller/device_controller.h b/src/device_controller/device_controller.h index 3f1ae84..f690518 100644 --- a/src/device_controller/device_controller.h +++ b/src/device_controller/device_controller.h @@ -13,7 +13,8 @@ typedef enum { mouse = 0, keyboard, audio_capture, - host_infomation + host_infomation, + display_id, } ControlType; typedef enum { move = 0, @@ -51,6 +52,7 @@ typedef struct { Key k; HostInfo i; bool a; + int d; }; } RemoteAction; diff --git a/src/screen_capturer/screen_capturer.h b/src/screen_capturer/screen_capturer.h index 308e407..922ca40 100644 --- a/src/screen_capturer/screen_capturer.h +++ b/src/screen_capturer/screen_capturer.h @@ -32,8 +32,11 @@ class ScreenCapturer { virtual int Destroy() = 0; virtual int Start() = 0; virtual int Stop() = 0; + virtual int Pause(int monitor_index) = 0; + virtual int Resume(int monitor_index) = 0; virtual std::vector GetDisplayList() = 0; + virtual int SwitchTo(int monitor_index) = 0; }; #endif \ No newline at end of file diff --git a/src/screen_capturer/windows/screen_capturer_wgc.cpp b/src/screen_capturer/windows/screen_capturer_wgc.cpp index 8dc252a..6c8e57b 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.cpp +++ b/src/screen_capturer/windows/screen_capturer_wgc.cpp @@ -28,19 +28,25 @@ BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc, monitor_info_.cbSize = sizeof(MONITORINFOEX); if (GetMonitorInfo(hmonitor, &monitor_info_)) { - gs_display_list.push_back( - {(void *)hmonitor, WideToUtf8(monitor_info_.szDevice), - (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, - monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, - monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); + if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) { + gs_display_list.insert( + gs_display_list.begin(), + {(void *)hmonitor, WideToUtf8(monitor_info_.szDevice), + (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, + monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, + monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); + *(HMONITOR *)data = hmonitor; + } else { + gs_display_list.push_back( + {(void *)hmonitor, WideToUtf8(monitor_info_.szDevice), + (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, + monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, + monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); + } } if (monitor_info_.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true; - if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) { - *(HMONITOR *)data = hmonitor; - } - return true; } @@ -84,164 +90,160 @@ bool ScreenCapturerWgc::IsWgcSupported() { int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) { int error = 0; - if (_inited == true) return error; + if (inited_ == true) return error; // nv12_frame_ = new unsigned char[rect.right * rect.bottom * 3 / 2]; // nv12_frame_scaled_ = new unsigned char[1280 * 720 * 3 / 2]; - _fps = fps; + fps_ = fps; - _on_data = cb; + 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); - - monitor_ = GetPrimaryMonitor(); - - display_list_ = gs_display_list; - - for (const auto &display : display_list_) { - LOG_INFO("Display Name: {}, Is Primary: {}, Bounds: ({}, {}) - ({}, {})", - display.name, (display.is_primary ? "Yes" : "No"), display.left, - display.top, display.right, display.bottom); - } - - error = session_->Initialize(monitor_); - - _inited = true; - } while (0); - - if (error != 0) { + if (!IsWgcSupported()) { + LOG_ERROR("WGC not supported"); + error = 2; + return error; } - return error; + monitor_ = GetPrimaryMonitor(); + + display_list_ = gs_display_list; + + if (display_list_.empty()) { + LOG_ERROR("No display found"); + return -1; + } + + for (int i = 0; i < display_list_.size(); i++) { + const auto &display = display_list_[i]; + LOG_INFO( + "index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - " + "({}, {})", + i, display.name, (display.is_primary ? "yes" : "no"), display.left, + display.top, display.right, display.bottom); + + sessions_.push_back( + {std::make_unique(), false, false, false}); + sessions_.back().session_->RegisterObserver(this); + error = sessions_.back().session_->Initialize((HMONITOR)display.handle); + if (error != 0) { + return error; + } + sessions_[i].inited_ = true; + inited_ = true; + } + + LOG_INFO("Default on monitor {}:{}", monitor_index_, + display_list_[monitor_index_].name); + + return 0; } int ScreenCapturerWgc::Destroy() { return 0; } int ScreenCapturerWgc::Start() { - if (_running == true) { - std::cout << "record desktop duplication is already running" << std::endl; + if (running_ == true) { + LOG_ERROR("Screen capturer already running"); return 0; } - if (_inited == false) { - std::cout << "AE_NEED_INIT" << std::endl; + if (inited_ == false) { + LOG_ERROR("Screen capturer not inited"); return 4; } - _running = true; - session_->Start(); + for (int i = 0; i < sessions_.size(); i++) { + if (sessions_[i].inited_ == false) { + LOG_ERROR("Session {} not inited", i); + continue; + } + + if (sessions_[i].running_) { + LOG_ERROR("Session {} is already running", i); + } else { + sessions_[i].session_->Start(); + + if (i != 0) { + sessions_[i].session_->Pause(); + sessions_[i].paused_ = true; + } + sessions_[i].running_ = true; + } + running_ = true; + } return 0; } -int ScreenCapturerWgc::Pause() { - _paused = true; - if (session_) session_->Pause(); +int ScreenCapturerWgc::Pause(int monitor_index) { + if (monitor_index >= sessions_.size() || monitor_index < 0) { + LOG_ERROR("Invalid session index: {}", monitor_index); + return -1; + } + + if (!sessions_[monitor_index].paused_) { + sessions_[monitor_index].session_->Pause(); + sessions_[monitor_index].paused_ = true; + LOG_INFO("Pausing session {}", monitor_index); + } return 0; } -int ScreenCapturerWgc::Resume() { - _paused = false; - if (session_) session_->Resume(); +int ScreenCapturerWgc::Resume(int monitor_index) { + if (monitor_index >= sessions_.size() || monitor_index < 0) { + LOG_ERROR("Invalid session index: {}", monitor_index); + return -1; + } + + if (sessions_[monitor_index].paused_) { + sessions_[monitor_index].session_->Resume(); + sessions_[monitor_index].paused_ = false; + LOG_INFO("Resuming session {}", monitor_index); + } return 0; } int ScreenCapturerWgc::Stop() { - _running = false; - - if (session_) session_->Stop(); + for (int i = 0; i < sessions_.size(); i++) { + if (sessions_[i].running_) { + sessions_[i].session_->Stop(); + sessions_[i].running_ = false; + } + } return 0; } int ScreenCapturerWgc::SwitchTo(int monitor_index) { - if (!_inited) return -1; + if (monitor_index_ == monitor_index) { + LOG_INFO("Already on monitor {}:{}", monitor_index_, + display_list_[monitor_index_].name); + return 0; + } + if (monitor_index >= display_list_.size()) { LOG_ERROR("Invalid monitor index: {}", monitor_index); - return -3; + return -1; } - LOG_INFO("Switching to monitor {}:{}", monitor_index, - display_list_[monitor_index].name); - - Stop(); - - if (session_) { - session_->Release(); - delete session_; - session_ = nullptr; + if (!sessions_[monitor_index].inited_) { + LOG_ERROR("Monitor {} not inited", monitor_index); + return -1; } - session_ = new WgcSessionImpl(); - if (!session_) { - LOG_ERROR("Failed to create new WgcSessionImpl."); - return -4; - } + Pause(monitor_index_); - session_->RegisterObserver(this); + monitor_index_ = monitor_index; + LOG_INFO("Switching to monitor {}:{}", monitor_index_, + display_list_[monitor_index_].name); - int err = session_->Initialize((HMONITOR)display_list_[monitor_index].handle); - if (err != 0) { - LOG_ERROR("Failed to re-initialize session on new monitor."); - return -5; - } + Resume(monitor_index); - monitor_ = (HMONITOR)display_list_[monitor_index].handle; - _inited = true; - - return Start(); -} - -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) { - int abgr_index = (i * abgr_stride + j) * 4; - int bgra_index = (i * bgra_stride + j) * 4; - - bgra_data[bgra_index + 0] = abgr_data[abgr_index + 2]; // 蓝色 - bgra_data[bgra_index + 1] = abgr_data[abgr_index + 1]; // 绿色 - bgra_data[bgra_index + 2] = abgr_data[abgr_index + 0]; // 红色 - 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) { - int bgra_index = (i * bgra_stride + j) * 4; - int abgr_index = (i * abgr_stride + j) * 4; - - 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 - } - } + return 0; } void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame) { - if (_on_data) { - // int width = 1280; - // int height = 720; - + if (on_data_) { if (!nv12_frame_) { nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2]; } @@ -251,15 +253,20 @@ void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame) { (uint8_t *)(nv12_frame_ + frame.width * frame.height), frame.width, frame.width, frame.height); - _on_data(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width, + on_data_(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width, frame.height); } } void ScreenCapturerWgc::CleanUp() { - _inited = false; - - if (session_) session_->Release(); - - session_ = nullptr; + if (inited_) { + for (auto &session : sessions_) { + if (session.session_) { + session.session_->Stop(); + session.session_->Release(); + session.session_ = nullptr; + } + } + sessions_.clear(); + } } diff --git a/src/screen_capturer/windows/screen_capturer_wgc.h b/src/screen_capturer/windows/screen_capturer_wgc.h index 087ad47..c434679 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.h +++ b/src/screen_capturer/windows/screen_capturer_wgc.h @@ -25,8 +25,8 @@ class ScreenCapturerWgc : public ScreenCapturer, virtual int Start() override; virtual int Stop() override; - int Pause(); - int Resume(); + virtual int Pause(int monitor_index) override; + virtual int Resume(int monitor_index) override; std::vector GetDisplayList() { return display_list_; } @@ -41,21 +41,25 @@ class ScreenCapturerWgc : public ScreenCapturer, HMONITOR monitor_; MONITORINFOEX monitor_info_; std::vector display_list_; + int monitor_index_ = 0; private: - WgcSession *session_ = nullptr; + class WgcSessionInfo { + public: + std::unique_ptr session_; + bool inited_ = false; + bool running_ = false; + bool paused_ = false; + }; - std::atomic_bool _running; - std::atomic_bool _paused; - std::atomic_bool _inited; + std::vector sessions_; - std::thread _thread; + std::atomic_bool running_; + std::atomic_bool inited_; - std::string _device_name; + int fps_; - int _fps; - - cb_desktop_data _on_data = nullptr; + cb_desktop_data on_data_ = nullptr; unsigned char *nv12_frame_ = nullptr; unsigned char *nv12_frame_scaled_ = nullptr; diff --git a/src/screen_capturer/windows/wgc_session_impl.cpp b/src/screen_capturer/windows/wgc_session_impl.cpp index 29663ce..3a5c9ee 100644 --- a/src/screen_capturer/windows/wgc_session_impl.cpp +++ b/src/screen_capturer/windows/wgc_session_impl.cpp @@ -124,6 +124,8 @@ int WgcSessionImpl::Stop() { int WgcSessionImpl::Pause() { std::lock_guard locker(lock_); + is_paused_ = true; + CHECK_INIT; return 0; } @@ -131,6 +133,8 @@ int WgcSessionImpl::Pause() { int WgcSessionImpl::Resume() { std::lock_guard locker(lock_); + is_paused_ = false; + CHECK_INIT; return 0; } @@ -233,6 +237,10 @@ void WgcSessionImpl::OnFrame( // copy to mapped texture { + if (is_paused_) { + return; + } + auto frame_captured = GetDXGIInterfaceFromObject(frame.Surface()); diff --git a/src/single_window/control_bar.cpp b/src/single_window/control_bar.cpp index 8a5dd25..d9ffe77 100644 --- a/src/single_window/control_bar.cpp +++ b/src/single_window/control_bar.cpp @@ -65,6 +65,14 @@ int Render::ControlBar(std::shared_ptr& props) { for (int i = 0; i < display_list.size(); i++) { if (ImGui::Selectable(display_list[i].name.c_str())) { selected_display_ = i + 1; + + RemoteAction remote_action; + remote_action.type = ControlType::display_id; + remote_action.d = i; + if (props->connection_status_ == ConnectionStatus::Connected) { + SendDataFrame(props->peer_, (const char*)&remote_action, + sizeof(remote_action)); + } } } ImGui::SetWindowFontScale(1.0f); @@ -118,7 +126,8 @@ int Render::ControlBar(std::shared_ptr& props) { float disable_audio_x = ImGui::GetCursorScreenPos().x + 4; float disable_audio_y = ImGui::GetCursorScreenPos().y + 4.0f; // std::string audio = audio_capture_button_pressed_ ? ICON_FA_VOLUME_HIGH - // : ICON_FA_VOLUME_XMARK; + // : + // ICON_FA_VOLUME_XMARK; std::string audio = props->audio_capture_button_pressed_ ? ICON_FA_VOLUME_HIGH : ICON_FA_VOLUME_HIGH; diff --git a/src/single_window/render.h b/src/single_window/render.h index 45ca681..6387d2d 100644 --- a/src/single_window/render.h +++ b/src/single_window/render.h @@ -79,6 +79,8 @@ class Render { int texture_height_ = 720; int video_width_ = 0; int video_height_ = 0; + int video_width_last_ = 0; + int video_height_last_ = 0; size_t video_size_ = 0; bool tab_selected_ = false; bool tab_opened_ = true; diff --git a/src/single_window/render_callback_func.cpp b/src/single_window/render_callback_func.cpp index 62584f8..c54b9a1 100644 --- a/src/single_window/render_callback_func.cpp +++ b/src/single_window/render_callback_func.cpp @@ -215,8 +215,11 @@ void Render::OnReceiveVideoBufferCb(const XVideoFrame *video_frame, memcpy(props->dst_buffer_, video_frame->data, video_frame->size); bool need_to_update_render_rect = false; - if (props->video_width_ == 0 && props->video_height_ == 0) { + if (props->video_width_ != props->video_width_last_ || + props->video_height_ != props->video_height_last_) { need_to_update_render_rect = true; + props->video_width_last_ = props->video_width_; + props->video_height_last_ = props->video_height_; } props->video_width_ = video_frame->width; props->video_height_ = video_frame->height; @@ -261,6 +264,7 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size, std::string remote_id(user_id, user_id_size); if (render->client_properties_.find(remote_id) != render->client_properties_.end()) { + // local auto props = render->client_properties_.find(remote_id)->second; if (ControlType::host_infomation == remote_action.type) { props->remote_host_name_ = std::string(remote_action.i.host_name, @@ -268,6 +272,7 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size, LOG_INFO("Remote hostname: [{}]", props->remote_host_name_); } } else { + // remote if (ControlType::mouse == remote_action.type && render->mouse_controller_) { render->mouse_controller_->SendMouseCommand(remote_action); } else if (ControlType::audio_capture == remote_action.type) { @@ -283,6 +288,10 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size, render->keyboard_capturer_->SendKeyboardCommand( (int)remote_action.k.key_value, remote_action.k.flag == KeyFlag::key_down); + } else if (ControlType::display_id == remote_action.type) { + if (render->screen_capturer_) { + render->screen_capturer_->SwitchTo(remote_action.d); + } } } } diff --git a/src/single_window/stream_window.cpp b/src/single_window/stream_window.cpp index c54e32e..1a828b5 100644 --- a/src/single_window/stream_window.cpp +++ b/src/single_window/stream_window.cpp @@ -79,6 +79,7 @@ int Render::StreamWindow() { props->render_window_y_ = pos.y; props->render_window_width_ = size.x; props->render_window_height_ = size.y; + UpdateRenderRect(); ControlWindow(props); @@ -139,6 +140,7 @@ int Render::StreamWindow() { props->render_window_y_ = pos.y; props->render_window_width_ = size.x; props->render_window_height_ = size.y; + UpdateRenderRect(); ControlWindow(props); ImGui::End(); @@ -161,7 +163,7 @@ int Render::StreamWindow() { } } - UpdateRenderRect(); + // UpdateRenderRect(); ImGui::End(); // End VideoBg return 0; diff --git a/thirdparty/projectx b/thirdparty/projectx index 881cecc..5aa61bf 160000 --- a/thirdparty/projectx +++ b/thirdparty/projectx @@ -1 +1 @@ -Subproject commit 881cecc3f9d5d0f5f7a9bba47b8b5e0560ac6b77 +Subproject commit 5aa61bf7359873cf5c6cae4603f357974023c0a6