Skip to content

Commit 1102ac9

Browse files
author
loki
committed
Merge branch 'nvenc'
2 parents 12115a8 + 7ee5966 commit 1102ac9

24 files changed

+2586
-1156
lines changed

CMakeLists.txt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,12 @@ if(WIN32)
5757
include_directories(
5858
ViGEmClient/include)
5959
set(PLATFORM_TARGET_FILES
60-
sunshine/platform/windows.cpp
61-
sunshine/platform/windows_dxgi.cpp
62-
sunshine/platform/windows_wasapi.cpp
60+
sunshine/platform/windows/input.cpp
61+
sunshine/platform/windows/display.h
62+
sunshine/platform/windows/display_base.cpp
63+
sunshine/platform/windows/display_vram.cpp
64+
sunshine/platform/windows/display_ram.cpp
65+
sunshine/platform/windows/audio.cpp
6366
ViGEmClient/src/ViGEmClient.cpp
6467
ViGEmClient/include/ViGEm/Client.h
6568
ViGEmClient/include/ViGEm/Common.h
@@ -82,8 +85,8 @@ else()
8285

8386
find_package(X11 REQUIRED)
8487
set(PLATFORM_TARGET_FILES
85-
sunshine/platform/linux.cpp
86-
sunshine/platform/linux_evdev.cpp)
88+
sunshine/platform/linux/display.cpp
89+
sunshine/platform/linux/input.cpp)
8790

