diff --git a/src/moonlight-server/state/configTOML.cpp b/src/moonlight-server/state/configTOML.cpp index d58bc36b..fa9335e8 100644 --- a/src/moonlight-server/state/configTOML.cpp +++ b/src/moonlight-server/state/configTOML.cpp @@ -16,6 +16,7 @@ namespace state { */ constexpr char const *default_toml = #include "default/config.include.toml" + ; using namespace std::literals; @@ -131,7 +132,7 @@ Config load_or_default(const std::string &source, if (default_gst_video_settings.default_source.find("appsrc") != std::string::npos) { logs::log(logs::debug, "Found appsrc in default_source, migrating to interpipesrc"); default_gst_video_settings.default_source = "interpipesrc listen-to={session_id}_video is-live=true " - "stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false"; + "stream-sync=restart-ts max-buffers=1 block=false"; } auto default_gst_audio_settings = cfg.gstreamer.audio; @@ -140,7 +141,25 @@ Config load_or_default(const std::string &source, default_gst_audio_settings.default_source = "interpipesrc listen-to={session_id}_audio is-live=true " "stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false"; } + auto default_gst_encoder_settings = default_gst_video_settings.defaults; + auto update_leaky_queue = [](std::string &pipeline) { + std::string old_str = "queue"; + auto replace_pos = pipeline.find(old_str); + pipeline.replace(replace_pos, old_str.size(), "queue leaky=downstream max-size-buffers=1 "); + }; + if (default_gst_encoder_settings["nvcodec"].video_params.find("queue !") != std::string::npos) { + logs::log(logs::debug, "Found leaky queue in nvcodec, migrating to queue leaky=downstream"); + update_leaky_queue(default_gst_encoder_settings["nvcodec"].video_params); + } + if (default_gst_encoder_settings["vaapi"].video_params.find("queue !") != std::string::npos) { + logs::log(logs::debug, "Found leaky queue in vaapi, migrating to queue leaky=downstream"); + update_leaky_queue(default_gst_encoder_settings["vaapi"].video_params); + } + if (default_gst_encoder_settings["qsv"].video_params.find("queue !") != std::string::npos) { + logs::log(logs::debug, "Found leaky queue in qsv, migrating to queue leaky=downstream"); + update_leaky_queue(default_gst_encoder_settings["qsv"].video_params); + } auto default_app_render_node = utils::get_env("WOLF_RENDER_NODE", "/dev/dri/renderD128"); auto default_gst_render_node = utils::get_env("WOLF_ENCODER_NODE", default_app_render_node); diff --git a/src/moonlight-server/state/data-structures.hpp b/src/moonlight-server/state/data-structures.hpp index 294b8a25..e7bf7014 100644 --- a/src/moonlight-server/state/data-structures.hpp +++ b/src/moonlight-server/state/data-structures.hpp @@ -191,7 +191,7 @@ static const audio::AudioMode &get_audio_mode(int channels, bool high_quality) { base_index = 1; } else if (channels == 8) { base_index = 2; - } else { + } else if (channels != 2) { logs::log(logs::warning, "Moonlight requested an impossible number of channels: {}", channels); } diff --git a/src/moonlight-server/state/default/config.include.toml b/src/moonlight-server/state/default/config.include.toml index e0e2a1f8..5411177b 100644 --- a/src/moonlight-server/state/default/config.include.toml +++ b/src/moonlight-server/state/default/config.include.toml @@ -172,7 +172,7 @@ source = "audiotestsrc wave=ticks is-live=true" [gstreamer.video] -default_source = "interpipesrc listen-to={session_id}_video is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false" +default_source = 'interpipesrc listen-to={session_id}_video is-live=true stream-sync=restart-ts max-buffers=1 block=false' default_sink = """ rtpmoonlightpay_video name=moonlight_pay \ payload_size={payload_size} fec_percentage={fec_percentage} min_required_fec_packets={min_required_fec_packets} ! @@ -184,7 +184,7 @@ udpsink bind-port={host_port} host={client_ip} port={client_port} sync=true\ # To avoid repetition between H264, HEVC and AV1 encoders [gstreamer.video.defaults.nvcodec] video_params = """ -queue ! +queue leaky=downstream max-size-buffers=1 ! cudaupload ! cudaconvertscale ! video/x-raw(memory:CUDAMemory), width={width}, height={height}, \ @@ -193,14 +193,14 @@ chroma-site={color_range}, format=NV12, colorimetry={color_space}, pixel-aspect- [gstreamer.video.defaults.qsv] video_params = """ -queue ! +queue leaky=downstream max-size-buffers=1 ! videoconvertscale ! video/x-raw, chroma-site={color_range}, width={width}, height={height}, format=NV12, colorimetry={color_space}\ """ [gstreamer.video.defaults.vaapi] video_params = """ -queue ! +queue leaky=downstream max-size-buffers=1 ! videoconvertscale ! video/x-raw, chroma-site={color_range}, width={width}, height={height}, format=NV12, colorimetry={color_space}\ """ @@ -342,7 +342,7 @@ video/x-av1, stream-format=obu-stream, alignment=frame, profile=main\ plugin_name = "vaapi" check_elements = ["vaav1enc", "videoconvertscale"] encoder_pipeline = """ -vaav1enc gop-size=0 ref-frames=1 bitrate={bitrate} rate-control=cbr ! +vaav1enc ref-frames=1 bitrate={bitrate} rate-control=cbr target-usage=6 ! av1parse ! video/x-av1, stream-format=obu-stream, alignment=frame, profile=main\ """ @@ -351,7 +351,7 @@ video/x-av1, stream-format=obu-stream, alignment=frame, profile=main\ plugin_name = "vaapi" check_elements = ["vaav1lpenc", "videoconvertscale"] # LP = Low Power encoder_pipeline = """ -vaav1lpenc gop-size=0 ref-frames=1 bitrate={bitrate} rate-control=cbr ! +vaav1lpenc ref-frames=1 bitrate={bitrate} rate-control=cbr target-usage=6 ! av1parse ! video/x-av1, stream-format=obu-stream, alignment=frame, profile=main\ """ diff --git a/src/moonlight-server/state/default/config.v4.toml b/src/moonlight-server/state/default/config.v4.toml index 6bcea4e3..6ae13858 100644 --- a/src/moonlight-server/state/default/config.v4.toml +++ b/src/moonlight-server/state/default/config.v4.toml @@ -171,7 +171,7 @@ source = "audiotestsrc wave=ticks is-live=true" [gstreamer.video] -default_source = "interpipesrc listen-to={session_id}_video is-live=true stream-sync=restart-ts max-bytes=0 max-buffers=3 block=false" +default_source = 'interpipesrc listen-to={session_id}_video is-live=true stream-sync=restart-ts max-buffers=1 block=false' default_sink = """ rtpmoonlightpay_video name=moonlight_pay \ payload_size={payload_size} fec_percentage={fec_percentage} min_required_fec_packets={min_required_fec_packets} ! @@ -183,7 +183,7 @@ udpsink bind-port={host_port} host={client_ip} port={client_port} sync=true\ # To avoid repetition between H264, HEVC and AV1 encoders [gstreamer.video.defaults.nvcodec] video_params = """ -queue ! +queue leaky=downstream max-size-buffers=1 ! cudaupload ! cudaconvertscale ! video/x-raw(memory:CUDAMemory), width={width}, height={height}, \ @@ -192,14 +192,14 @@ chroma-site={color_range}, format=NV12, colorimetry={color_space}, pixel-aspect- [gstreamer.video.defaults.qsv] video_params = """ -queue ! +queue leaky=downstream max-size-buffers=1 ! videoconvertscale ! video/x-raw, chroma-site={color_range}, width={width}, height={height}, format=NV12, colorimetry={color_space}\ """ [gstreamer.video.defaults.vaapi] video_params = """ -queue ! +queue leaky=downstream max-size-buffers=1 ! videoconvertscale ! video/x-raw, chroma-site={color_range}, width={width}, height={height}, format=NV12, colorimetry={color_space}\ """ diff --git a/src/moonlight-server/streaming/streaming.cpp b/src/moonlight-server/streaming/streaming.cpp index 9a151e0c..00086139 100644 --- a/src/moonlight-server/streaming/streaming.cpp +++ b/src/moonlight-server/streaming/streaming.cpp @@ -82,8 +82,8 @@ void start_video_producer(std::size_t session_id, const std::shared_ptr &event_bus) { auto appsrc_state = streaming::custom_src::setup_app_src(display_mode, std::move(wl_state)); auto pipeline = fmt::format("appsrc is-live=true name=wolf_wayland_source ! " // - "queue ! " // - "interpipesink name={}_video sync=true async=false max-bytes=0 max-buffers=3", // + "queue leaky=downstream max-size-buffers=1 ! " // + "interpipesink name={}_video max-buffers=1", // session_id); logs::log(logs::debug, "[GSTREAMER] Starting video producer: {}", pipeline); run_pipeline(pipeline, [=](auto pipeline, auto loop) { @@ -132,8 +132,8 @@ void start_audio_producer(std::size_t session_id, auto pipeline = fmt::format( "pulsesrc device=\"{sink_name}\" server=\"{server_name}\" ! " // "audio/x-raw, channels={channels}, rate=48000 ! " // - "queue ! " // - "interpipesink name=\"{session_id}_audio\" sync=true async=false max-bytes=0 max-buffers=3", + "queue leaky=downstream max-size-buffers=3 ! " // + "interpipesink name=\"{session_id}_audio\" sync=true async=false max-buffers=3", fmt::arg("session_id", session_id), fmt::arg("channels", channel_count), fmt::arg("sink_name", sink_name),