From 035f15cb037253e78a4b8985b5665d354af6ece5 Mon Sep 17 00:00:00 2001 From: Zhennan Tu Date: Mon, 25 Mar 2024 09:01:18 +0800 Subject: [PATCH] Support 'Max bitreate' setting --- app/i18n/lt-zh_CN.ts | 97 +++++++++++-------- app/src/app.cpp | 8 ++ app/src/app.h | 2 + app/src/views/gui.h | 2 + app/src/views/mainwindow/mainwindow.cpp | 31 ++++++ app/src/views/mainwindow/mainwindow.ui | 53 +++++++++- .../video_capture_encode_pipeline.cpp | 7 ++ .../video_capture_encode_pipeline.h | 1 + lanthing/src/worker/worker_streaming.cpp | 12 +++ lanthing/src/worker/worker_streaming.h | 2 + 10 files changed, 168 insertions(+), 47 deletions(-) diff --git a/app/i18n/lt-zh_CN.ts b/app/i18n/lt-zh_CN.ts index d8c89103..beab8876 100644 --- a/app/i18n/lt-zh_CN.ts +++ b/app/i18n/lt-zh_CN.ts @@ -43,78 +43,78 @@ 连接已断开 - + New Connection 连接请求 - + Device %s is requesting connection 设备 %s 正在请求连接 - + Accept 同意 - + Accept, as well as next time 同意,下次不再提醒 - + Reject 拒绝 - + The new version %s has been released, please download it<br>from <a href='%s'>Github</a>. 新版本%s已经发布,请到<a href='%s'>Github</a>或QQ群89746161下载。 - + Version: 版本: - + Released date: 发布日期: - + New features: 新特性: - + Bug fix: 修复: - - + + New Version 新版本 - + The new version %s has been released, this is a force update version, please download it from <a href='%s'>Github</a>. 新版本%s已经发布,该版本与旧版不兼容,请到<a href='%s'>Github</a>或QQ群89746161下载。 - + 🟢Connected to server 🟢已连接服务器 - + 🔴Disconnected from server 🔴与服务器断开 - + 🟢Controlled module up 🟢被控模块正常 @@ -123,49 +123,49 @@ 🟡正在启动被控模块 - + 🔴Controlled module down 🔴被控模块掉线 - + gamepad 手柄 - + keyboard 键盘 - + mouse 鼠标 - + audio 声音 - + kick 断开 - + DeviceID or AccessToken invalid 设备码或验证码错误 - + delete 删除 - + Lanthing @@ -271,8 +271,9 @@ - - + + + Confirm 确认 @@ -281,7 +282,7 @@ 鼠标模式(暂不生效) - + 🟡Connecting... 🟡正在连接服务器 @@ -370,24 +371,34 @@ - + + Max Mbps + 最大码率Mbps + + + + 1-100 + + + + Misc 杂项 - + Status Color 状态颜色 - - - + + + 0-255 - + Mouse Accel 鼠标加速 @@ -396,47 +407,47 @@ 鼠标加速 - + 0.1-3.0 - + Shotcut key 快捷键 - + Switch Fullscreen 切换全屏 - + Win+Shift+Z - + Mouse mode 鼠标模式 - + Win+Shift+X - + <html><head/><body><p>Lanthing is a remote control tool created by <a href="https://github.com/pjlt"><span style=" text-decoration: underline; color:#007af4;">Project Lanthing</span></a>.</p></body></html> - + License - + <html><head/><body><p>Lanthing release under <a href="https://github.com/pjlt/lanthing-pc/blob/master/LICENSE"><span style=" text-decoration: underline; color:#007af4;">BSD-3-Clause license</span></a>.</p><p>Thirdparty software licenses are listed in</p><p><a href="https://github.com/pjlt/lanthing-pc/blob/master/third-party-licenses.txt"><span style=" text-decoration: underline; color:#007af4;">https://github.com/pjlt/lanthing-pc/blob/master/third-party-licenses.txt</span></a></p></body></html> diff --git a/app/src/app.cpp b/app/src/app.cpp index a9fd9039..7b7e1a70 100644 --- a/app/src/app.cpp +++ b/app/src/app.cpp @@ -115,6 +115,7 @@ bool App::init() { ignored_nic_ = settings_->getString("ignored_nic").value_or(""); enable_444_ = settings_->getBoolean("enable_444").value_or(false); enable_tcp_ = settings_->getBoolean("enable_tcp").value_or(false); + max_mbps_ = static_cast(settings_->getInteger("max_mbps").value_or(0)); std::optional access_token = settings_->getString("access_token"); if (access_token.has_value()) { @@ -185,6 +186,7 @@ int App::exec(int argc, char** argv) { params.set_ignored_nic = std::bind(&App::setIgnoredNIC, this, std::placeholders::_1); params.enable_tcp = std::bind(&App::enableTCP, this, std::placeholders::_1); params.on_clipboard_text = std::bind(&App::syncClipboardText, this, std::placeholders::_1); + params.set_max_mbps = std::bind(&App::setMaxMbps, this, std::placeholders::_1); gui_.init(params, argc, argv); thread_ = ltlib::BlockingThread::create( @@ -240,6 +242,7 @@ GUI::Settings App::getSettings() const { settings.rel_mouse_accel = rel_mouse_accel_; settings.ignored_nic = ignored_nic_; settings.tcp = enable_tcp_; + settings.max_mbps = max_mbps_; return settings; } @@ -392,6 +395,11 @@ void App::syncClipboardText(const std::string& text) { }); } +void App::setMaxMbps(uint32_t mbps) { + max_mbps_ = mbps; + settings_->setInteger("max_mbps", mbps); +} + void App::ioLoop(const std::function& i_am_alive) { LOG(INFO) << "App enter io loop"; ioloop_->run(i_am_alive); diff --git a/app/src/app.h b/app/src/app.h index 0055e6b4..b35c8931 100644 --- a/app/src/app.h +++ b/app/src/app.h @@ -83,6 +83,7 @@ class App { void setIgnoredNIC(const std::string& nic_list); void enableTCP(bool enable); void syncClipboardText(const std::string& text); + void setMaxMbps(uint32_t mbps); void createAndStartService(); void stopService(); @@ -153,6 +154,7 @@ class App { std::string ignored_nic_; bool enable_444_ = false; bool enable_tcp_ = false; + uint32_t max_mbps_ = 0; std::optional windowed_fullscreen_; std::string relay_server_; std::mt19937 rand_engine_; diff --git a/app/src/views/gui.h b/app/src/views/gui.h index 770c4bf0..48967503 100644 --- a/app/src/views/gui.h +++ b/app/src/views/gui.h @@ -71,6 +71,7 @@ class GUI { std::optional status_color; uint8_t rel_mouse_accel; std::string ignored_nic; + uint32_t max_mbps; }; struct TrustedDevice { @@ -101,6 +102,7 @@ class GUI { std::function set_ignored_nic; std::function enable_tcp; std::function on_clipboard_text; + std::function set_max_mbps; }; public: diff --git a/app/src/views/mainwindow/mainwindow.cpp b/app/src/views/mainwindow/mainwindow.cpp index 7f235cf3..1006be7d 100644 --- a/app/src/views/mainwindow/mainwindow.cpp +++ b/app/src/views/mainwindow/mainwindow.cpp @@ -178,6 +178,11 @@ MainWindow::MainWindow(const lt::GUI::Params& params, QWidget* parent) if (!settings.ignored_nic.empty()) { ui->leditIgnoredNIC->setText(QString::fromStdString(settings.ignored_nic)); } + ui->btnMaxMbps->setEnabled(false); + ui->leditMaxMbps->setValidator(new QIntValidator(1, 100, this)); + if (settings.max_mbps != 0) { + ui->leditMaxMbps->setText(QString::number(settings.max_mbps)); + } ui->btnStatusColor->setEnabled(false); ui->leditRed->setValidator(new QIntValidator(0, 255, this)); ui->leditGreen->setValidator(new QIntValidator(0, 255, this)); @@ -622,6 +627,32 @@ void MainWindow::setupOtherCallbacks() { ui->btnPortRange->setEnabled(false); } }); + connect(ui->leditMaxMbps, &QLineEdit::textChanged, [this](const QString& _text) { + if (_text.trimmed().isEmpty()) { + ui->btnMaxMbps->setEnabled(true); + return; + } + int mbps = _text.trimmed().toInt(); + if (mbps >= 1 && mbps <= 100) { + ui->btnMaxMbps->setEnabled(true); + } + else { + ui->btnMaxMbps->setEnabled(false); + } + }); + connect(ui->btnMaxMbps, &QPushButton::clicked, [this]() { + if (ui->leditMaxMbps->text().trimmed().isEmpty()) { + params_.set_max_mbps(0); + ui->btnMaxMbps->setEnabled(false); + } + else { + int mbps = ui->leditMaxMbps->text().trimmed().toInt(); + if (mbps >= 1 && mbps <= 100) { + params_.set_max_mbps(static_cast(mbps)); + ui->btnMaxMbps->setEnabled(false); + } + } + }); connect(ui->leditIgnoredNIC, &QLineEdit::textChanged, [this](const QString&) { ui->btnIgnoredNIC->setEnabled(true); }); connect(ui->btnIgnoredNIC, &QPushButton::clicked, [this]() { diff --git a/app/src/views/mainwindow/mainwindow.ui b/app/src/views/mainwindow/mainwindow.ui index 41fa0bd2..bae2b8c7 100644 --- a/app/src/views/mainwindow/mainwindow.ui +++ b/app/src/views/mainwindow/mainwindow.ui @@ -1613,18 +1613,18 @@ QHeaderView::section:vertical 0 - 0 + -275 527 - 650 + 700 0 - 650 + 700 - + QLayout::SetDefaultConstraint @@ -1917,6 +1917,51 @@ QHeaderView::section:vertical + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 90 + 0 + + + + + 90 + 16777215 + + + + Max Mbps + + + + + + + 1-100 + + + + + + + Confirm + + + + + + diff --git a/lanthing/src/video/cepipeline/video_capture_encode_pipeline.cpp b/lanthing/src/video/cepipeline/video_capture_encode_pipeline.cpp index 85b45d08..22debc2f 100644 --- a/lanthing/src/video/cepipeline/video_capture_encode_pipeline.cpp +++ b/lanthing/src/video/cepipeline/video_capture_encode_pipeline.cpp @@ -140,6 +140,7 @@ class VCEPipeline : public CaptureEncodePipeline { uint32_t client_refresh_rate_; uint32_t max_fps_; uint32_t target_fps_; + uint32_t max_bps_; ltlib::Monitor monitor_; std::function register_message_handler_; std::function&)> @@ -167,6 +168,8 @@ VCEPipeline::VCEPipeline(const CaptureEncodePipeline::Params& params) , client_refresh_rate_{params.client_refresh_rate} , max_fps_{params.client_refresh_rate} , target_fps_{params.client_refresh_rate} + , max_bps_{(params.max_mbps == 0 || params.max_mbps > 100) ? (100 * 1024 * 1024) + : (params.max_mbps * 1024 * 1024)} , monitor_{params.monitor} , register_message_handler_{params.register_message_handler} , send_message_{params.send_message} @@ -204,6 +207,7 @@ bool VCEPipeline::init() { Encoder::InitParams encode_params{}; encode_params.freq = max_fps_; encode_params.bitrate_bps = 4 * 1024 * 1024; + encode_params.bitrate_bps = std::min(encode_params.bitrate_bps, max_bps_); if (monitor_.rotation == 90 || monitor_.rotation == 270) { encode_params.width = height_; encode_params.height = width_; @@ -508,6 +512,9 @@ void VCEPipeline::onReconfigure(std::shared_ptr _ if (msg->has_bitrate_bps()) { LOG(DEBUG) << "Set bitrate " << msg->bitrate_bps(); params.bitrate_bps = msg->bitrate_bps(); + if (!manual_bitrate_) { + params.bitrate_bps = std::min(params.bitrate_bps.value(), max_bps_); + } changed = true; } if (msg->has_fps()) { diff --git a/lanthing/src/video/cepipeline/video_capture_encode_pipeline.h b/lanthing/src/video/cepipeline/video_capture_encode_pipeline.h index 781a7565..cd67b3ed 100644 --- a/lanthing/src/video/cepipeline/video_capture_encode_pipeline.h +++ b/lanthing/src/video/cepipeline/video_capture_encode_pipeline.h @@ -49,6 +49,7 @@ class CaptureEncodePipeline { uint32_t width; uint32_t height; uint32_t client_refresh_rate; + uint32_t max_mbps; ltlib::Monitor monitor; std::function register_message_handler; std::function&)> diff --git a/lanthing/src/worker/worker_streaming.cpp b/lanthing/src/worker/worker_streaming.cpp index f8234e97..70e69603 100644 --- a/lanthing/src/worker/worker_streaming.cpp +++ b/lanthing/src/worker/worker_streaming.cpp @@ -213,6 +213,7 @@ int32_t WorkerStreaming::init() { LOG(ERR) << "Init pipe client failed"; return kExitCodeInitWorkerFailed; } + getUserMaxMbps(); #if 0 // 引入多屏支持后,协商变得很麻烦 if (need_negotiate_) { if (!negotiateAllParameters()) { @@ -375,6 +376,7 @@ int32_t WorkerStreaming::negotiateStreamParameters() { video_params.width = static_cast(monitors_[monitor_index_].width); video_params.height = static_cast(monitors_[monitor_index_].height); video_params.client_refresh_rate = client_refresh_rate_; + video_params.max_mbps = max_mbps_; video_params.monitor = monitors_[monitor_index_]; video_params.send_message = std::bind(&WorkerStreaming::sendPipeMessageFromOtherThread, this, std::placeholders::_1, std::placeholders::_2); @@ -403,6 +405,16 @@ int32_t WorkerStreaming::negotiateStreamParameters() { return kExitCodeOK; } +void WorkerStreaming::getUserMaxMbps() { + auto settings = ltlib::Settings::create(ltlib::Settings::Storage::Sqlite); + if (settings == nullptr) { + LOG(WARNING) << "Create Settings failed, we will not limit the bitrate"; + return; + } + max_mbps_ = static_cast(settings->getInteger("max_mbps").value_or(0)); + LOG(INFO) << "Loaded max_mbps " << max_mbps_; +} + void WorkerStreaming::mainLoop(const std::function& i_am_alive) { LOG(INFO) << "Worker enter main loop"; ioloop_->run(i_am_alive); diff --git a/lanthing/src/worker/worker_streaming.h b/lanthing/src/worker/worker_streaming.h index 517c640c..56e01a3c 100644 --- a/lanthing/src/worker/worker_streaming.h +++ b/lanthing/src/worker/worker_streaming.h @@ -83,6 +83,7 @@ class WorkerStreaming : public Worker { void recoverDisplaySettings(); bool negotiateAllParameters(); int32_t negotiateStreamParameters(); + void getUserMaxMbps(); void mainLoop(const std::function& i_am_alive); void stop(int exit_code); void postTask(const std::function& task); @@ -135,6 +136,7 @@ class WorkerStreaming : public Worker { std::unique_ptr audio_; std::unique_ptr settings_; std::vector monitors_; + uint32_t max_mbps_ = 0; }; } // namespace worker