8891
set(PLATFORM_LIBRARIES
8992
Xfixes

assets/sunshine.conf

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,64 @@
105105
# Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually
106106
# worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest
107107
# value that can reliably encode at your desired streaming settings on your hardware.
108-
# min_threads = 2
108+
# min_threads = 1
109109

110110
# Allows the client to request HEVC Main or HEVC Main10 video streams.
111-
# HEVC is more CPU-intensive to encode, so enabling this may reduce performance.
112-
# If set to 0 (default), Sunshine will not advertise support for HEVC
113-
# If set to 1, Sunshine will advertise support for HEVC Main profile
114-
# If set to 2, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles
115-
# hevc_mode = 2
116-
111+
# HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software encoding.
112+
# If set to 0 (default), Sunshine will specify support for HEVC based on encoder
113+
# If set to 1, Sunshine will not advertise support for HEVC
114+
# If set to 2, Sunshine will advertise support for HEVC Main profile
115+
# If set to 3, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles
116+
# hevc_mode = 0
117+
118+
# Force a specific encoder, otherwise Sunshine will use the first encoder that is available
119+
# supported encoders:
120+
# nvenc
121+
# software
122+
#
123+
# encoder = nvenc
124+
##################################### Software #####################################
117125
# See x264 --fullhelp for the different presets
118-
# preset = superfast
119-
# tune = zerolatency
126+
# sw_preset = superfast
127+
# sw_tune = zerolatency
120128
#
129+
130+
##################################### NVENC #####################################
131+
###### presets ###########
132+
# default
133+
# hp -- high performance
134+
# hq -- high quality
135+
# slow -- hq 2 passes
136+
# medium -- hq 1 pass
137+
# fast -- hp 1 pass
138+
# bd
139+
# ll -- low latency
140+
# llhq
141+
# llhp
142+
# lossless
143+
# losslesshp
144+
##########################
145+
# nv_preset = llhq
121146
#
147+
####### rate control #####
148+
# auto -- let ffmpeg decide rate control
149+
# constqp -- constant QP mode
150+
# vbr -- variable bitrate
151+
# cbr -- constant bitrate
152+
# cbr_hq -- cbr high quality
153+
# cbr_ld_hq -- cbr low delay high quality
154+
# vbr_hq -- vbr high quality
155+
##########################
156+
# nv_rc = auto
157+
158+
###### h264 entropy ######
159+
# auto -- let ffmpeg nvenc decide the entropy encoding
160+
# cabac
161+
# cavlc
162+
##########################
163+
# nv_coder = auto
164+
165+
122166
##############################################
123167
# Some configurable parameters, are merely toggles for specific features
124168
# The first occurrence turns it on, the second occurence turns it off, the third occurence turns it on again, etc, etc

pre-compiled

Submodule pre-compiled updated from 51f776d to afd9a9b

sunshine/config.cpp

Lines changed: 145 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,97 @@
1515
#define APPS_JSON_PATH SUNSHINE_ASSETS_DIR "/" APPS_JSON
1616
namespace config {
1717
using namespace std::literals;
18+
19+
namespace nv {
20+
enum preset_e : int {
21+
_default = 0,
22+
slow,
23+
medium,
24+
fast,
25+
hp,
26+
hq,
27+
bd,
28+
ll_default,
29+
llhq,
30+
llhp,
31+
lossless_default, // lossless presets must be the last ones
32+
lossless_hp,
33+
};
34+
35+
enum rc_e : int {
36+
constqp = 0x0, /**< Constant QP mode */
37+
vbr = 0x1, /**< Variable bitrate mode */
38+
cbr = 0x2, /**< Constant bitrate mode */
39+
cbr_ld_hq = 0x8, /**< low-delay CBR, high quality */
40+
cbr_hq = 0x10, /**< CBR, high quality (slower) */
41+
vbr_hq = 0x20 /**< VBR, high quality (slower) */
42+
};
43+
44+
enum coder_e : int {
45+
_auto = 0,
46+
cabac,
47+
cavlc
48+
};
49+
50+
std::optional<preset_e> preset_from_view(const std::string_view &preset) {
51+
#define _CONVERT_(x) if(preset == #x##sv) return x
52+
_CONVERT_(slow);
53+
_CONVERT_(medium);
54+
_CONVERT_(fast);
55+
_CONVERT_(hp);
56+
_CONVERT_(bd);
57+
_CONVERT_(ll_default);
58+
_CONVERT_(llhq);
59+
_CONVERT_(llhp);
60+
_CONVERT_(lossless_default);
61+
_CONVERT_(lossless_hp);
62+
if(preset == "default"sv) return _default;
63+
#undef _CONVERT_
64+
return std::nullopt;
65+
}
66+
67+
std::optional<rc_e> rc_from_view(const std::string_view &rc) {
68+
#define _CONVERT_(x) if(rc == #x##sv) return x
69+
_CONVERT_(constqp);
70+
_CONVERT_(vbr);
71+
_CONVERT_(cbr);
72+
_CONVERT_(cbr_hq);
73+
_CONVERT_(vbr_hq);
74+
_CONVERT_(cbr_ld_hq);
75+
#undef _CONVERT_
76+
return std::nullopt;
77+
}
78+
79+
int coder_from_view(const std::string_view &coder) {
80+
if(coder == "auto"sv) return _auto;
81+
if(coder == "cabac"sv || coder == "ac"sv) return cabac;
82+
if(coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
83+
84+
return -1;
85+
}
86+
}
87+
1888
video_t video {
1989
0, // crf
2090
28, // qp
2191

22-
2, // min_threads
23-
2492
0, // hevc_mode
25-
"superfast"s, // preset
26-
"zerolatency"s, // tune
93+
94+
1, // min_threads
95+
{
96+
"superfast"s, // preset
97+
"zerolatency"s, // tune
98+
}, // software
99+
100+
{
101+
nv::llhq,
102+
std::nullopt,
103+
-1
104+
}, // nv
105+
106+
{}, // encoder
27107
{}, // adapter_name
28-
{} // output_name
108+
{} // output_name
29109
};
30110

31111
audio_t audio {};
@@ -138,6 +218,37 @@ void int_f(std::unordered_map<std::string, std::string> &vars, const std::string
138218
vars.erase(it);
139219
}
140220

221+
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::optional<int> &input) {
222+
auto it = vars.find(name);
223+
224+
if(it == std::end(vars)) {
225+
return;
226+
}
227+
228+
auto &val = it->second;
229+
input = util::from_chars(&val[0], &val[0] + val.size());
230+
231+
vars.erase(it);
232+
}
233+
234+
template<class F>
235+
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, F &&f) {
236+
std::string tmp;
237+
string_f(vars, name, tmp);
238+
if(!tmp.empty()) {
239+
input = f(tmp);
240+
}
241+
}
242+
243+
template<class F>
244+
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::optional<int> &input, F &&f) {
245+
std::string tmp;
246+
string_f(vars, name, tmp);
247+
if(!tmp.empty()) {
248+
input = f(tmp);
249+
}
250+
}
251+
141252
void int_between_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, const std::pair<int, int> &range) {
142253
int temp = input;
143254

@@ -149,6 +260,28 @@ void int_between_f(std::unordered_map<std::string, std::string> &vars, const std
149260
}
150261
}
151262

