diff --git a/assets/sunshine.conf b/assets/sunshine.conf index ef96f52f..6b316a76 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -80,8 +80,11 @@ crf = 0 # If crf != 0, then this parameter is ignored qp = 28 -# Number of threads used by ffmpeg to encode the video -threads = 8 +# Minimum number of threads used by ffmpeg to encode the video. +# Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually +# worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest +# value that can reliably encode at your desired streaming settings on your hardware. +min_threads = 2 # Allows the client to request HEVC Main or HEVC Main10 video streams. # HEVC is more CPU-intensive to encode, so enabling this may reduce performance. diff --git a/sunshine/config.cpp b/sunshine/config.cpp index 444cd16c..8db697d8 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -19,7 +19,7 @@ video_t video { 35, // crf 35, // qp - 4, // threads + 2, // min_threads 0, // hevc_mode "superfast"s, // preset @@ -156,7 +156,7 @@ void parse_file(const char *file) { int_f(vars, "crf", video.crf); int_f(vars, "qp", video.qp); - int_f(vars, "threads", video.threads); + int_f(vars, "min_threads", video.min_threads); int_between_f(vars, "hevc_mode", video.hevc_mode, { 0, 2 }); diff --git a/sunshine/config.h b/sunshine/config.h index c55b5c85..541d8727 100644 --- a/sunshine/config.h +++ b/sunshine/config.h @@ -10,7 +10,7 @@ struct video_t { int crf; // higher == more compression and less quality int qp; // higher == more compression and less quality, ignored if crf != 0 - int threads; // Number threads used by ffmpeg + int min_threads; // Minimum number of threads/slices for CPU encoding int hevc_mode; std::string preset; diff --git a/sunshine/video.cpp b/sunshine/video.cpp index d8cd84aa..be9652c7 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -165,10 +165,12 @@ void encodeThread( // Some client decoders have limits on the number of reference frames ctx->refs = config.numRefFrames; - ctx->slices = config.slicesPerFrame; + // Clients will request for the fewest slices per frame to get the + // most efficient encode, but we may want to provide more slices than + // requested to ensure we have enough parallelism for good performance. + ctx->slices = std::max(config.slicesPerFrame, config::video.min_threads); ctx->thread_type = FF_THREAD_SLICE; - ctx->thread_count = std::min(ctx->slices, config::video.threads); - + ctx->thread_count = ctx->slices; AVDictionary *options {nullptr}; av_dict_set(&options, "preset", config::video.preset.c_str(), 0);