diff --git a/src/config.cpp b/src/config.cpp index 45d354ad..034e2cbb 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -307,15 +307,6 @@ audio_t audio{ true, // install_steam_drivers }; -stream_t stream{ - 10s, // ping_timeout - - APPS_JSON_PATH, - - 20, // fecPercentage - 1 // channels -}; - sunshine_t sunshine{ 2, // min_log_level 0, // flags @@ -331,572 +322,6 @@ sunshine_t sunshine{ {}, // prep commands }; -bool endline(char ch) { return ch == '\r' || ch == '\n'; } -bool space_tab(char ch) { return ch == ' ' || ch == '\t'; } -bool whitespace(char ch) { return space_tab(ch) || endline(ch); } - -std::string to_string(const char *begin, const char *end) { - std::string result; - - KITTY_WHILE_LOOP(auto pos = begin, pos != end, { - auto comment = std::find(pos, end, '#'); - auto endl = std::find_if(comment, end, endline); - - result.append(pos, comment); - - pos = endl; - }) - - return result; -} - -template -It skip_list(It skipper, It end) { - int stack = 1; - while (skipper != end && stack) { - if (*skipper == '[') { - ++stack; - } - if (*skipper == ']') { - --stack; - } - - ++skipper; - } - - return skipper; -} - -std::pair>> -parse_option(std::string_view::const_iterator begin, - std::string_view::const_iterator end) { - begin = std::find_if_not(begin, end, whitespace); - auto endl = std::find_if(begin, end, endline); - auto endc = std::find(begin, endl, '#'); - endc = - std::find_if(std::make_reverse_iterator(endc), - std::make_reverse_iterator(begin), std::not_fn(whitespace)) - .base(); - - auto eq = std::find(begin, endc, '='); - if (eq == endc || eq == begin) { - return std::make_pair(endl, std::nullopt); - } - - auto end_name = - std::find_if_not(std::make_reverse_iterator(eq), - std::make_reverse_iterator(begin), space_tab) - .base(); - auto begin_val = std::find_if_not(eq + 1, endc, space_tab); - - if (begin_val == endl) { - return std::make_pair(endl, std::nullopt); - } - - // Lists might contain newlines - if (*begin_val == '[') { - endl = skip_list(begin_val + 1, end); - if (endl == end) { - std::cout << "Warning: Config option ["sv - << to_string(begin, end_name) << "] Missing ']'"sv; - - return std::make_pair(endl, std::nullopt); - } - } - - return std::make_pair(endl, std::make_pair(to_string(begin, end_name), - to_string(begin_val, endl))); -} - -void string_f(std::unordered_map &vars, - const std::string &name, std::string &input) { - auto it = vars.find(name); - if (it == std::end(vars)) { - return; - } - - input = std::move(it->second); - - vars.erase(it); -} - -template -void generic_f(std::unordered_map &vars, - const std::string &name, T &input, F &&f) { - std::string tmp; - string_f(vars, name, tmp); - if (!tmp.empty()) { - input = f(tmp); - } -} - -void string_restricted_f(std::unordered_map &vars, - const std::string &name, std::string &input, - const std::vector &allowed_vals) { - std::string temp; - string_f(vars, name, temp); - - for (auto &allowed_val : allowed_vals) { - if (temp == allowed_val) { - input = std::move(temp); - return; - } - } -} - -void path_f(std::unordered_map &vars, - const std::string &name, fs::path &input) { - // appdata needs to be retrieved once only - static auto appdata = platf::appdata(); - - std::string temp; - string_f(vars, name, temp); - - if (!temp.empty()) { - input = temp; - } - - if (input.is_relative()) { - input = appdata / input; - } - - auto dir = input; - dir.remove_filename(); - - // Ensure the directories exists - if (!fs::exists(dir)) { - fs::create_directories(dir); - } -} - -void path_f(std::unordered_map &vars, - const std::string &name, std::string &input) { - fs::path temp = input; - - path_f(vars, name, temp); - - input = temp.string(); -} - -void int_f(std::unordered_map &vars, - const std::string &name, int &input) { - auto it = vars.find(name); - - if (it == std::end(vars)) { - return; - } - - std::string_view val = it->second; - - // If value is something like: "756" instead of 756 - if (val.size() >= 2 && val[0] == '"') { - val = val.substr(1, val.size() - 2); - } - - // If that integer is in hexadecimal - if (val.size() >= 2 && val.substr(0, 2) == "0x"sv) { - input = util::from_hex(val.substr(2)); - } else { - input = util::from_view(val); - } - - vars.erase(it); -} - -void int_f(std::unordered_map &vars, - const std::string &name, std::optional &input) { - auto it = vars.find(name); - - if (it == std::end(vars)) { - return; - } - - std::string_view val = it->second; - - // If value is something like: "756" instead of 756 - if (val.size() >= 2 && val[0] == '"') { - val = val.substr(1, val.size() - 2); - } - - // If that integer is in hexadecimal - if (val.size() >= 2 && val.substr(0, 2) == "0x"sv) { - input = util::from_hex(val.substr(2)); - } else { - input = util::from_view(val); - } - - vars.erase(it); -} - -template -void int_f(std::unordered_map &vars, - const std::string &name, int &input, F &&f) { - std::string tmp; - string_f(vars, name, tmp); - if (!tmp.empty()) { - input = f(tmp); - } -} - -template -void int_f(std::unordered_map &vars, - const std::string &name, std::optional &input, F &&f) { - std::string tmp; - string_f(vars, name, tmp); - if (!tmp.empty()) { - input = f(tmp); - } -} - -void int_between_f(std::unordered_map &vars, - const std::string &name, int &input, - const std::pair &range) { - int temp = input; - - int_f(vars, name, temp); - - TUPLE_2D_REF(lower, upper, range); - if (temp >= lower && temp <= upper) { - input = temp; - } -} - -bool to_bool(std::string &boolean) { - std::for_each(std::begin(boolean), std::end(boolean), - [](char ch) { return (char)std::tolower(ch); }); - - return boolean == "true"sv || boolean == "yes"sv || boolean == "enable"sv || - boolean == "enabled"sv || boolean == "on"sv || - (std::find(std::begin(boolean), std::end(boolean), '1') != - std::end(boolean)); -} - -void bool_f(std::unordered_map &vars, - const std::string &name, bool &input) { - std::string tmp; - string_f(vars, name, tmp); - - if (tmp.empty()) { - return; - } - - input = to_bool(tmp); -} - -void double_f(std::unordered_map &vars, - const std::string &name, double &input) { - std::string tmp; - string_f(vars, name, tmp); - - if (tmp.empty()) { - return; - } - - char *c_str_p; - auto val = std::strtod(tmp.c_str(), &c_str_p); - - if (c_str_p == tmp.c_str()) { - return; - } - - input = val; -} - -void double_between_f(std::unordered_map &vars, - const std::string &name, double &input, - const std::pair &range) { - double temp = input; - - double_f(vars, name, temp); - - TUPLE_2D_REF(lower, upper, range); - if (temp >= lower && temp <= upper) { - input = temp; - } -} - -void list_string_f(std::unordered_map &vars, - const std::string &name, std::vector &input) { - std::string string; - string_f(vars, name, string); - - if (string.empty()) { - return; - } - - input.clear(); - - auto begin = std::cbegin(string); - if (*begin == '[') { - ++begin; - } - - begin = std::find_if_not(begin, std::cend(string), whitespace); - if (begin == std::cend(string)) { - return; - } - - auto pos = begin; - while (pos < std::cend(string)) { - if (*pos == '[') { - pos = skip_list(pos + 1, std::cend(string)) + 1; - } else if (*pos == ']') { - break; - } else if (*pos == ',') { - input.emplace_back(begin, pos); - pos = begin = - std::find_if_not(pos + 1, std::cend(string), whitespace); - } else { - ++pos; - } - } - - if (pos != begin) { - input.emplace_back(begin, pos); - } -} - -void list_int_f(std::unordered_map &vars, - const std::string &name, std::vector &input) { - std::vector list; - list_string_f(vars, name, list); - - for (auto &el : list) { - std::string_view val = el; - - // If value is something like: "756" instead of 756 - if (val.size() >= 2 && val[0] == '"') { - val = val.substr(1, val.size() - 2); - } - - int tmp; - - // If the integer is a hexadecimal - if (val.size() >= 2 && val.substr(0, 2) == "0x"sv) { - tmp = util::from_hex(val.substr(2)); - } else { - tmp = util::from_view(val); - } - input.emplace_back(tmp); - } -} - -void map_int_int_f(std::unordered_map &vars, - const std::string &name, - std::unordered_map &input) { - std::vector list; - list_int_f(vars, name, list); - - // The list needs to be a multiple of 2 - if (list.size() % 2) { - std::cout << "Warning: expected "sv << name - << " to have a multiple of two elements --> not "sv - << list.size() << std::endl; - return; - } - - int x = 0; - while (x < list.size()) { - auto key = list[x++]; - auto val = list[x++]; - - input.emplace(key, val); - } -} - -int apply_flags(const char *line) { - int ret = 0; - while (*line != '\0') { - switch (*line) { - case '0': - config::sunshine.flags[config::flag::PIN_STDIN].flip(); - break; - case '1': - config::sunshine.flags[config::flag::FRESH_STATE].flip(); - break; - case '2': - config::sunshine.flags[config::flag::FORCE_VIDEO_HEADER_REPLACE] - .flip(); - break; - case 'p': - config::sunshine.flags[config::flag::UPNP].flip(); - break; - default: - std::cout << "Warning: Unrecognized flag: ["sv << *line << ']' - << std::endl; - ret = -1; - } - - ++line; - } - - return ret; -} - -void apply_config(std::unordered_map &&vars) { - if (!fs::exists(stream.file_apps.c_str())) { - fs::copy_file(SUNSHINE_ASSETS_DIR "/apps.json", stream.file_apps); - } - - for (auto &[name, val] : vars) { - std::cout << "["sv << name << "] -- ["sv << val << ']' << std::endl; - } - - int_f(vars, "qp", video.qp); - int_f(vars, "min_threads", video.min_threads); - int_between_f(vars, "hevc_mode", video.hevc_mode, {0, 3}); - int_between_f(vars, "av1_mode", video.av1_mode, {0, 3}); - string_f(vars, "sw_preset", video.sw.sw_preset); - if (!video.sw.sw_preset.empty()) { - video.sw.svtav1_preset = - sw::svtav1_preset_from_view(video.sw.sw_preset); - } - string_f(vars, "sw_tune", video.sw.sw_tune); - - int_between_f(vars, "nvenc_preset", video.nv.quality_preset, {1, 7}); - generic_f(vars, "nvenc_twopass", video.nv.two_pass, nv::twopass_from_view); - bool_f(vars, "nvenc_h264_cavlc", video.nv.h264_cavlc); - bool_f(vars, "nvenc_realtime_hags", video.nv_realtime_hags); - - video.nv_legacy.preset = video.nv.quality_preset + 11; - video.nv_legacy.multipass = - video.nv.two_pass == nvenc::nvenc_two_pass::quarter_resolution - ? NV_ENC_TWO_PASS_QUARTER_RESOLUTION - : video.nv.two_pass == nvenc::nvenc_two_pass::full_resolution - ? NV_ENC_TWO_PASS_FULL_RESOLUTION - : NV_ENC_MULTI_PASS_DISABLED; - video.nv_legacy.h264_coder = video.nv.h264_cavlc - ? NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC - : NV_ENC_H264_ENTROPY_CODING_MODE_CABAC; - - int_f(vars, "qsv_preset", video.qsv.qsv_preset, qsv::preset_from_view); - int_f(vars, "qsv_coder", video.qsv.qsv_cavlc, qsv::coder_from_view); - - std::string quality; - string_f(vars, "amd_quality", quality); - if (!quality.empty()) { - video.amd.amd_quality_h264 = - amd::quality_from_view(quality); - video.amd.amd_quality_hevc = - amd::quality_from_view(quality); - video.amd.amd_quality_av1 = - amd::quality_from_view(quality); - } - - std::string rc; - string_f(vars, "amd_rc", rc); - int_f(vars, "amd_coder", video.amd.amd_coder, amd::coder_from_view); - if (!rc.empty()) { - video.amd.amd_rc_h264 = amd::rc_from_view(rc); - video.amd.amd_rc_hevc = amd::rc_from_view(rc); - video.amd.amd_rc_av1 = amd::rc_from_view(rc); - } - - std::string usage; - string_f(vars, "amd_usage", usage); - if (!usage.empty()) { - video.amd.amd_usage_h264 = amd::usage_from_view(rc); - video.amd.amd_usage_hevc = amd::usage_from_view(rc); - video.amd.amd_usage_av1 = amd::usage_from_view(rc); - } - - bool_f(vars, "amd_preanalysis", (bool &)video.amd.amd_preanalysis); - bool_f(vars, "amd_vbaq", (bool &)video.amd.amd_vbaq); - - int_f(vars, "vt_coder", video.vt.vt_coder, vt::coder_from_view); - int_f(vars, "vt_software", video.vt.vt_allow_sw, - vt::allow_software_from_view); - int_f(vars, "vt_software", video.vt.vt_require_sw, - vt::force_software_from_view); - int_f(vars, "vt_realtime", video.vt.vt_realtime, vt::rt_from_view); - - string_f(vars, "capture", video.capture); - string_f(vars, "encoder", video.encoder); - string_f(vars, "adapter_name", video.adapter_name); - string_f(vars, "output_name", video.output_name); - - path_f(vars, "log_path", config::sunshine.log_file); - - // Must be run after "file_state" - path_f(vars, "credentials_file", config::sunshine.credentials_file); - - string_f(vars, "audio_sink", audio.sink); - string_f(vars, "virtual_sink", audio.virtual_sink); - bool_f(vars, "install_steam_audio_drivers", audio.install_steam_drivers); - - int to = -1; - int_between_f(vars, "ping_timeout", to, - {-1, std::numeric_limits::max()}); - if (to != -1) { - stream.ping_timeout = std::chrono::milliseconds(to); - } - - int_between_f(vars, "channels", stream.channels, - {1, std::numeric_limits::max()}); - - path_f(vars, "file_apps", stream.file_apps); - int_between_f(vars, "fec_percentage", stream.fec_percentage, {1, 255}); - - // This config option will only be used by the UI - // When editing in the config file itself, use "keybindings" - bool map_rightalt_to_win = false; - bool_f(vars, "key_rightalt_to_key_win", map_rightalt_to_win); - - int port = sunshine.port; - sunshine.port = (std::uint16_t)port; - - string_restricted_f(vars, "address_family", sunshine.address_family, - {"ipv4"sv, "both"sv}); - - bool upnp = false; - bool_f(vars, "upnp"s, upnp); - - if (upnp) { - config::sunshine.flags[config::flag::UPNP].flip(); - } - - std::string log_level_string; - string_f(vars, "min_log_level", log_level_string); - - if (!log_level_string.empty()) { - if (log_level_string == "verbose"sv) { - sunshine.min_log_level = 0; - } else if (log_level_string == "debug"sv) { - sunshine.min_log_level = 1; - } else if (log_level_string == "info"sv) { - sunshine.min_log_level = 2; - } else if (log_level_string == "warning"sv) { - sunshine.min_log_level = 3; - } else if (log_level_string == "error"sv) { - sunshine.min_log_level = 4; - } else if (log_level_string == "fatal"sv) { - sunshine.min_log_level = 5; - } else if (log_level_string == "none"sv) { - sunshine.min_log_level = 6; - } else { - // accept digit directly - auto val = log_level_string[0]; - if (val >= '0' && val < '7') { - sunshine.min_log_level = val - '0'; - } - } - } - - auto it = vars.find("flags"s); - if (it != std::end(vars)) { - apply_flags(it->second.c_str()); - - vars.erase(it); - } - - if (sunshine.min_log_level <= 3) { - for (auto &[var, _] : vars) { - std::cout << "Warning: Unrecognized configurable option ["sv << var - << ']' << std::endl; - } - } -} } // namespace config diff --git a/src/config.h b/src/config.h index bd113473..7b4abb7b 100644 --- a/src/config.h +++ b/src/config.h @@ -87,22 +87,7 @@ struct stream_t { int channels; }; -struct nvhttp_t { - // Could be any of the following values: - // pc|lan|wan - std::string origin_web_ui_allowed; - std::string pkey; // must be 2048 bits - std::string cert; // must be signed with a key of 2048 bits - - std::string sunshine_name; - - std::string file_state; - - std::string external_ip; - std::vector resolutions; - std::vector fps; -}; namespace flag { enum flag_e : std::size_t { @@ -153,7 +138,5 @@ struct sunshine_t { extern video_t video; extern audio_t audio; -extern stream_t stream; -extern nvhttp_t nvhttp; extern sunshine_t sunshine; } // namespace config diff --git a/src/nvenc/nvenc_base.cpp b/src/nvenc/nvenc_base.cpp index d139c01f..bc4bdbb8 100644 --- a/src/nvenc/nvenc_base.cpp +++ b/src/nvenc/nvenc_base.cpp @@ -534,19 +534,7 @@ nvenc_encoded_frame nvenc_base::encode_frame(uint64_t frame_index, << last_error_string; } - // if (config::sunshine.min_log_level <= 1) { - // // Print encoded frame size stats to debug log every 20 seconds - // auto callback = [&](float stat_min, float stat_max, double stat_avg) { - // auto f = stat_trackers::one_digit_after_decimal(); - // BOOST_LOG(debug) << "NvEnc: encoded frame sizes (min max avg) " << f - // % stat_min << " " << f % stat_max << " " << f % stat_avg << " kB"; - // }; - // using namespace std::literals; - // encoder_state.frame_size_tracker.collect_and_callback_on_interval(encoded_frame.data.size() - // / 1000., callback, 20s); - // } - - return encoded_frame; + return encoded_frame; } bool nvenc_base::nvenc_failed(NVENCSTATUS status) { diff --git a/src/platform/windows/misc.cpp b/src/platform/windows/misc.cpp index 56988a2f..98cb7ff5 100644 --- a/src/platform/windows/misc.cpp +++ b/src/platform/windows/misc.cpp @@ -41,13 +41,13 @@ ProcThreadAttributeValue(13, FALSE, TRUE, FALSE) #endif -#ifndef HAS_QOS_FLOWID -typedef UINT32 QOS_FLOWID; -#endif +// #ifndef HAS_QOS_FLOWID +// typedef UINT32 QOS_FLOWID; +// #endif -#ifndef HAS_PQOS_FLOWID -typedef UINT32 *PQOS_FLOWID; -#endif +// #ifndef HAS_PQOS_FLOWID +// typedef UINT32 *PQOS_FLOWID; +// #endif #include diff --git a/src/video.cpp b/src/video.cpp index 8ab43c5f..5c90366c 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -622,8 +622,7 @@ static encoder_t amdvce{ // Common options { {"filler_data"s, false}, - {"log_to_dbg"s, - []() { return config::sunshine.min_log_level < 2 ? 1 : 0; }}, + {"log_to_dbg"s, 1 }, {"preencode"s, &config::video.amd.amd_preanalysis}, {"quality"s, &config::video.amd.amd_quality_av1}, {"rc"s, &config::video.amd.amd_rc_av1}, @@ -638,8 +637,7 @@ static encoder_t amdvce{ // Common options { {"filler_data"s, false}, - {"log_to_dbg"s, - []() { return config::sunshine.min_log_level < 2 ? 1 : 0; }}, + {"log_to_dbg"s, 1 }, {"gops_per_idr"s, 1}, {"header_insertion_mode"s, "idr"s}, {"preencode"s, &config::video.amd.amd_preanalysis}, @@ -659,8 +657,7 @@ static encoder_t amdvce{ // Common options { {"filler_data"s, false}, - {"log_to_dbg"s, - []() { return config::sunshine.min_log_level < 2 ? 1 : 0; }}, + {"log_to_dbg"s, 1 }, {"preencode"s, &config::video.amd.amd_preanalysis}, {"qmax"s, 51}, {"qmin"s, 0}, diff --git a/third-party/Simple-Web-Server b/third-party/Simple-Web-Server new file mode 160000 index 00000000..2f29926d --- /dev/null +++ b/third-party/Simple-Web-Server @@ -0,0 +1 @@ +Subproject commit 2f29926dbbcd8a0425064d98c24f37ac50bd0b5b diff --git a/third-party/TPCircularBuffer b/third-party/TPCircularBuffer new file mode 160000 index 00000000..8833b3a7 --- /dev/null +++ b/third-party/TPCircularBuffer @@ -0,0 +1 @@ +Subproject commit 8833b3a73fab6530cc51e2063a85cced01714cfb diff --git a/third-party/ViGEmClient b/third-party/ViGEmClient new file mode 160000 index 00000000..b66d02d5 --- /dev/null +++ b/third-party/ViGEmClient @@ -0,0 +1 @@ +Subproject commit b66d02d57e32cc8595369c53418b843e958649b4 diff --git a/third-party/miniupnp b/third-party/miniupnp new file mode 160000 index 00000000..e439318c --- /dev/null +++ b/third-party/miniupnp @@ -0,0 +1 @@ +Subproject commit e439318cf782e30066d430f27a1365e013a5ab94 diff --git a/third-party/moonlight-common-c b/third-party/moonlight-common-c new file mode 160000 index 00000000..f78f2135 --- /dev/null +++ b/third-party/moonlight-common-c @@ -0,0 +1 @@ +Subproject commit f78f2135fa49e19855c2028b6865657d42d511f1 diff --git a/third-party/nanors b/third-party/nanors new file mode 160000 index 00000000..395e5ada --- /dev/null +++ b/third-party/nanors @@ -0,0 +1 @@ +Subproject commit 395e5ada44dd8d5974eaf6bb6b17f23406e3ca72 diff --git a/third-party/tray b/third-party/tray new file mode 160000 index 00000000..2664388b --- /dev/null +++ b/third-party/tray @@ -0,0 +1 @@ +Subproject commit 2664388b0ed88234674a37f8cd569747522247b4