Commit 15537512 authored by pkviet's avatar pkviet Committed by Timo Rothenpieler

avcodec/nvenc: support dynamic bitrate changes

The patch enables dynamic bitrate through ReconfigureEncoder method
from nvenc API.
This is useful for live streaming in case of network congestion.
Signed-off-by: 's avatarpkviet <pkv.stream@gmail.com>
Signed-off-by: 's avatarTimo Rothenpieler <timo@rothenpieler.org>
parent 952421cd
...@@ -394,6 +394,8 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) ...@@ -394,6 +394,8 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
} }
#endif #endif
ctx->support_dyn_bitrate = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE);
return 0; return 0;
} }
...@@ -873,7 +875,7 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx) ...@@ -873,7 +875,7 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
if (avctx->rc_buffer_size > 0) { if (avctx->rc_buffer_size > 0) {
ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size; ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size;
} else if (ctx->encode_config.rcParams.averageBitRate > 0) { } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate; avctx->rc_buffer_size = ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate;
} }
if (ctx->aq) { if (ctx->aq) {
...@@ -1944,6 +1946,7 @@ static int reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) ...@@ -1944,6 +1946,7 @@ static int reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
NV_ENC_RECONFIGURE_PARAMS params = { 0 }; NV_ENC_RECONFIGURE_PARAMS params = { 0 };
int needs_reconfig = 0; int needs_reconfig = 0;
int needs_encode_config = 0; int needs_encode_config = 0;
int reconfig_bitrate = 0, reconfig_dar = 0;
int dw, dh; int dw, dh;
params.version = NV_ENC_RECONFIGURE_PARAMS_VER; params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
...@@ -1960,6 +1963,47 @@ static int reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) ...@@ -1960,6 +1963,47 @@ static int reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
params.reInitEncodeParams.darWidth = dw; params.reInitEncodeParams.darWidth = dw;
needs_reconfig = 1; needs_reconfig = 1;
reconfig_dar = 1;
}
if (ctx->rc != NV_ENC_PARAMS_RC_CONSTQP && ctx->support_dyn_bitrate) {
if (avctx->bit_rate > 0 && params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate != avctx->bit_rate) {
av_log(avctx, AV_LOG_VERBOSE,
"avg bitrate change: %d -> %d\n",
params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate,
(uint32_t)avctx->bit_rate);
params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate = avctx->bit_rate;
reconfig_bitrate = 1;
}
if (avctx->rc_max_rate > 0 && ctx->encode_config.rcParams.maxBitRate != avctx->rc_max_rate) {
av_log(avctx, AV_LOG_VERBOSE,
"max bitrate change: %d -> %d\n",
params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate,
(uint32_t)avctx->rc_max_rate);
params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate = avctx->rc_max_rate;
reconfig_bitrate = 1;
}
if (avctx->rc_buffer_size > 0 && ctx->encode_config.rcParams.vbvBufferSize != avctx->rc_buffer_size) {
av_log(avctx, AV_LOG_VERBOSE,
"vbv buffer size change: %d -> %d\n",
params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize,
avctx->rc_buffer_size);
params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize = avctx->rc_buffer_size;
reconfig_bitrate = 1;
}
if (reconfig_bitrate) {
params.resetEncoder = 1;
params.forceIDR = 1;
needs_encode_config = 1;
needs_reconfig = 1;
}
} }
if (!needs_encode_config) if (!needs_encode_config)
...@@ -1970,8 +2014,17 @@ static int reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) ...@@ -1970,8 +2014,17 @@ static int reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
if (ret != NV_ENC_SUCCESS) { if (ret != NV_ENC_SUCCESS) {
nvenc_print_error(avctx, ret, "failed to reconfigure nvenc"); nvenc_print_error(avctx, ret, "failed to reconfigure nvenc");
} else { } else {
ctx->init_encode_params.darHeight = dh; if (reconfig_dar) {
ctx->init_encode_params.darWidth = dw; ctx->init_encode_params.darHeight = dh;
ctx->init_encode_params.darWidth = dw;
}
if (reconfig_bitrate) {
ctx->encode_config.rcParams.averageBitRate = params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate;
ctx->encode_config.rcParams.maxBitRate = params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate;
ctx->encode_config.rcParams.vbvBufferSize = params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize;
}
} }
} }
......
...@@ -152,6 +152,8 @@ typedef struct NvencContext ...@@ -152,6 +152,8 @@ typedef struct NvencContext
int64_t initial_pts[2]; int64_t initial_pts[2];
int first_packet_output; int first_packet_output;
int support_dyn_bitrate;
void *nvencoder; void *nvencoder;
int preset; int preset;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment