dynamically change bitrate

This commit is contained in:
pigeatgarlic 2023-12-15 00:53:35 +07:00
parent 0407248e18
commit 710a2b9d63
5 changed files with 55 additions and 1 deletions

View File

@ -127,6 +127,9 @@ RaiseEvent(VideoPipeline *pipeline,
case POINTER_VISIBLE: // IDR FRAME
pipeline->mail->event<bool>(mail::toggle_cursor)->raise(value != 0);
break;
case CHANGE_BITRATE: // IDR FRAME
pipeline->mail->event<int>(mail::bitrate)->raise(value);
break;
default:
break;
}

View File

@ -43,6 +43,7 @@ namespace mail {
MAIL(switch_display);
MAIL(toggle_cursor);
MAIL(idr);
MAIL(bitrate);
MAIL(hdr);
MAIL(invalidate_ref_frames);

View File

@ -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) {

View File

@ -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<NV_ENCODE_API_FUNCTION_LIST> nvenc;
void *encoder = nullptr;
NV_ENC_INITIALIZE_PARAMS init_params;
struct {
uint32_t width = 0;

View File

@ -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<bool> shutdown_event;
safe::mail_raw_t::queue_t<packet_t> packets;
safe::mail_raw_t::event_t<bool> idr_events;
safe::mail_raw_t::event_t<int> bitrate_events;
safe::mail_raw_t::event_t<std::string> switch_display;
safe::mail_raw_t::event_t<bool> toggle_cursor;
safe::mail_raw_t::event_t<hdr_info_t> hdr_events;
@ -1763,6 +1782,7 @@ namespace video {
auto packets = mail->queue<packet_t>(mail::video_packets);
auto idr_events = mail->event<bool>(mail::idr);
auto bitrate_events = mail->event<int>(mail::bitrate);
auto invalidate_ref_frames_events = mail->event<std::pair<int64_t, int64_t>>(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<bool>(mail::toggle_cursor);
auto idr_events = mail->event<bool>(mail::idr);
auto bitrate_events = mail->event<int>(mail::bitrate);
auto display_events = mail->event<std::string>(mail::switch_display);
auto shutdown_event = mail->event<bool>(mail::shutdown);
auto packets = mail->queue<packet_t>(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<hdr_info_t>(mail::hdr),