diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index d22555f665f..b74ab4f920c 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -409,6 +409,25 @@ dwmflush dwmflush = enabled +min_fps_target +^^^^^^^^^^^^^^ + +**Description** + The minimum FPS Sunshine will attempt to maintain. Increasing this value slightly may help when streaming + mostly static content. + + .. Warning:: Higher values will consume more bandwidth. + +**Default** + ``10`` + +**Range** + ``1-240`` + +**Example** + .. code-block:: text + min_fps_target = 10 + Audio ----- diff --git a/src/config.cpp b/src/config.cpp index 2f16cbffce8..e625206e952 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -330,6 +330,7 @@ namespace config { 0, // hevc_mode + 10, // min_fps_target 1, // min_threads { "superfast"s, // preset @@ -957,6 +958,7 @@ namespace config { string_f(vars, "adapter_name", video.adapter_name); string_f(vars, "output_name", video.output_name); bool_f(vars, "dwmflush", video.dwmflush); + int_between_f(vars, "min_fps_target", video.min_fps_target, { 1, 240 }); path_f(vars, "pkey", nvhttp.pkey); path_f(vars, "cert", nvhttp.cert); diff --git a/src/config.h b/src/config.h index fc77748bdde..c76bbee6066 100644 --- a/src/config.h +++ b/src/config.h @@ -15,6 +15,7 @@ namespace config { int hevc_mode; + int min_fps_target; // Minimum fps target, determines minimum frame time int min_threads; // Minimum number of threads/slices for CPU encoding struct { std::string sw_preset; diff --git a/src/video.cpp b/src/video.cpp index 0ee04ff39aa..318268d9bd2 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -1311,6 +1311,10 @@ namespace video { return; } + // set minimum frame time, avoiding violation of client-requested target framerate + auto minimum_frame_time = std::chrono::milliseconds(1000 / std::min(config.framerate, config::video.min_fps_target)); + BOOST_LOG(debug) << "Minimum frame time set to "sv << minimum_frame_time.count() << "ms, based on min fps target of "sv << std::min(config.framerate, config::video.min_fps_target) << "."sv; + auto frame = session->device->frame; auto shutdown_event = mail->event(mail::shutdown); @@ -1336,9 +1340,9 @@ namespace video { idr_events->pop(); } - // Encode at a minimum of 10 FPS to avoid image quality issues with static content + // Encode at a minimum FPS to avoid image quality issues with static content if (!frame->key_frame || images->peek()) { - if (auto img = images->pop(100ms)) { + if (auto img = images->pop(minimum_frame_time)) { if (session->device->convert(*img)) { BOOST_LOG(error) << "Could not convert image"sv; return; diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 9e664ee7ee7..05e511e3cc2 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -550,6 +550,22 @@

Configuration

Disable if you encounter any VSync-related issues. + +
+ + +
+ The minimum FPS Sunshine will attempt to maintain.
+ Increasing this value slightly may help when streaming mostly static content.
+ Higher values will consume more bandwidth.
+
+
Configuration Quantization Parameter
Some devices may not support Constant Bit Rate.
For those devices, QP is used instead.
- Higher value means more compression, but less quality
+ Higher value means more compression, but less quality.
@@ -983,6 +999,7 @@

Configuration

"key_rightalt_to_key_win": "disabled", "keyboard": "enabled", "min_log_level": 2, + "min_fps_target": 10, "mouse": "enabled", "nv_coder": "auto", "nv_preset": "p4",