@@ -384,6 +384,7 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
#endif
ctx->support_dyn_bitrate = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE);
+ ctx->support_dyn_res = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_RES_CHANGE);
return 0;
}
@@ -1121,6 +1122,8 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
ctx->init_encode_params.encodeHeight = avctx->height;
ctx->init_encode_params.encodeWidth = avctx->width;
+ ctx->init_encode_params.maxEncodeHeight = ctx->max_height;
+ ctx->init_encode_params.maxEncodeWidth = ctx->max_width;
ctx->init_encode_params.encodeConfig = &ctx->encode_config;
@@ -1276,8 +1279,8 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
}
allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
- allocSurf.width = avctx->width;
- allocSurf.height = avctx->height;
+ allocSurf.width = FFMAX(ctx->max_width, avctx->width);
+ allocSurf.height = FFMAX(ctx->max_height, avctx->height);
allocSurf.bufferFmt = ctx->surfaces[idx].format;
nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf);
@@ -1926,7 +1929,7 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
NV_ENC_RECONFIGURE_PARAMS params = { 0 };
int needs_reconfig = 0;
int needs_encode_config = 0;
- int reconfig_bitrate = 0, reconfig_dar = 0;
+ int reconfig_bitrate = 0, reconfig_dar = 0, reconfig_res = 0;
int dw, dh;
params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
@@ -1986,6 +1989,24 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
}
}
+ if (ctx->support_dyn_res && ctx->init_encode_params.maxEncodeWidth && ctx->init_encode_params.maxEncodeHeight) {
+ if (params.reInitEncodeParams.encodeWidth != avctx->width || params.reInitEncodeParams.encodeHeight != avctx->height) {
+ av_log(avctx, AV_LOG_VERBOSE,
+ "resolution change: %d x %d -> %d x %d\n",
+ params.reInitEncodeParams.encodeWidth,
+ params.reInitEncodeParams.encodeHeight,
+ (uint32_t)avctx->width,
+ (uint32_t)avctx->height);
+
+ params.reInitEncodeParams.encodeWidth = avctx->width;
+ params.reInitEncodeParams.encodeHeight = avctx->height;
+ params.forceIDR = 1;
+
+ needs_reconfig = 1;
+ reconfig_res = 1;
+ }
+ }
+
if (!needs_encode_config)
params.reInitEncodeParams.encodeConfig = NULL;
@@ -2005,6 +2026,10 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
ctx->encode_config.rcParams.vbvBufferSize = params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize;
}
+ if (reconfig_res) {
+ ctx->init_encode_params.encodeWidth = params.reInitEncodeParams.encodeWidth;
+ ctx->init_encode_params.encodeHeight = params.reInitEncodeParams.encodeHeight;
+ }
}
}
}
@@ -158,6 +158,7 @@ typedef struct NvencContext
int first_packet_output;
int support_dyn_bitrate;
+ int support_dyn_res;
void *nvencoder;
@@ -192,6 +193,8 @@ typedef struct NvencContext
int coder;
int b_ref_mode;
int a53_cc;
+ int max_width;
+ int max_height;
} NvencContext;
int ff_nvenc_encode_init(AVCodecContext *avctx);
@@ -138,6 +138,10 @@ static const AVOption options[] = {
{ "middle", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" },
#endif
{ "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
+ { "max_width", "Maximum encode width for dynamic resolution encoding",
+ OFFSET(max_width), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, VE },
+ { "max_height", "Maximum encode height for dynamic resolution encoding",
+ OFFSET(max_height), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, VE },
{ NULL }
};
@@ -127,6 +127,10 @@ static const AVOption options[] = {
{ "each", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "b_ref_mode" },
{ "middle", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" },
#endif
+ { "max_width", "Maximum encode width for dynamic resolution encoding",
+ OFFSET(max_width), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, VE },
+ { "max_height", "Maximum encode height for dynamic resolution encoding",
+ OFFSET(max_height), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, VE },
{ NULL }
};