From 73d777fa0b2e9d6f8242bb71201ba53a9f9e973c Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 24 Oct 2024 19:11:50 -0500 Subject: [PATCH 1/3] feat(stream)!: remove limit on concurrent sessions and allow quitting apps with active sessions (#3325) --- docs/configuration.md | 26 ------ src/config.cpp | 3 - src/config.h | 3 - src/network.cpp | 5 +- src/network.h | 2 +- src/nvhttp.cpp | 30 +------ src/rtsp.cpp | 84 +++++++++---------- src/rtsp.h | 10 +++ src/stream.cpp | 2 +- src_assets/common/assets/web/config.html | 1 - .../assets/web/configs/tabs/General.vue | 10 --- 11 files changed, 56 insertions(+), 120 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index f853e418..2b282d1c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -186,32 +186,6 @@ editing the `conf` file in a text editor. Use the examples as reference. -### channels - - - - - - - - - - - - - - -
Description - Sunshine can support multiple clients streaming simultaneously, - at the cost of higher CPU and GPU usage. - @note{All connected clients share control of the same streaming session.} - @warning{Some hardware encoders may have limitations that reduce performance with multiple streams.} -
Default@code{} - 1 - @endcode
Example@code{} - channels = 1 - @endcode
- ### global_prep_cmd diff --git a/src/config.cpp b/src/config.cpp index b42eb097..8475a5e3 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -395,7 +395,6 @@ namespace config { APPS_JSON_PATH, 20, // fecPercentage - 1, // channels ENCRYPTION_MODE_NEVER, // lan_encryption_mode ENCRYPTION_MODE_OPPORTUNISTIC, // wan_encryption_mode @@ -1046,8 +1045,6 @@ namespace config { stream.ping_timeout = std::chrono::milliseconds(to); } - int_between_f(vars, "channels", stream.channels, { 1, std::numeric_limits::max() }); - int_between_f(vars, "lan_encryption_mode", stream.lan_encryption_mode, { 0, 2 }); int_between_f(vars, "wan_encryption_mode", stream.wan_encryption_mode, { 0, 2 }); diff --git a/src/config.h b/src/config.h index c987fc54..e599afae 100644 --- a/src/config.h +++ b/src/config.h @@ -94,9 +94,6 @@ namespace config { int fec_percentage; - // max unique instances of video and audio streams - int channels; - // Video encryption settings for LAN and WAN streams int lan_encryption_mode; int wan_encryption_mode; diff --git a/src/network.cpp b/src/network.cpp index 5d56866c..5b34df46 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -163,7 +163,7 @@ namespace net { } host_t - host_create(af_e af, ENetAddress &addr, std::size_t peers, std::uint16_t port) { + host_create(af_e af, ENetAddress &addr, std::uint16_t port) { static std::once_flag enet_init_flag; std::call_once(enet_init_flag, []() { enet_initialize(); @@ -173,7 +173,8 @@ namespace net { enet_address_set_host(&addr, any_addr.data()); enet_address_set_port(&addr, port); - auto host = host_t { enet_host_create(af == IPV4 ? AF_INET : AF_INET6, &addr, peers, 0, 0, 0) }; + // Maximum of 128 clients, which should be enough for anyone + auto host = host_t { enet_host_create(af == IPV4 ? AF_INET : AF_INET6, &addr, 128, 0, 0, 0) }; // Enable opportunistic QoS tagging (automatically disables if the network appears to drop tagged packets) enet_socket_set_option(host->socket, ENET_SOCKOPT_QOS, 1); diff --git a/src/network.h b/src/network.h index dbae81b9..98de905b 100644 --- a/src/network.h +++ b/src/network.h @@ -53,7 +53,7 @@ namespace net { from_address(const std::string_view &view); host_t - host_create(af_e af, ENetAddress &addr, std::size_t peers, std::uint16_t port); + host_create(af_e af, ENetAddress &addr, std::uint16_t port); /** * @brief Get the address family enum value from a string. diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index 7eec1100..fbdbd051 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -820,14 +820,6 @@ namespace nvhttp { response->close_connection_after_response = true; }); - if (rtsp_stream::session_count() == config::stream.channels) { - tree.put("root.resume", 0); - tree.put("root..status_code", 503); - tree.put("root..status_message", "The host's concurrent stream limit has been reached. Stop an existing stream or increase the 'Channels' value in the Sunshine Web UI."); - - return; - } - auto args = request->parse_query_string(); if ( args.find("rikey"s) == std::end(args) || @@ -913,16 +905,6 @@ namespace nvhttp { response->close_connection_after_response = true; }); - // It is possible that due a race condition that this if-statement gives a false negative, - // that is automatically resolved in rtsp_server_t - if (rtsp_stream::session_count() == config::stream.channels) { - tree.put("root.resume", 0); - tree.put("root..status_code", 503); - tree.put("root..status_message", "The host's concurrent stream limit has been reached. Stop an existing stream or increase the 'Channels' value in the Sunshine Web UI."); - - return; - } - auto current_appid = proc::proc.running(); if (current_appid == 0) { tree.put("root.resume", 0); @@ -999,19 +981,11 @@ namespace nvhttp { response->close_connection_after_response = true; }); - // It is possible that due a race condition that this if-statement gives a false positive, - // the client should try again - if (rtsp_stream::session_count() != 0) { - tree.put("root.resume", 0); - tree.put("root..status_code", 503); - tree.put("root..status_message", "All sessions must be disconnected before quitting"); - - return; - } - tree.put("root.cancel", 1); tree.put("root..status_code", 200); + rtsp_stream::terminate_sessions(); + if (proc::proc.running() > 0) { proc::proc.terminate(); } diff --git a/src/rtsp.cpp b/src/rtsp.cpp index 3f146937..a6abd9c1 100644 --- a/src/rtsp.cpp +++ b/src/rtsp.cpp @@ -26,6 +26,7 @@ extern "C" { #include "sync.h" #include "video.h" +#include #include namespace asio = boost::asio; @@ -417,13 +418,6 @@ namespace rtsp_stream { int bind(net::af_e af, std::uint16_t port, boost::system::error_code &ec) { - { - auto lg = _session_slots.lock(); - - _session_slots->resize(config::stream.channels); - _slot_count = config::stream.channels; - } - acceptor.open(af == net::IPV4 ? tcp::v4() : tcp::v6(), ec); if (ec) { return -1; @@ -529,7 +523,6 @@ namespace rtsp_stream { } raised_timeout = now + config::stream.ping_timeout; - --_slot_count; launch_event.raise(std::move(launch_session)); } @@ -552,9 +545,14 @@ namespace rtsp_stream { } } + /** + * @brief Get the number of active sessions. + * @return Count of active sessions. + */ int - session_count() const { - return config::stream.channels - _slot_count; + session_count() { + auto lg = _session_slots.lock(); + return _session_slots->size(); } safe::event_t> launch_event; @@ -573,20 +571,21 @@ namespace rtsp_stream { auto discarded = launch_event.pop(0s); if (discarded) { BOOST_LOG(debug) << "Event timeout: "sv << discarded->unique_id; - ++_slot_count; } } auto lg = _session_slots.lock(); - for (auto &slot : *_session_slots) { - if (slot && (all || stream::session::state(*slot) == stream::session::state_e::STOPPING)) { - stream::session::stop(*slot); - stream::session::join(*slot); + for (auto i = _session_slots->begin(); i != _session_slots->end();) { + auto &slot = *(*i); + if (all || stream::session::state(slot) == stream::session::state_e::STOPPING) { + stream::session::stop(slot); + stream::session::join(slot); - slot.reset(); - - ++_slot_count; + i = _session_slots->erase(i); + } + else { + i++; } } @@ -595,36 +594,33 @@ namespace rtsp_stream { } } + /** + * @brief Removes the provided session from the set of sessions. + * @param session The session to remove. + */ void - clear(std::shared_ptr *session_p) { + remove(const std::shared_ptr &session) { auto lg = _session_slots.lock(); - - session_p->reset(); - - ++_slot_count; + _session_slots->erase(session); } - std::shared_ptr * - accept(std::shared_ptr &session) { + /** + * @brief Inserts the provided session into the set of sessions. + * @param session The session to insert. + */ + void + insert(const std::shared_ptr &session) { auto lg = _session_slots.lock(); - - for (auto &slot : *_session_slots) { - if (!slot) { - slot = session; - return &slot; - } - } - - return nullptr; + _session_slots->emplace(session); + BOOST_LOG(info) << "New streaming session started [active sessions: "sv << _session_slots->size() << ']'; } private: std::unordered_map _map_cmd_cb; - sync_util::sync_t>> _session_slots; + sync_util::sync_t>> _session_slots; std::chrono::steady_clock::time_point raised_timeout; - int _slot_count; boost::asio::io_service ios; tcp::acceptor acceptor { ios }; @@ -652,6 +648,11 @@ namespace rtsp_stream { return server.session_count(); } + void + terminate_sessions() { + server.clear(true); + } + int send(tcp::socket &sock, const std::string_view &sv) { std::size_t bytes_send = 0; @@ -1110,19 +1111,12 @@ namespace rtsp_stream { } auto stream_session = stream::session::alloc(config, session); - - auto slot = server->accept(stream_session); - if (!slot) { - BOOST_LOG(info) << "Ran out of slots for client from ["sv << ']'; - - respond(sock, session, &option, 503, "Service Unavailable", req->sequenceNumber, {}); - return; - } + server->insert(stream_session); if (stream::session::start(*stream_session, sock.remote_endpoint().address().to_string())) { BOOST_LOG(error) << "Failed to start a streaming session"sv; - server->clear(slot); + server->remove(stream_session); respond(sock, session, &option, 500, "Internal Server Error", req->sequenceNumber, {}); return; } diff --git a/src/rtsp.h b/src/rtsp.h index 910fc427..0ea78a9d 100644 --- a/src/rtsp.h +++ b/src/rtsp.h @@ -48,9 +48,19 @@ namespace rtsp_stream { void launch_session_clear(uint32_t launch_session_id); + /** + * @brief Get the number of active sessions. + * @return Count of active sessions. + */ int session_count(); + /** + * @brief Terminates all running streaming sessions. + */ + void + terminate_sessions(); + void rtpThread(); diff --git a/src/stream.cpp b/src/stream.cpp index 0f6b9463..e6729a21 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -252,7 +252,7 @@ namespace stream { public: int bind(net::af_e address_family, std::uint16_t port) { - _host = net::host_create(address_family, _addr, config::stream.channels, port); + _host = net::host_create(address_family, _addr, port); return !(bool) _host; } diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 3c9cb3aa..c9c0a6dd 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -203,7 +203,6 @@ id: "advanced", name: "Advanced", options: { - "channels": 1, "fec_percentage": 20, "qp": 28, "min_threads": 2, diff --git a/src_assets/common/assets/web/configs/tabs/General.vue b/src_assets/common/assets/web/configs/tabs/General.vue index 8c188765..5349a3c4 100644 --- a/src_assets/common/assets/web/configs/tabs/General.vue +++ b/src_assets/common/assets/web/configs/tabs/General.vue @@ -73,16 +73,6 @@ function removeCmd(index) {
{{ $t('config.log_level_desc') }}
- -
- - -
- {{ $t('config.channels_desc_1') }}
- {{ $t('_common.note') }} {{ $t('config.channels_desc_2') }} -
-
-
From 8810c5ccdd3327521eb41a1a17999d87095423b8 Mon Sep 17 00:00:00 2001 From: Kelvie Wong Date: Thu, 24 Oct 2024 18:26:35 -0700 Subject: [PATCH 2/3] docs(troubleshooting): Add workaround for "blur" plugin in KDE (#3328) --- docs/troubleshooting.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index da91630d..133a063b 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -165,6 +165,14 @@ high as long as the encoder is used. ### Gamescope compatibility Some users have reported stuttering issues when streaming games running within Gamescope. +### Occasional flickering in KDE + +The `blur` plugin causes flickering during streaming for some people. Disable it from the +KDE System Settings or from the commandline: +```bash +qdbus org.kde.KWin /Effects unloadEffect blur +``` + ## macOS ### Dynamic session lookup failed From 5582e6186fc01ed0949363c931199ebd04a8bc6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 09:24:19 +0000 Subject: [PATCH 3/3] build(deps-dev): bump the dev-dependencies group across 1 directory with 4 updates Bumps the dev-dependencies group with 4 updates in the / directory: [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue), [serve](https://github.com/vercel/serve), [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) and [vite-plugin-ejs](https://github.com/trapcodeio/vite-plugin-ejs). Updates `@vitejs/plugin-vue` from 4.6.2 to 5.1.4 - [Release notes](https://github.com/vitejs/vite-plugin-vue/releases) - [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@5.1.4/packages/plugin-vue) Updates `serve` from 14.2.3 to 14.2.4 - [Release notes](https://github.com/vercel/serve/releases) - [Commits](https://github.com/vercel/serve/compare/14.2.3...14.2.4) Updates `vite` from 4.5.2 to 5.3.6 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v5.3.6/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v5.3.6/packages/vite) Updates `vite-plugin-ejs` from 1.6.4 to 1.7.0 - [Release notes](https://github.com/trapcodeio/vite-plugin-ejs/releases) - [Commits](https://github.com/trapcodeio/vite-plugin-ejs/compare/v1.6.4...v1.7.0) --- updated-dependencies: - dependency-name: "@vitejs/plugin-vue" dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: serve dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: vite dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: vite-plugin-ejs dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 78d6994c..0b29b400 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "vue-i18n": "9.14.0" }, "devDependencies": { - "@vitejs/plugin-vue": "4.6.2", - "serve": "14.2.3", - "vite": "4.5.2", - "vite-plugin-ejs": "1.6.4" + "@vitejs/plugin-vue": "5.1.4", + "serve": "14.2.4", + "vite": "5.3.6", + "vite-plugin-ejs": "1.7.0" } }