263+
bool to_bool(std::string &boolean) {
264+
std::for_each(std::begin(boolean), std::end(boolean), [](char ch) { return (char)std::tolower(ch); });
265+
266+
return
267+
boolean == "true"sv ||
268+
boolean == "yes"sv ||
269+
boolean == "enable"sv ||
270+
(std::find(std::begin(boolean), std::end(boolean), '1') != std::end(boolean));
271+
}
272+
void bool_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) {
273+
std::string tmp;
274+
string_restricted_f(vars, name, tmp, {
275+
"enable"sv, "dis"
276+
});
277+
278+
if(tmp.empty()) {
279+
return;
280+
}
281+
282+
input = to_bool(tmp) ? 1 : 0;
283+
}
284+
152285
void print_help(const char *name) {
153286
std::cout <<
154287
"Usage: "sv << name << " [options] [/path/to/configuration_file]"sv << std::endl <<
@@ -190,10 +323,14 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
190323
int_f(vars, "qp", video.qp);
191324
int_f(vars, "min_threads", video.min_threads);
192325
int_between_f(vars, "hevc_mode", video.hevc_mode, {
193-
0, 2
326+
0, 3
194327
});
195-
string_f(vars, "preset", video.preset);
196-
string_f(vars, "tune", video.tune);
328+
string_f(vars, "sw_preset", video.sw.preset);
329+
string_f(vars, "sw_tune", video.sw.tune);
330+
int_f(vars, "nv_preset", video.nv.preset, nv::preset_from_view);
331+
int_f(vars, "nv_rc", video.nv.preset, nv::rc_from_view);
332+
int_f(vars, "nv_coder", video.nv.coder, nv::coder_from_view);
333+
string_f(vars, "encoder", video.encoder);
197334
string_f(vars, "adapter_name", video.adapter_name);
198335
string_f(vars, "output_name", video.output_name);
199336

sunshine/config.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,29 @@
44
#include <chrono>
55
#include <string>
66
#include <bitset>
7+
#include <optional>
78

89
namespace config {
910
struct video_t {
1011
// ffmpeg params
1112
int crf; // higher == more compression and less quality
1213
int qp; // higher == more compression and less quality, ignored if crf != 0
1314

14-
int min_threads; // Minimum number of threads/slices for CPU encoding
15-
1615
int hevc_mode;
17-
std::string preset;
18-
std::string tune;
1916

17+
int min_threads; // Minimum number of threads/slices for CPU encoding
18+
struct {
19+
std::string preset;
20+
std::string tune;
21+
} sw;
22+
23+
struct {
24+
std::optional<int> preset;
25+
std::optional<int> rc;
26+
int coder;
27+
} nv;
28+
29+
std::string encoder;
2030
std::string adapter_name;
2131
std::string output_name;
2232
};

sunshine/main.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ int main(int argc, char *argv[]) {
140140
auto deinit_guard = platf::init();
141141
input::init();
142142
reed_solomon_init();
143-
video::init();
143+
if(video::init()) {
144+
return 2;
145+
}
144146

145147
task_pool.start(1);
146148

sunshine/nvhttp.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,15 @@ void update_id_client(const std::string &uniqueID, std::string &&cert, op_e op)
168168
}
169169

170170
void getservercert(pair_session_t &sess, pt::ptree &tree, const std::string &pin) {
171-
auto salt = util::from_hex<std::array<uint8_t, 16>>(sess.async_insert_pin.salt, true);
171+
if(sess.async_insert_pin.salt.size() < 32) {
172+
tree.put("root.paired", 0);
173+
tree.put("root.<xmlattr>.status_code", 400);
174+
return;
175+
}
176+
177+
std::string_view salt_view { sess.async_insert_pin.salt.data(), 32 };
178+
179+
auto salt = util::from_hex<std::array<uint8_t, 16>>(salt_view, true);
172180

173181
auto key = crypto::gen_aes_key(*salt, pin);
174182
sess.cipher_key = std::make_unique<crypto::aes_t>(key);
@@ -464,13 +472,13 @@ void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
464472
tree.put("root.GfeVersion", GFE_VERSION);
465473
tree.put("root.uniqueid", unique_id);
466474
tree.put("root.mac", platf::get_mac_address(request->local_endpoint_address()));
467-
tree.put("root.MaxLumaPixelsHEVC", config::video.hevc_mode > 0 ? "1869449984" : "0");
475+
tree.put("root.MaxLumaPixelsHEVC", config::video.hevc_mode > 1 ? "1869449984" : "0");
468476
tree.put("root.LocalIP", request->local_endpoint_address());
469477

470-
if(config::video.hevc_mode == 2) {
478+
if(config::video.hevc_mode == 3) {
471479
tree.put("root.ServerCodecModeSupport", "3843");
472480
}
473-
else if(config::video.hevc_mode == 1) {
481+
else if(config::video.hevc_mode == 2) {
474482
tree.put("root.ServerCodecModeSupport", "259");
475483
}
476484
else {
@@ -484,7 +492,7 @@ void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
484492
auto current_appid = proc::proc.running();
485493
tree.put("root.PairStatus", pair_status);
486494
tree.put("root.currentgame", current_appid >= 0 ? current_appid + 1 : 0);
487-
tree.put("root.state", "_SERVER_BUSY");
495+
tree.put("root.state", current_appid >= 0 ? "_SERVER_BUSY" : "_SERVER_FREE");
488496

489497
std::ostringstream data;
490498

@@ -522,7 +530,7 @@ void applist(resp_https_t response, req_https_t request) {
522530
for(auto &proc : proc::proc.get_apps()) {
523531
pt::ptree app;
524532

525-
app.put("IsHdrSupported"s, config::video.hevc_mode == 2 ? 1 : 0);
533+
app.put("IsHdrSupported"s, config::video.hevc_mode == 3 ? 1 : 0);
526534
app.put("AppTitle"s, proc.name);
527535
app.put("ID"s, ++x);
528536

0 commit comments

Comments
 (0)