Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,26 @@ updates:
target-branch: "nightly"
open-pull-requests-limit: 10

- package-ecosystem: "pip"
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"
time: "09:30"
target-branch: "nightly"
open-pull-requests-limit: 10

- package-ecosystem: "gitsubmodule"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
time: "10:00"
target-branch: "nightly"
open-pull-requests-limit: 10

- package-ecosystem: "gitsubmodule"
directory: "/"
schedule:
interval: "daily"
time: "10:30"
target-branch: "nightly"
open-pull-requests-limit: 10
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ jobs:
runs-on: windows-latest # the required action can only be run on Windows
steps:
- name: Release to WinGet
uses: vedantmgoyal2009/winget-releaser@v1
uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: LizardByte.Sunshine
release-tag: ${{ needs.setup_release.outputs.release_tag }}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ jobs:
- name: Build artifacts
if: ${{ steps.prepare.outputs.artifacts == 'true' }}
id: build_artifacts
uses: docker/build-push-action@v3
uses: docker/build-push-action@v4
with:
context: ./
file: ${{ matrix.dockerfile }}
Expand All @@ -334,7 +334,7 @@ jobs:

- name: Build and push
id: build
uses: docker/build-push-action@v3
uses: docker/build-push-action@v4
with:
context: ./
file: ${{ matrix.dockerfile }}
Expand Down Expand Up @@ -362,7 +362,7 @@ jobs:
if: ${{ steps.prepare.outputs.artifacts == 'true' }}
uses: actions/upload-artifact@v3
with:
name: sunshine${{ matrix.tag }}
name: Docker${{ matrix.tag }}
path: artifacts/

- name: Create/Update GitHub Release
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## [0.18.2] - 2023-02-13
### Fixed
- (Video/KMV/Linux) Fixed wayland capture on Nvidia for KMS
- (Video/Linux) Implement vaSyncBuffer stuf for libva <2.9.0
- (UI) Fix issue where mime type was not being set for node_modules when using a reverse proxy
- (UI/macOS) Added missing audio sink config options
- (Linux) Specify correct Boost dependency versions
- (Video/AMF) Add missing encoder tunables

## [0.18.1] - 2023-01-31
### Fixed
- (Linux) Fixed missing dependencies for deb and rpm packages
Expand Down Expand Up @@ -307,3 +316,4 @@ settings. In v0.17.0, games now run under your user account without elevated pri
[0.17.0]: https://github.com/LizardByte/Sunshine/releases/tag/v0.17.0
[0.18.0]: https://github.com/LizardByte/Sunshine/releases/tag/v0.18.0
[0.18.1]: https://github.com/LizardByte/Sunshine/releases/tag/v0.18.1
[0.18.2]: https://github.com/LizardByte/Sunshine/releases/tag/v0.18.2
18 changes: 9 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.18)
# `CMAKE_CUDA_ARCHITECTURES` requires 3.18

