diff --git a/assets/sunshine.conf b/assets/sunshine.conf
index 1b82910e..103f44b0 100644
--- a/assets/sunshine.conf
+++ b/assets/sunshine.conf
@@ -78,7 +78,7 @@
# ]
# How long to wait in milliseconds for data from moonlight before shutting down the stream
-# ping_timeout = 2000
+# ping_timeout = 10000
# The file where configuration for the different applications that Sunshine can run during a stream
# file_apps = apps.json
diff --git a/assets/web/config.html b/assets/web/config.html
index a4a39c58..f9c5380f 100644
--- a/assets/web/config.html
+++ b/assets/web/config.html
@@ -55,7 +55,7 @@
Ping Timeout
-
How long to wait in milliseconds for data from moonlight before shutting down the
stream
@@ -528,7 +528,7 @@
}
if (this.platform == "linux") {
this.tabs = this.tabs.filter(el => {
- return el.id !== "nv" && el.id !== "amd";
+ return el.id !== "amd";
});
}
diff --git a/sunshine/config.cpp b/sunshine/config.cpp
index b7c258f3..f8cc735d 100644
--- a/sunshine/config.cpp
+++ b/sunshine/config.cpp
@@ -176,7 +176,7 @@ video_t video {
audio_t audio {};
stream_t stream {
- 2s, // ping_timeout
+ 10s, // ping_timeout
APPS_JSON_PATH,
diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp
index bef7cd67..cffc65dd 100644
--- a/sunshine/nvhttp.cpp
+++ b/sunshine/nvhttp.cpp
@@ -34,7 +34,7 @@ using namespace std::literals;
namespace nvhttp {
constexpr auto VERSION = "7.1.431.0";
-constexpr auto GFE_VERSION = "3.12.0.1";
+constexpr auto GFE_VERSION = "3.23.0.74";
namespace fs = std::filesystem;
namespace pt = boost::property_tree;
diff --git a/sunshine/platform/common.h b/sunshine/platform/common.h
index e866ce4b..0699d886 100644
--- a/sunshine/platform/common.h
+++ b/sunshine/platform/common.h
@@ -75,6 +75,7 @@ enum class mem_type_e {
system,
vaapi,
dxgi,
+ cuda,
unknown
};
diff --git a/sunshine/platform/linux/display.cpp b/sunshine/platform/linux/display.cpp
index 867220d3..188974b0 100644
--- a/sunshine/platform/linux/display.cpp
+++ b/sunshine/platform/linux/display.cpp
@@ -372,7 +372,7 @@ struct shm_attr_t : public x11_attr_t {
};
std::shared_ptr
display(platf::mem_type_e hwdevice_type) {
- if(hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::vaapi) {
+ if(hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::vaapi && hwdevice_type != platf::mem_type_e::cuda) {
BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv;
return nullptr;
}
diff --git a/sunshine/stream.cpp b/sunshine/stream.cpp
index 5352eeed..07aa4b3f 100644
--- a/sunshine/stream.cpp
+++ b/sunshine/stream.cpp
@@ -512,11 +512,14 @@ std::vector replace(const std::string_view &original, const std::string
std::vector replaced;
auto begin = std::begin(original);
- auto next = std::search(begin, std::end(original), std::begin(old), std::end(old));
+ auto end = std::end(original);
+ auto next = std::search(begin, end, std::begin(old), std::end(old));
std::copy(begin, next, std::back_inserter(replaced));
- std::copy(std::begin(_new), std::end(_new), std::back_inserter(replaced));
- std::copy(next + old.size(), std::end(original), std::back_inserter(replaced));
+ if(next != end) {
+ std::copy(std::begin(_new), std::end(_new), std::back_inserter(replaced));
+ std::copy(next + old.size(), end, std::back_inserter(replaced));
+ }
return replaced;
}
@@ -928,7 +931,7 @@ void videoBroadcastThread(udp::socket &sock) {
inspect->packet.flags |= FLAG_EOF;
}
- inspect->rtp.header = FLAG_EXTENSION;
+ inspect->rtp.header = 0x80 | FLAG_EXTENSION;
inspect->rtp.sequenceNumber = util::endian::big(lowseq + x);
}
diff --git a/sunshine/video.cpp b/sunshine/video.cpp
index 8313fb0c..59f3a1ec 100644
--- a/sunshine/video.cpp
+++ b/sunshine/video.cpp
@@ -71,6 +71,7 @@ platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt);
util::Either dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx);
util::Either vaapi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx);
+util::Either cuda_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx);
int hwframe_ctx(ctx_t &ctx, buffer_t &hwdevice, AVPixelFormat format);
@@ -402,12 +403,16 @@ void end_capture_async(capture_thread_async_ctx_t &ctx);
auto capture_thread_async = safe::make_shared(start_capture_async, end_capture_async);
auto capture_thread_sync = safe::make_shared(start_capture_sync, end_capture_sync);
-#ifdef _WIN32
static encoder_t nvenc {
"nvenc"sv,
{ (int)nv::profile_h264_e::high, (int)nv::profile_hevc_e::main, (int)nv::profile_hevc_e::main_10 },
+#ifdef _WIN32
AV_HWDEVICE_TYPE_D3D11VA,
AV_PIX_FMT_D3D11,
+#else
+ AV_HWDEVICE_TYPE_CUDA,
+ AV_PIX_FMT_CUDA,
+#endif
AV_PIX_FMT_NV12, AV_PIX_FMT_P010,
{
{
@@ -432,10 +437,16 @@ static encoder_t nvenc {
std::make_optional({ "qp"s, &config::video.qp }),
"h264_nvenc"s,
},
+#ifdef _WIN32
DEFAULT,
dxgi_make_hwdevice_ctx
+#else
+ SYSTEM_MEMORY,
+ cuda_make_hwdevice_ctx
+#endif
};
+#ifdef _WIN32
static encoder_t amdvce {
"amdvce"sv,
{ FF_PROFILE_H264_HIGH, FF_PROFILE_HEVC_MAIN },
@@ -537,8 +548,8 @@ static encoder_t vaapi {
#endif
static std::vector encoders {
-#ifdef _WIN32
nvenc,
+#ifdef _WIN32
amdvce,
#endif
#ifdef __linux__
@@ -1649,6 +1660,19 @@ util::Either vaapi_make_hwdevice_ctx(platf::hwdevice_t *base) {
return hw_device_buf;
}
+util::Either cuda_make_hwdevice_ctx(platf::hwdevice_t *base) {
+ buffer_t hw_device_buf;
+
+ auto status = av_hwdevice_ctx_create(&hw_device_buf, AV_HWDEVICE_TYPE_CUDA, nullptr, nullptr, 0);
+ if(status < 0) {
+ char string[AV_ERROR_MAX_STRING_SIZE];
+ BOOST_LOG(error) << "Failed to create a CUDA device: "sv << av_make_error_string(string, AV_ERROR_MAX_STRING_SIZE, status);
+ return -1;
+ }
+
+ return hw_device_buf;
+}
+
#ifdef _WIN32
}
@@ -1716,7 +1740,9 @@ platf::mem_type_e map_dev_type(AVHWDeviceType type) {
return platf::mem_type_e::dxgi;
case AV_HWDEVICE_TYPE_VAAPI:
return platf::mem_type_e::vaapi;
- case AV_PICTURE_TYPE_NONE:
+ case AV_HWDEVICE_TYPE_CUDA:
+ return platf::mem_type_e::cuda;
+ case AV_HWDEVICE_TYPE_NONE:
return platf::mem_type_e::system;
default:
return platf::mem_type_e::unknown;