Merge remote-tracking branch 'sunshine/master'

This commit is contained in:
Yukino Song
2025-05-25 19:45:07 +08:00
6 changed files with 88 additions and 15 deletions

View File

@@ -27,6 +27,9 @@ endif()
# set the module path, used for includes # set the module path, used for includes
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# export compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# set version info for this build # set version info for this build
include(${CMAKE_MODULE_PATH}/prep/build_version.cmake) include(${CMAKE_MODULE_PATH}/prep/build_version.cmake)

View File

@@ -9,7 +9,7 @@
}, },
"dependencies": { "dependencies": {
"@lizardbyte/shared-web": "2025.326.11214", "@lizardbyte/shared-web": "2025.326.11214",
"vue": "3.5.13", "vue": "3.5.14",
"vue-i18n": "11.1.3" "vue-i18n": "11.1.3"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1327,7 +1327,7 @@ namespace stream {
void videoBroadcastThread(udp::socket &sock) { void videoBroadcastThread(udp::socket &sock) {
auto shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown); auto shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
auto packets = mail::man->queue<video::packet_t>(mail::video_packets); auto packets = mail::man->queue<video::packet_t>(mail::video_packets);
auto timebase = boost::posix_time::microsec_clock::universal_time(); auto video_epoch = std::chrono::steady_clock::now();
// Video traffic is sent on this thread // Video traffic is sent on this thread
platf::adjust_thread_priority(platf::thread_priority_e::high); platf::adjust_thread_priority(platf::thread_priority_e::high);
@@ -1523,14 +1523,20 @@ namespace stream {
size_t next_shard_to_send = 0; size_t next_shard_to_send = 0;
// RTP video timestamps use a 90 KHz clock and the frame_timestamp from when the frame was captured
// When a timestamp isn't available (duplicate frames), the timestamp from rate control is used instead.
bool frame_is_dupe = false;
if (!packet->frame_timestamp) {
packet->frame_timestamp = ratecontrol_next_frame_start;
frame_is_dupe = true;
}
using rtp_tick = std::chrono::duration<uint32_t, std::ratio<1, 90000>>;
uint32_t timestamp = std::chrono::round<rtp_tick>(*packet->frame_timestamp - video_epoch).count();
// set FEC info now that we know for sure what our percentage will be for this frame // set FEC info now that we know for sure what our percentage will be for this frame
for (auto x = 0; x < shards.size(); ++x) { for (auto x = 0; x < shards.size(); ++x) {
auto *inspect = (video_packet_raw_t *) shards.data(x); auto *inspect = (video_packet_raw_t *) shards.data(x);
// RTP video timestamps use a 90 KHz clock
auto now = boost::posix_time::microsec_clock::universal_time();
auto timestamp = (now - timebase).total_microseconds() / (1000 / 90);
inspect->packet.fecInfo = inspect->packet.fecInfo =
(x << 12 | (x << 12 |
shards.data_shards << 22 | shards.data_shards << 22 |
@@ -1622,11 +1628,11 @@ namespace stream {
frame_network_latency_logger.second_point_now_and_log(); frame_network_latency_logger.second_point_now_and_log();
if (packet->is_idr()) { BOOST_LOG(verbose) << "Sent Frame seq ["sv << packet->frame_index() << "] pts ["sv << timestamp
BOOST_LOG(verbose) << "Key Frame ["sv << packet->frame_index() << "] :: send ["sv << shards.size() << "] shards..."sv; << "] shards ["sv << shards.size() << "/"sv << shards.percentage << "%]"sv
} else { << (frame_is_dupe ? " Dupe" : "")
BOOST_LOG(verbose) << "Frame ["sv << packet->frame_index() << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl; << (packet->is_idr() ? " Key" : "")
} << (packet->after_ref_frame_invalidation ? " RFI" : "");
++blockIndex; ++blockIndex;
lowseq += shards.size(); lowseq += shards.size();
@@ -1686,6 +1692,8 @@ namespace stream {
break; break;
} }
BOOST_LOG(verbose) << "Audio [seq "sv << sequenceNumber << ", pts "sv << timestamp << "] :: send..."sv;
audio_packet.rtp.sequenceNumber = util::endian::big(sequenceNumber); audio_packet.rtp.sequenceNumber = util::endian::big(sequenceNumber);
audio_packet.rtp.timestamp = util::endian::big(timestamp); audio_packet.rtp.timestamp = util::endian::big(timestamp);
@@ -1705,7 +1713,6 @@ namespace stream {
session->localAddress, session->localAddress,
}; };
platf::send(send_info); platf::send(send_info);
BOOST_LOG(verbose) << "Audio ["sv << sequenceNumber << "] :: send..."sv;
auto &fec_packet = session->audio.fec_packet; auto &fec_packet = session->audio.fec_packet;
// initialize the FEC header at the beginning of the FEC block // initialize the FEC header at the beginning of the FEC block

View File

@@ -1,10 +1,13 @@
@echo off @echo off
setlocal enabledelayedexpansion
rem Get sunshine root directory rem Get sunshine root directory
for %%I in ("%~dp0\..") do set "ROOT_DIR=%%~fI" for %%I in ("%~dp0\..") do set "ROOT_DIR=%%~fI"
set SERVICE_NAME=ApolloService set SERVICE_NAME=ApolloService
set SERVICE_BIN="%ROOT_DIR%\tools\sunshinesvc.exe" set "SERVICE_BIN=%ROOT_DIR%\tools\sunshinesvc.exe"
set "SERVICE_CONFIG_DIR=%LOCALAPPDATA%\SudoMaker\Apollo"
set "SERVICE_CONFIG_FILE=%SERVICE_CONFIG_DIR%\service_start_type.txt"
rem Set service to demand start. It will be changed to auto later if the user selected that option. rem Set service to demand start. It will be changed to auto later if the user selected that option.
set SERVICE_START_TYPE=demand set SERVICE_START_TYPE=demand
@@ -26,8 +29,36 @@ if %ERRORLEVEL%==0 (
set SC_CMD=create set SC_CMD=create
) )
rem Check if we have a saved start type from previous installation
if exist "%SERVICE_CONFIG_FILE%" (
rem Debug output file content
type "%SERVICE_CONFIG_FILE%"
rem Read the saved start type
for /f "usebackq delims=" %%a in ("%SERVICE_CONFIG_FILE%") do (
set "SAVED_START_TYPE=%%a"
)
echo Raw saved start type: [!SAVED_START_TYPE!]
rem Check start type
if "!SAVED_START_TYPE!"=="2-delayed" (
set SERVICE_START_TYPE=delayed-auto
) else if "!SAVED_START_TYPE!"=="2" (
set SERVICE_START_TYPE=auto
) else if "!SAVED_START_TYPE!"=="3" (
set SERVICE_START_TYPE=demand
) else if "!SAVED_START_TYPE!"=="4" (
set SERVICE_START_TYPE=disabled
)
del "%SERVICE_CONFIG_FILE%"
)
echo Setting service start type set to: [!SERVICE_START_TYPE!]
rem Run the sc command to create/reconfigure the service rem Run the sc command to create/reconfigure the service
sc %SC_CMD% %SERVICE_NAME% binPath= %SERVICE_BIN% start= %SERVICE_START_TYPE% DisplayName= "Apollo Service" sc %SC_CMD% %SERVICE_NAME% binPath= "%SERVICE_BIN%" start= %SERVICE_START_TYPE% DisplayName= "Apollo Service"
rem Set the description of the service rem Set the description of the service
sc description %SERVICE_NAME% "Apollo is a self-hosted game stream host for Moonlight." sc description %SERVICE_NAME% "Apollo is a self-hosted game stream host for Moonlight."

View File

@@ -1,4 +1,36 @@
@echo off @echo off
setlocal enabledelayedexpansion
set "SERVICE_CONFIG_DIR=%LOCALAPPDATA%\SudoMaker\Apollo"
set "SERVICE_CONFIG_FILE=%SERVICE_CONFIG_DIR%\service_start_type.txt"
rem Save the current service start type to a file if the service exists
sc qc ApolloService >nul 2>&1
if %ERRORLEVEL%==0 (
if not exist "%SERVICE_CONFIG_DIR%\" mkdir "%SERVICE_CONFIG_DIR%\"
rem Get the start type
for /f "tokens=3" %%i in ('sc qc ApolloService ^| findstr /C:"START_TYPE"') do (
set "CURRENT_START_TYPE=%%i"
)
rem Set the content to write
if "!CURRENT_START_TYPE!"=="2" (
sc qc ApolloService | findstr /C:"(DELAYED)" >nul
if !ERRORLEVEL!==0 (
set "CONTENT=2-delayed"
) else (
set "CONTENT=2"
)
) else if "!CURRENT_START_TYPE!" NEQ "" (
set "CONTENT=!CURRENT_START_TYPE!"
) else (
set "CONTENT=unknown"
)
rem Write content to file
echo !CONTENT!> "%SERVICE_CONFIG_FILE%"
)
rem Stop and delete the legacy SunshineSvc service rem Stop and delete the legacy SunshineSvc service
net stop sunshinesvc net stop sunshinesvc