project(Sunshine VERSION 0.18.1
project(Sunshine VERSION 0.18.2
DESCRIPTION "Sunshine is a self-hosted game stream host for Moonlight."
HOMEPAGE_URL "https://app.lizardbyte.dev")

Expand Down Expand Up @@ -789,10 +789,10 @@ elseif(UNIX)
set(CPACK_DEB_COMPONENT_INSTALL ON)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "\
${CPACK_DEB_PLATFORM_PACKAGE_DEPENDS} \
libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, \
libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, \
libboost-program-options1.67.0 | libboost-program-options1.71.0 | libboost-program-options1.74.0, \
libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, \
libboost-filesystem${Boost_VERSION}, \
libboost-log${Boost_VERSION}, \
libboost-program-options${Boost_VERSION}, \
libboost-thread${Boost_VERSION}, \
libcap2, \
libcurl4, \
libdrm2, \
Expand All @@ -808,10 +808,10 @@ elseif(UNIX)
openssl | libssl3")
set(CPACK_RPM_PACKAGE_REQUIRES "\
${CPACK_RPM_PLATFORM_PACKAGE_REQUIRES} \
boost-filesystem >= 1.67.0, \
boost-log >= 1.67.0, \
boost-program-options >= 1.67.0, \
boost-thread >= 1.67.0, \
boost-filesystem >= ${Boost_VERSION}, \
boost-log >= ${Boost_VERSION}, \
boost-program-options >= ${Boost_VERSION}, \
boost-thread >= ${Boost_VERSION}, \
libcap >= 2.22, \
libcurl >= 7.0, \
libdrm >= 2.4.97, \
Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
furo==2022.12.7
m2r2==0.3.3
m2r2==0.3.3.post2
Sphinx==6.1.3
sphinx-copybutton==0.5.1
62 changes: 62 additions & 0 deletions docs/source/about/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,68 @@ amd_rc

amd_rc = vbr_latency

amd_usage
^^^^^^^^^

**Description**
The encoder usage profile, used to balance latency with encoding quality.

.. Note:: This option only applies when using amdvce `encoder`_.

**Choices**

.. table::
:widths: auto

=============== ===========
Value Description
=============== ===========
transcoding transcoding (slowest)
webcam webcam (slow)
lowlatency low latency (fast)
ultralowlatency ultra low latency (fastest)
=============== ===========

**Default**
``ultralowlatency``

**Example**
.. code-block:: text

amd_usage = ultralowlatency

amd_preanalysis
^^^^^^^^^^^^^^^

**Description**
Preanalysis can increase encoding quality at the cost of latency.

.. Note:: This option only applies when using amdvce `encoder`_.

**Default**
``disabled``

**Example**
.. code-block:: text

amd_preanalysis = disabled

amd_vbaq
^^^^^^^^

**Description**
Variance Based Adaptive Quantization (VBAQ) can increase subjective visual quality.

.. Note:: This option only applies when using amdvce `encoder`_.

**Default**
``enabled``

**Example**
.. code-block:: text

amd_vbaq = enabled

amd_coder
^^^^^^^^^

Expand Down
3 changes: 1 addition & 2 deletions docs/source/about/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ macOS
^^^^^
Sunshine can only access microphones on macOS due to system limitations. To stream system audio use
`Soundflower <https://github.com/mattingalls/Soundflower>`_ or
`BlackHole <https://github.com/ExistentialAudio/BlackHole>`_ and
select their sink as audio device in `sunshine.conf`.
`BlackHole <https://github.com/ExistentialAudio/BlackHole>`_.

.. Note:: Command Keys are not forwarded by Moonlight. Right Option-Key is mapped to CMD-Key.

Expand Down
59 changes: 53 additions & 6 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ namespace amd {
#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR 1
#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR 2
#define AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR 3
#define AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING 0
#define AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY 1
#define AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY 2
#define AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM 3
#define AMF_VIDEO_ENCODER_USAGE_TRANSCONDING 0
#define AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY 1
#define AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY 2
#define AMF_VIDEO_ENCODER_USAGE_WEBCAM 3
#define AMF_VIDEO_ENCODER_UNDEFINED 0
#define AMF_VIDEO_ENCODER_CABAC 1
#define AMF_VIDEO_ENCODER_CALV 2
Expand Down Expand Up @@ -164,6 +172,20 @@ enum class rc_h264_e : int {
cbr = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR
};

enum class usage_hevc_e : int {
transcoding = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING,
webcam = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM,
lowlatency = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY,
ultralowlatency = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY
};

enum class usage_h264_e : int {
transcoding = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING,
webcam = AMF_VIDEO_ENCODER_USAGE_WEBCAM,
lowlatency = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY,
ultralowlatency = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY
};

enum coder_e : int {
_auto = AMF_VIDEO_ENCODER_UNDEFINED,
cabac = AMF_VIDEO_ENCODER_CABAC,
Expand Down Expand Up @@ -191,6 +213,17 @@ std::optional<int> rc_from_view(const std::string_view &rc, int codec) {
return std::nullopt;
}

std::optional<int> usage_from_view(const std::string_view &rc, int codec) {
#define _CONVERT_(x) \
if(rc == #x##sv) return codec == 0 ? (int)usage_hevc_e::x : (int)usage_h264_e::x
_CONVERT_(transcoding);
_CONVERT_(webcam);
_CONVERT_(lowlatency);
_CONVERT_(ultralowlatency);
#undef _CONVERT_
return std::nullopt;
}

int coder_from_view(const std::string_view &coder) {
if(coder == "auto"sv) return _auto;
if(coder == "cabac"sv || coder == "ac"sv) return cabac;
Expand Down Expand Up @@ -300,12 +333,16 @@ video_t video {
}, // qsv

{
(int)amd::quality_h264_e::balanced, // quality (h264)
(int)amd::quality_hevc_e::balanced, // quality (hevc)
(int)amd::rc_h264_e::vbr_latency, // rate control (h264)
(int)amd::rc_hevc_e::vbr_latency, // rate control (hevc)
(int)amd::coder_e::_auto, // coder
}, // amd
(int)amd::quality_h264_e::balanced, // quality (h264)
(int)amd::quality_hevc_e::balanced, // quality (hevc)
(int)amd::rc_h264_e::vbr_latency, // rate control (h264)
(int)amd::rc_hevc_e::vbr_latency, // rate control (hevc)
(int)amd::usage_h264_e::ultralowlatency, // usage (h264)
(int)amd::usage_hevc_e::ultralowlatency, // usage (hevc)
0, // preanalysis
1, // vbaq
(int)amd::coder_e::_auto, // coder
}, // amd

{
0,
Expand Down Expand Up @@ -826,6 +863,16 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
video.amd.rc_hevc = amd::rc_from_view(rc, 0);
}

std::string usage;
string_f(vars, "amd_usage", usage);
if(!usage.empty()) {
video.amd.usage_h264 = amd::usage_from_view(rc, 1);
video.amd.usage_hevc = amd::usage_from_view(rc, 0);
}

bool_f(vars, "amd_preanalysis", (bool &)video.amd.preanalysis);
bool_f(vars, "amd_vbaq", (bool &)video.amd.vbaq);

int_f(vars, "vt_coder", video.vt.coder, vt::coder_from_view);
int_f(vars, "vt_software", video.vt.allow_sw, vt::allow_software_from_view);
int_f(vars, "vt_software", video.vt.require_sw, vt::force_software_from_view);
Expand Down
4 changes: 4 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ struct video_t {
std::optional<int> quality_hevc;
std::optional<int> rc_h264;
std::optional<int> rc_hevc;
std::optional<int> usage_h264;
std::optional<int> usage_hevc;
std::optional<int> preanalysis;
std::optional<int> vbaq;
int coder;
} amd;

Expand Down
22 changes: 14 additions & 8 deletions src/confighttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ void not_found(resp_https_t response, req_https_t request) {
<< data.str();
}

// todo - combine these functions into a single function that accepts the page, i.e "index", "pin", "apps"
void getIndexPage(resp_https_t response, req_https_t request) {
if(!authenticate(response, request)) return;

Expand Down Expand Up @@ -229,6 +230,8 @@ void getTroubleshootingPage(resp_https_t response, req_https_t request) {
}

void getFaviconImage(resp_https_t response, req_https_t request) {
// todo - combine function with getSunshineLogoImage and possibly getNodeModules
// todo - use mime_types map
print_req(request);

std::ifstream in(WEB_DIR "images/favicon.ico", std::ios::binary);
Expand All @@ -238,6 +241,8 @@ void getFaviconImage(resp_https_t response, req_https_t request) {
}

void getSunshineLogoImage(resp_https_t response, req_https_t request) {
// todo - combine function with getFaviconImage and possibly getNodeModules
// todo - use mime_types map
print_req(request);

std::ifstream in(WEB_DIR "images/logo-sunshine-45.png", std::ios::binary);
Expand Down Expand Up @@ -269,17 +274,18 @@ void getNodeModules(resp_https_t response, req_https_t request) {
}
else {
auto relPath = fs::relative(filePath, webDirPath);
if(relPath.extension() == ".ttf" or relPath.extension() == ".woff2") {
// Fonts are read differntly
// get the mime type from the file extension mime_types map
// remove the leading period from the extension
auto mimeType = mime_types.find(relPath.extension().string().substr(1));
// check if the extension is in the map at the x position
if(mimeType != mime_types.end()) {
// if it is, set the content type to the mime type
SimpleWeb::CaseInsensitiveMultimap headers;
std::ifstream in((filePath).c_str(), std::ios::binary);
headers.emplace("Content-Type", "font/" + filePath.extension().string().substr(1));
headers.emplace("Content-Type", mimeType->second);
std::ifstream in(filePath.string(), std::ios::binary);
response->write(SimpleWeb::StatusCode::success_ok, in, headers);
}
else {
std::string content = read_file((filePath.string()).c_str());
response->write(content);
}
// do not return any file if the type is not in the map
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/confighttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,23 @@ constexpr auto PORT_HTTPS = 1;
void start();
} // namespace confighttp

// mime types map
const std::map<std::string, std::string> mime_types = {
{ "css", "text/css" },
{ "gif", "image/gif" },
{ "htm", "text/html" },
{ "html", "text/html" },
{ "ico", "image/x-icon" },
{ "jpeg", "image/jpeg" },
{ "jpg", "image/jpeg" },
{ "js", "application/javascript" },
{ "json", "application/json" },
{ "png", "image/png" },
{ "svg", "image/svg+xml" },
{ "ttf", "font/ttf" },
{ "txt", "text/plain" },
{ "woff2", "font/woff2" },
{ "xml", "text/xml" },
};

#endif // SUNSHINE_CONFIGHTTP_H
Loading