From 4569eea05bd70f9357662ff7ac9e63d238a098ac Mon Sep 17 00:00:00 2001 From: loki Date: Thu, 12 Dec 2019 13:13:10 +0100 Subject: [PATCH] Add configurable variable QP for video --- assets/sunshine.conf | 20 +++++++++++++------- sunshine/config.cpp | 2 ++ sunshine/config.h | 1 + sunshine/stream.cpp | 2 +- sunshine/video.cpp | 13 ++++++++----- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/assets/sunshine.conf b/assets/sunshine.conf index e5e47887..696a4b04 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -20,7 +20,7 @@ ping_timeout = 2000 # How much error correcting packets must be send for every video max_b_frames # This is just some random number, don't know the optimal value # The higher fec_percentage, the lower space for the actual data to send per frame there is -fec_percentage = 25 +fec_percentage = 1 ############################################### # FFmpeg software encoding parameters @@ -29,15 +29,21 @@ fec_percentage = 25 max_b_frames = 16 gop_size = 24 -# Constant Rate Factor. Between 1 and 52. +# Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still image, resulting in constant perceived quality # Higher value means more compression, but less quality -crf = 28 +# If crf == 0, then use QP directly instead +crf = 0 + +# Quantitization Parameter +# Higher value means more compression, but less quality +# If crf != 0, then this parameter is ignored +qp = 28 # Number of threads used by ffmpeg to encode the video -# threads = 4 +threads = 8 # See x264 --fullhelp for the different presets -# profile = baseline -# preset = superfast -# tune = zerolatency +profile = baseline +preset = superfast +tune = zerolatency diff --git a/sunshine/config.cpp b/sunshine/config.cpp index e4b9f486..2c52c141 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -19,6 +19,7 @@ video_t video { 16, // max_b_frames 24, // gop_size 35, // crf + 35, // qp 4, // threads @@ -121,6 +122,7 @@ void parse_file(const char *file) { int_f(vars, "max_b_frames", video.max_b_frames); int_f(vars, "gop_size", video.gop_size); int_f(vars, "crf", video.crf); + int_f(vars, "qp", video.qp); int_f(vars, "threads", video.threads); string_f(vars, "profile", video.profile); string_f(vars, "preset", video.preset); diff --git a/sunshine/config.h b/sunshine/config.h index ad82e5d5..1ab0ea3d 100644 --- a/sunshine/config.h +++ b/sunshine/config.h @@ -10,6 +10,7 @@ struct video_t { int max_b_frames; int gop_size; 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 diff --git a/sunshine/stream.cpp b/sunshine/stream.cpp index 464639f2..b43f5a9f 100644 --- a/sunshine/stream.cpp +++ b/sunshine/stream.cpp @@ -876,7 +876,7 @@ void cmd_announce(host_t &host, peer_t peer, msg_t &&req) { config.monitor.height = util::from_view(args.at("x-nv-video[0].clientViewportHt"sv)); config.monitor.width = util::from_view(args.at("x-nv-video[0].clientViewportWd"sv)); config.monitor.framerate = util::from_view(args.at("x-nv-video[0].maxFPS"sv)); - config.monitor.bitrate = util::from_view(args.at("x-nv-video[0].initialBitrateKbps"sv)); + config.monitor.bitrate = util::from_view(args.at("x-nv-vqos[0].bw.maximumBitrateKbps"sv)); config.monitor.slicesPerFrame = util::from_view(args.at("x-nv-video[0].videoEncoderSlicesPerFrame"sv)); } catch(std::out_of_range &) { diff --git a/sunshine/video.cpp b/sunshine/video.cpp index 45e92039..4f2042e3 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -103,6 +103,7 @@ void encodeThread( ctx->pix_fmt = AV_PIX_FMT_YUV420P; ctx->max_b_frames = config::video.max_b_frames; ctx->gop_size = config::video.gop_size; + ctx->has_b_frames = 1; ctx->slices = config.slicesPerFrame; ctx->thread_type = FF_THREAD_SLICE; @@ -114,8 +115,13 @@ void encodeThread( av_dict_set(&options, "preset", config::video.preset.c_str(), 0); av_dict_set(&options, "tune", config::video.tune.c_str(), 0); - av_dict_set_int(&options, "crf", config::video.crf, 0); - + if(config::video.crf != 0) { + av_dict_set_int(&options, "crf", config::video.crf, 0); + } + else { + av_dict_set_int(&options, "qp", config::video.qp, 0); + } + ctx->flags |= (AV_CODEC_FLAG_CLOSED_GOP | AV_CODEC_FLAG_LOW_DELAY); ctx->flags2 |= AV_CODEC_FLAG2_FAST; @@ -126,7 +132,6 @@ void encodeThread( yuv_frame->width = ctx->width; yuv_frame->height = ctx->height; - // yuv_frame->opaque = 0; av_frame_get_buffer(yuv_frame.get(), 0); int64_t frame = 1; @@ -146,8 +151,6 @@ void encodeThread( if(idr_events->peek()) { yuv_frame->pict_type = AV_PICTURE_TYPE_I; frame = idr_events->pop()->first; - -// ++yuv_frame->opaque; } encode(frame++, ctx, sws, yuv_frame, img, packets);