From patchwork Wed Jul 15 14:34:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Bin X-Patchwork-Id: 21039 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id B3FEE44A9A1 for ; Wed, 15 Jul 2020 17:34:51 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8EFC568B0D6; Wed, 15 Jul 2020 17:34:51 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 979A46806AC for ; Wed, 15 Jul 2020 17:34:44 +0300 (EEST) Received: by mail-pf1-f178.google.com with SMTP id t11so2160038pfq.11 for ; Wed, 15 Jul 2020 07:34:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=j2zHM+dcCkRu1xhoFHdYelov72/DaEp5MCOUCiCv0lY=; b=GKUk0zqi63BzgQFWwTkvrRq+NgmUDgXoQTxkYvuE3pIZiZ/JnzWd2riy4qBn+986DR Zx4QUwYVasQ47m8VI4Exvy5A9ffsV0YP/Z0bAe0ovIIOQLBwTNF1QMr/c3Fqhxynjp46 HRuOoKfrVYp1SQVO3tn8xv/opv3lvAi2jMVqfHabCKtgDLO8EE9viPo1Gp2yVOojaZdi ucrQ2xJODdN1k25SinIRF1Tr+KwTTyorsLpVqeXJpdWwEaIx0qm7s//kxi+dwZH8Isi5 Q8NyXstzaKatbLJUNWOJ2lTB2Z1Rr44KSQADdGkkkrwxKQLx4Krok3kvkIbTdAHU47Lf 9Dew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=j2zHM+dcCkRu1xhoFHdYelov72/DaEp5MCOUCiCv0lY=; b=GR3epG5YeHUKi/g82cF9/nItzh9qhmhvRxpamDHsiCJm2DJ30WkkX9t1/FB8aMm/7Q cjlAYKH8xAySmW79QS7D67MggjgkWtPyuIO1tUj07NtnDjG4dmG2+UnxlgwAchiX5mn1 s0jd/BDVDWuPfVqLQ0pzWeS6/Y+rFlPOHp8QSA4SI1KntSm7NjnftYEgJ9K5W6PtgpvV HPPwmIR4JAq6VHE7H/XWOgNIq7uaxzup183x0HH9A7dgYDSPdKtT2kyQEWmOZhJOmese nQ1Yf8ymlR/+rtlpIL2JRao5U7lS5YgERruaOnq2StwHZt8YpXW/LjC2PMBy9IGbAu35 W5Yw== X-Gm-Message-State: AOAM533yIGpCLLuYMoBoV5YXPFZsl8d2NaHeJrPsDlYYL4JA1Kjq4j50 s9J/DagbjpCn+AGAutFXKGnNlgp2ng== X-Google-Smtp-Source: ABdhPJzUfi+4LjMYUEOxL6y63IRIFb4la4RtuUa7TUYaXMPaaGUw6lPgVRtOSpFZrpGffW79iUBP8w== X-Received: by 2002:a63:69ca:: with SMTP id e193mr37954pgc.148.1594823682021; Wed, 15 Jul 2020 07:34:42 -0700 (PDT) Received: from localhost.localdomain ([107.181.229.172]) by smtp.gmail.com with ESMTPSA id f207sm2454295pfa.107.2020.07.15.07.34.39 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Jul 2020 07:34:41 -0700 (PDT) From: wangbin To: ffmpeg-devel@ffmpeg.org Date: Wed, 15 Jul 2020 22:34:00 +0800 Message-Id: <20200715143402.18582-1-wbsecg1@gmail.com> X-Mailer: git-send-email 2.24.1 (Apple Git-126) MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/3] nvenc: use runtime api version to support old drivers X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: wang-bin Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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 = avctx->width; @@ -1231,8 +1241,8 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) nvenc_map_preset(ctx); - preset_config.version = NV_ENC_PRESET_CONFIG_VER; - preset_config.presetCfg.version = NV_ENC_CONFIG_VER; + preset_config.version = struct_ver_rt(ctx, 4) | (1<<31);// NV_ENC_PRESET_CONFIG_VER; + preset_config.presetCfg.version = ctx->config_ver_rt;//NV_ENC_CONFIG_VER; if (IS_SDK10_PRESET(ctx->preset)) { #ifdef NVENC_HAVE_NEW_PRESETS @@ -1260,7 +1270,7 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config)); - ctx->encode_config.version = NV_ENC_CONFIG_VER; + ctx->encode_config.version = ctx->config_ver_rt;//NV_ENC_CONFIG_VER; compute_dar(avctx, &dw, &dh); ctx->init_encode_params.darHeight = dh; @@ -1404,7 +1414,7 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) NVENCSTATUS nv_status; NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 }; - allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER; + allocOut.version = struct_ver_rt(ctx, 1);//NV_ENC_CREATE_BITSTREAM_BUFFER_VER; if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { ctx->surfaces[idx].in_ref = av_frame_alloc(); @@ -1420,7 +1430,7 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) return AVERROR(EINVAL); } - allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER; + allocSurf.version = struct_ver_rt(ctx, 1);//NV_ENC_CREATE_INPUT_BUFFER_VER; allocSurf.width = avctx->width; allocSurf.height = avctx->height; allocSurf.bufferFmt = ctx->surfaces[idx].format; @@ -1503,7 +1513,7 @@ static av_cold int nvenc_setup_extradata(AVCodecContext *avctx) uint32_t outSize = 0; char tmpHeader[256]; NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 }; - payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER; + payload.version = struct_ver_rt(ctx, 1);//NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER; payload.spsppsBuffer = tmpHeader; payload.inBufferSize = sizeof(tmpHeader); @@ -1535,7 +1545,7 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) /* the encoder has to be flushed before it can be closed */ if (ctx->nvencoder) { - NV_ENC_PIC_PARAMS params = { .version = NV_ENC_PIC_PARAMS_VER, + NV_ENC_PIC_PARAMS params = { .version = struct_ver_rt(ctx, 4) | (1<<31), .encodePicFlags = NV_ENC_PIC_FLAG_EOS }; res = nvenc_push_context(avctx); @@ -1747,7 +1757,7 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) if (idx < 0) return idx; - reg.version = NV_ENC_REGISTER_RESOURCE_VER; + reg.version = struct_ver_rt(ctx, 3);// NV_ENC_REGISTER_RESOURCE_VER; reg.width = frames_ctx->width; reg.height = frames_ctx->height; reg.pitch = frame->linesize[0]; @@ -1802,7 +1812,7 @@ static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame, return res; if (!ctx->registered_frames[reg_idx].mapped) { - ctx->registered_frames[reg_idx].in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER; + ctx->registered_frames[reg_idx].in_map.version = struct_ver_rt(ctx, 4);// NV_ENC_MAP_INPUT_RESOURCE_VER; ctx->registered_frames[reg_idx].in_map.registeredResource = ctx->registered_frames[reg_idx].regptr; nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &ctx->registered_frames[reg_idx].in_map); if (nv_status != NV_ENC_SUCCESS) { @@ -1822,7 +1832,7 @@ static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame, } else { NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 }; - lockBufferParams.version = NV_ENC_LOCK_INPUT_BUFFER_VER; + lockBufferParams.version = struct_ver_rt(ctx, 1);//NV_ENC_LOCK_INPUT_BUFFER_VER; lockBufferParams.inputBuffer = nvenc_frame->input_surface; nv_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams); @@ -1936,7 +1946,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur goto error; } - lock_params.version = NV_ENC_LOCK_BITSTREAM_VER; + lock_params.version = struct_ver_rt(ctx, 1);//NV_ENC_LOCK_BITSTREAM_VER; lock_params.doNotWait = 0; lock_params.outputBitstream = tmpoutsurf->output_surface; @@ -2054,7 +2064,7 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) int reconfig_bitrate = 0, reconfig_dar = 0; int dw, dh; - params.version = NV_ENC_RECONFIGURE_PARAMS_VER; + params.version = struct_ver_rt(ctx, 1) | (1<<31);//NV_ENC_RECONFIGURE_PARAMS_VER; params.reInitEncodeParams = ctx->init_encode_params; compute_dar(avctx, &dw, &dh); @@ -2148,7 +2158,7 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; NV_ENC_PIC_PARAMS pic_params = { 0 }; - pic_params.version = NV_ENC_PIC_PARAMS_VER; + pic_params.version = struct_ver_rt(ctx, 4) | (1<<31);//NV_ENC_PIC_PARAMS_VER; if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder) return AVERROR(EINVAL); diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index fb3820f7cf..6a39391276 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -146,6 +146,9 @@ typedef struct NvencContext { AVClass *avclass; + uint32_t apiver_rt; + uint32_t config_ver_rt; + NvencDynLoadFunctions nvenc_dload_funcs; NV_ENC_INITIALIZE_PARAMS init_encode_params;