From: wang-bin
There are reserved bit fields in nvEncoderAPI.h structs, so driver's abi
is stable. Requesting runtime version of these structs should work. I've
compared 7.0~9.x headers, and confirmed on some devices.
---
libavcodec/nvenc.c | 72 ++
libavcodec/nvenc.h | 3 ++
2 files changed, 44 insertions(+), 31 deletions(-)
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index c6740c1842..ac35cb9f48 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -193,14 +193,26 @@ static void nvenc_print_driver_requirement(AVCodecContext
*avctx, int level)
av_log(avctx, level, "The minimum required Nvidia driver for nvenc is %s
or newer\n", minver);
}
+static inline uint32_t struct_ver_rt(NvencContext* ctx, uint32_t struct_ver)
+{
+return ((uint32_t)ctx->apiver_rt | ((struct_ver)<<16) | (0x7 << 28));
+}
+
+static inline uint32_t api_ver(uint32_t major_ver, uint32_t minor_ver)
+{
+return major_ver | (minor_ver << 24);
+}
+
static av_cold int nvenc_load_libraries(AVCodecContext *avctx)
{
NvencContext *ctx= avctx->priv_data;
NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
NVENCSTATUS err;
uint32_t nvenc_max_ver;
+uint32_t nvenc_max_major;
+uint32_t nvenc_max_minor;
+uint32_t func_ver = NV_ENCODE_API_FUNCTION_LIST_VER;
int ret;
-
ret = cuda_load_functions(&dl_fn->cuda_dl, avctx);
if (ret < 0)
return ret;
@@ -214,19 +226,17 @@ static av_cold int nvenc_load_libraries(AVCodecContext
*avctx)
err = dl_fn->nvenc_dl->NvEncodeAPIGetMaxSupportedVersion(&nvenc_max_ver);
if (err != NV_ENC_SUCCESS)
return nvenc_print_error(avctx, err, "Failed to query nvenc max
version");
+nvenc_max_major = nvenc_max_ver >> 4;
+nvenc_max_minor = nvenc_max_ver & 0xf;
+av_log(avctx, AV_LOG_VERBOSE, "nvenc build version: %d.%d, runtime
version: %d.%d\n", NVENCAPI_MAJOR_VERSION, NVENCAPI_MINOR_VERSION,
nvenc_max_major, nvenc_max_minor);
-av_log(avctx, AV_LOG_VERBOSE, "Loaded Nvenc version %d.%d\n",
nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
-
-if ((NVENCAPI_MAJOR_VERSION << 4 | NVENCAPI_MINOR_VERSION) >
nvenc_max_ver) {
-av_log(avctx, AV_LOG_ERROR, "Driver does not support the required
nvenc API version. "
- "Required: %d.%d Found: %d.%d\n",
- NVENCAPI_MAJOR_VERSION, NVENCAPI_MINOR_VERSION,
- nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
-nvenc_print_driver_requirement(avctx, AV_LOG_ERROR);
-return AVERROR(ENOSYS);
-}
+ctx->apiver_rt = api_ver(nvenc_max_major, nvenc_max_minor); /*
NVENCAPI_VERSION */
+ctx->config_ver_rt = struct_ver_rt(ctx, 7) | (1<<31); /* NV_ENC_CONFIG_VER
*/
+if (ctx->apiver_rt < api_ver(8, 1))
+ctx->config_ver_rt = struct_ver_rt(ctx, 6) | (1<<31);
+func_ver = struct_ver_rt(ctx, 2);
-dl_fn->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER;
+dl_fn->nvenc_funcs.version = func_ver;
err = dl_fn->nvenc_dl->NvEncodeAPICreateInstance(&dl_fn->nvenc_funcs);
if (err != NV_ENC_SUCCESS)
@@ -267,8 +277,8 @@ static av_cold int nvenc_open_session(AVCodecContext *avctx)
NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
NVENCSTATUS ret;
-params.version= NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
-params.apiVersion = NVENCAPI_VERSION;
+params.version= struct_ver_rt(ctx, 1); //
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER
+params.apiVersion = ctx->apiver_rt;
if (ctx->d3d11_device) {
params.device = ctx->d3d11_device;
params.deviceType = NV_ENC_DEVICE_TYPE_DIRECTX;
@@ -329,7 +339,7 @@ static int nvenc_check_cap(AVCodecContext *avctx,
NV_ENC_CAPS cap)
NV_ENC_CAPS_PARAM params= { 0 };
int ret, val = 0;
-params.version = NV_ENC_CAPS_PARAM_VER;
+params.version = struct_ver_rt(ctx, 1); // NV_ENC_CAPS_PARAM_VER;
params.capsToQuery = cap;
ret = p_nvenc->nvEncGetEncodeCaps(ctx->nvencoder,
ctx->init_encode_params.encodeGUID, ¶ms, &val);
@@ -688,7 +698,7 @@ static av_cold void set_constqp(AVCodecContext *avctx)
NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
-
+/*rc->reservedBitField1 = 0;*/
if (ctx->init_qp_p >= 0) {
rc->constQP.qpInterP = ctx->init_qp_p;
if (ctx->init_qp_i >= 0 && ctx->init_qp_b >= 0) {
@@ -1221,8 +1231,8 @@ static av_cold int nvenc_setup_encoder(AVCodecContext
*avctx)
int res = 0;
int dw, dh;
-ctx->encode_config.version = NV_ENC_CONFIG_VER;
-ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
+ctx->encode_config.version = ctx->config_ver_rt;//NV_ENC_CONFIG_VER;
+ctx->init_encode_params.version = struct_ver_rt(ctx, 5) |
(1<<31);//NV_ENC_INITIALIZE_PARAMS_VER;
ctx->init_encode_params.encodeHeight = avctx->height;
ctx->init_encode_params.encodeWidth =