From 710a2b9d6305a280e2b00950c025bf3206b44e10 Mon Sep 17 00:00:00 2001 From: pigeatgarlic Date: Fri, 15 Dec 2023 00:53:35 +0700 Subject: [PATCH] dynamically change bitrate --- src/dll.cpp | 3 +++ src/main.h | 1 + src/nvenc/nvenc_base.cpp | 14 +++++++++++++- src/nvenc/nvenc_base.h | 4 ++++ src/video.cpp | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/dll.cpp b/src/dll.cpp index fb239d4c..f6fecef0 100644 --- a/src/dll.cpp +++ b/src/dll.cpp @@ -127,6 +127,9 @@ RaiseEvent(VideoPipeline *pipeline, case POINTER_VISIBLE: // IDR FRAME pipeline->mail->event(mail::toggle_cursor)->raise(value != 0); break; + case CHANGE_BITRATE: // IDR FRAME + pipeline->mail->event(mail::bitrate)->raise(value); + break; default: break; } diff --git a/src/main.h b/src/main.h index 53ba40cb..6e2f8130 100644 --- a/src/main.h +++ b/src/main.h @@ -43,6 +43,7 @@ namespace mail { MAIL(switch_display); MAIL(toggle_cursor); MAIL(idr); + MAIL(bitrate); MAIL(hdr); MAIL(invalidate_ref_frames); diff --git a/src/nvenc/nvenc_base.cpp b/src/nvenc/nvenc_base.cpp index ed0a7c9c..cecb5e35 100644 --- a/src/nvenc/nvenc_base.cpp +++ b/src/nvenc/nvenc_base.cpp @@ -111,7 +111,7 @@ namespace nvenc { return false; } - NV_ENC_INITIALIZE_PARAMS init_params = { NV_ENC_INITIALIZE_PARAMS_VER }; + init_params = { NV_ENC_INITIALIZE_PARAMS_VER }; switch (client_config.videoFormat) { case 0: @@ -406,6 +406,18 @@ namespace nvenc { encoder_params = {}; } + + void + nvenc_base::update_bitrate(int bitrate) { + NV_ENC_RECONFIGURE_PARAMS reconfigure_params = { NV_ENC_RECONFIGURE_PARAMS_VER }; + /* reset rate control state and start from IDR */ + init_params.encodeConfig->rcParams.averageBitRate = bitrate; + reconfigure_params.reInitEncodeParams = init_params; + reconfigure_params.resetEncoder = TRUE; + reconfigure_params.forceIDR = TRUE; + nvenc->nvEncReconfigureEncoder(encoder, &reconfigure_params); + } + nvenc_encoded_frame nvenc_base::encode_frame(uint64_t frame_index, bool force_idr) { if (!encoder) { diff --git a/src/nvenc/nvenc_base.h b/src/nvenc/nvenc_base.h index ec84136c..87e5b6a3 100644 --- a/src/nvenc/nvenc_base.h +++ b/src/nvenc/nvenc_base.h @@ -25,6 +25,9 @@ namespace nvenc { void destroy_encoder(); + void + update_bitrate(int bitrate); + nvenc_encoded_frame encode_frame(uint64_t frame_index, bool force_idr); @@ -50,6 +53,7 @@ namespace nvenc { std::unique_ptr nvenc; void *encoder = nullptr; + NV_ENC_INITIALIZE_PARAMS init_params; struct { uint32_t width = 0; diff --git a/src/video.cpp b/src/video.cpp index 2946c380..eab68ed9 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -392,6 +392,9 @@ namespace video { virtual void request_idr_frame() = 0; + virtual void + update_bitrate (int bitrate) = 0; + virtual void request_normal_frame() = 0; @@ -441,6 +444,13 @@ namespace video { } } + void + update_bitrate(int bitrate) override { + // bitrate = bitrate * 1000; + // avcodec_ctx->rc_max_rate = bitrate; + // avcodec_ctx->bit_rate = bitrate; + } + void request_normal_frame() override { if (device && device->frame) { @@ -490,6 +500,14 @@ namespace video { force_idr = false; } + void + update_bitrate(int bitrate) override { + if (!device || !device->nvenc) return; + + device->nvenc->update_bitrate(bitrate); + } + + void invalidate_ref_frames(int64_t first_frame, int64_t last_frame) override { if (!device || !device->nvenc) return; @@ -518,6 +536,7 @@ namespace video { safe::mail_raw_t::event_t shutdown_event; safe::mail_raw_t::queue_t packets; safe::mail_raw_t::event_t idr_events; + safe::mail_raw_t::event_t bitrate_events; safe::mail_raw_t::event_t switch_display; safe::mail_raw_t::event_t toggle_cursor; safe::mail_raw_t::event_t hdr_events; @@ -1763,6 +1782,7 @@ namespace video { auto packets = mail->queue(mail::video_packets); auto idr_events = mail->event(mail::idr); + auto bitrate_events = mail->event(mail::bitrate); auto invalidate_ref_frames_events = mail->event>(mail::invalidate_ref_frames); { @@ -1797,7 +1817,14 @@ namespace video { idr_events->pop(); } + if (bitrate_events->peek()) { + auto bitrate = bitrate_events->pop().value(); + BOOST_LOG(info) << "bitrate changed"sv; + session->update_bitrate(bitrate); + } + if (requested_idr_frame) { + BOOST_LOG(info) << "IDR frame generated"sv; session->request_idr_frame(); } @@ -1982,6 +2009,11 @@ namespace video { BOOST_LOG(info) << "cursor set to " << display_cursor; } + if (ctx->bitrate_events->peek()) { + auto bitrate = ctx->bitrate_events->pop().value(); + BOOST_LOG(info) << "bitrate changed"sv; + pos->session->update_bitrate(bitrate); + } if (ctx->idr_events->peek()) { BOOST_LOG(info) << "IDR frame generated"sv; pos->session->request_idr_frame(); @@ -2160,6 +2192,7 @@ namespace video { // CAREFULL auto ptr_events = mail->event(mail::toggle_cursor); auto idr_events = mail->event(mail::idr); + auto bitrate_events = mail->event(mail::bitrate); auto display_events = mail->event(mail::switch_display); auto shutdown_event = mail->event(mail::shutdown); auto packets = mail->queue(mail::video_packets); @@ -2180,6 +2213,7 @@ namespace video { std::move(shutdown_event), std::move(packets), std::move(idr_events), + std::move(bitrate_events), std::move(display_events), std::move(ptr_events), mail->event(mail::hdr),