mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-08-10 00:52:16 +00:00
fix(video): restore the ability to set a minimum fps target (#4114)
This commit is contained in:
@@ -1270,7 +1270,7 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
||||
<td colspan="2">
|
||||
Remap the requested resolution and FPS to another display mode.<br>
|
||||
Depending on the [dd_resolution_option](#dd_resolution_option) and
|
||||
[dd_refresh_rate_option](#dd_refresh_rate_option) values, the following mapping
|
||||
[dd_refresh_rate_option](#dd_refresh_rate_option) values, the following mapping
|
||||
groups are available:
|
||||
<ul>
|
||||
<li>`mixed` - both options are set to `auto`.</li>
|
||||
@@ -1281,7 +1281,7 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
||||
`refresh_rate_only` - only [dd_refresh_rate_option](#dd_refresh_rate_option) is set to `auto`.
|
||||
</li>
|
||||
</ul>
|
||||
For each of those groups, a list of fields can be configured to perform remapping:
|
||||
For each of those groups, a list of fields can be configured to perform remapping:
|
||||
<ul>
|
||||
<li>
|
||||
`requested_resolution` - resolution that needs to be matched in order to use this remapping entry.
|
||||
@@ -1291,10 +1291,10 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
||||
<li>`final_refresh_rate` - refresh rate value to be used if the entry was matched.</li>
|
||||
</ul>
|
||||
If `requested_*` field is left empty, it will match <b>everything</b>.<br>
|
||||
If `final_*` field is left empty, the original value will not be remapped and either a requested, manual
|
||||
or current value is used. However, at least one `final_*` must be set, otherwise the entry is considered
|
||||
If `final_*` field is left empty, the original value will not be remapped and either a requested, manual
|
||||
or current value is used. However, at least one `final_*` must be set, otherwise the entry is considered
|
||||
invalid.<br>
|
||||
@note{"Optimize game settings" must be enabled on client side for ANY entry with `resolution`
|
||||
@note{"Optimize game settings" must be enabled on client side for ANY entry with `resolution`
|
||||
field to be considered.}
|
||||
@note{First entry to be matched in the list is the one that will be used.}
|
||||
@tip{`requested_resolution` and `final_resolution` can be omitted for `refresh_rate_only` group.}
|
||||
@@ -1371,6 +1371,32 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### minimum_fps_target
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td colspan="2">
|
||||
Sunshine tries to save bandwidth when content on screen is static or a low framerate. Because many clients expect a constant stream of video frames, a certain amount of duplicate frames are sent when this happens. This setting controls the lowest effective framerate a stream can reach.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Default</td>
|
||||
<td colspan="2">@code{}
|
||||
0
|
||||
@endcode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="3">Choices</td>
|
||||
<td>0</td>
|
||||
<td>Use half the stream's FPS as the minimum target.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1-1000</td>
|
||||
<td>Specify your own value. The real minimum may differ from this value.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Network
|
||||
|
||||
### upnp
|
||||
|
||||
@@ -504,7 +504,8 @@ namespace config {
|
||||
{} // wa
|
||||
}, // display_device
|
||||
|
||||
0 // max_bitrate
|
||||
0, // max_bitrate
|
||||
0 // minimum_fps_target (0 = framerate)
|
||||
};
|
||||
|
||||
audio_t audio {
|
||||
@@ -1146,6 +1147,7 @@ namespace config {
|
||||
}
|
||||
|
||||
int_f(vars, "max_bitrate", video.max_bitrate);
|
||||
double_between_f(vars, "minimum_fps_target", video.minimum_fps_target, {0.0, 1000.0});
|
||||
|
||||
path_f(vars, "pkey", nvhttp.pkey);
|
||||
path_f(vars, "cert", nvhttp.cert);
|
||||
|
||||
@@ -141,6 +141,7 @@ namespace config {
|
||||
} dd;
|
||||
|
||||
int max_bitrate; // Maximum bitrate, sets ceiling in kbps for bitrate requested from client
|
||||
double minimum_fps_target; ///< Lowest framerate that will be used when streaming. Range 0-1000, 0 = half of client's requested framerate.
|
||||
};
|
||||
|
||||
struct audio_t {
|
||||
|
||||
@@ -1890,9 +1890,10 @@ namespace video {
|
||||
}
|
||||
});
|
||||
|
||||
// set minimum frame time based on client-requested target framerate
|
||||
std::chrono::duration<double, std::milli> minimum_frame_time {1000.0 / config.framerate};
|
||||
BOOST_LOG(info) << "Minimum frame time set to "sv << minimum_frame_time.count() << "ms, based on client-requested target framerate "sv << config.framerate << "."sv;
|
||||
// set max frame time based on client-requested target framerate.
|
||||
double minimum_fps_target = (config::video.minimum_fps_target > 0.0) ? config::video.minimum_fps_target : config.framerate;
|
||||
std::chrono::duration<double, std::milli> max_frametime {1000.0 / minimum_fps_target};
|
||||
BOOST_LOG(info) << "Minimum FPS target set to ~"sv << (minimum_fps_target / 2) << "fps ("sv << max_frametime.count() * 2 << "ms)"sv;
|
||||
|
||||
auto shutdown_event = mail->event<bool>(mail::shutdown);
|
||||
auto packets = mail::man->queue<packet_t>(mail::video_packets);
|
||||
@@ -1943,7 +1944,7 @@ namespace video {
|
||||
|
||||
// Encode at a minimum FPS to avoid image quality issues with static content
|
||||
if (!requested_idr_frame || images->peek()) {
|
||||
if (auto img = images->pop(minimum_frame_time)) {
|
||||
if (auto img = images->pop(max_frametime)) {
|
||||
frame_timestamp = img->frame_timestamp;
|
||||
if (session->convert(*img)) {
|
||||
BOOST_LOG(error) << "Could not convert image"sv;
|
||||
|
||||
@@ -179,6 +179,7 @@
|
||||
"dd_mode_remapping": {"mixed": [], "resolution_only": [], "refresh_rate_only": []},
|
||||
"dd_wa_hdr_toggle_delay": 0,
|
||||
"max_bitrate": 0,
|
||||
"minimum_fps_target": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -17,6 +17,13 @@ const config = ref(props.config)
|
||||
<input type="number" class="form-control" id="max_bitrate" placeholder="0" v-model="config.max_bitrate" />
|
||||
<div class="form-text">{{ $t("config.max_bitrate_desc") }}</div>
|
||||
</div>
|
||||
|
||||
<!--minimum_fps_target-->
|
||||
<div class="mb-3">
|
||||
<label for="minimum_fps_target" class="form-label">{{ $t("config.minimum_fps_target") }}</label>
|
||||
<input type="number" min="0" max="1000" class="form-control" id="minimum_fps_target" placeholder="0" v-model="config.minimum_fps_target" />
|
||||
<div class="form-text">{{ $t("config.minimum_fps_target_desc") }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -256,6 +256,8 @@
|
||||
"log_path_desc": "The file where the current logs of Sunshine are stored.",
|
||||
"max_bitrate": "Maximum Bitrate",
|
||||
"max_bitrate_desc": "The maximum bitrate (in Kbps) that Sunshine will encode the stream at. If set to 0, it will always use the bitrate requested by Moonlight.",
|
||||
"minimum_fps_target": "Minimum FPS Target",
|
||||
"minimum_fps_target_desc": "The lowest effective FPS a stream can reach. A value of 0 is treated as roughly half of the stream's FPS. A setting of 20 is recommended if you stream 24 or 30fps content.",
|
||||
"min_threads": "Minimum CPU Thread Count",
|
||||
"min_threads_desc": "Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest value that can reliably encode at your desired streaming settings on your hardware.",
|
||||
"misc": "Miscellaneous options",
|
||||
|
||||
Reference in New Issue
Block a user