1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * H.264/HEVC hardware encoding using nvidia nvenc 3cabdff1aSopenharmony_ci * Copyright (c) 2016 Timo Rothenpieler <timo@rothenpieler.org> 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "config.h" 23cabdff1aSopenharmony_ci#include "config_components.h" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "nvenc.h" 26cabdff1aSopenharmony_ci#include "hevc_sei.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include "libavutil/hwcontext_cuda.h" 29cabdff1aSopenharmony_ci#include "libavutil/hwcontext.h" 30cabdff1aSopenharmony_ci#include "libavutil/cuda_check.h" 31cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 32cabdff1aSopenharmony_ci#include "libavutil/mem.h" 33cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 34cabdff1aSopenharmony_ci#include "atsc_a53.h" 35cabdff1aSopenharmony_ci#include "encode.h" 36cabdff1aSopenharmony_ci#include "internal.h" 37cabdff1aSopenharmony_ci#include "packet_internal.h" 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci#define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x) 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci#define NVENC_CAP 0x30 42cabdff1aSopenharmony_ci#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR || \ 43cabdff1aSopenharmony_ci rc == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || \ 44cabdff1aSopenharmony_ci rc == NV_ENC_PARAMS_RC_CBR_HQ) 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ciconst enum AVPixelFormat ff_nvenc_pix_fmts[] = { 47cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P, 48cabdff1aSopenharmony_ci AV_PIX_FMT_NV12, 49cabdff1aSopenharmony_ci AV_PIX_FMT_P010, 50cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P, 51cabdff1aSopenharmony_ci AV_PIX_FMT_P016, // Truncated to 10bits 52cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P16, // Truncated to 10bits 53cabdff1aSopenharmony_ci AV_PIX_FMT_0RGB32, 54cabdff1aSopenharmony_ci AV_PIX_FMT_RGB32, 55cabdff1aSopenharmony_ci AV_PIX_FMT_0BGR32, 56cabdff1aSopenharmony_ci AV_PIX_FMT_BGR32, 57cabdff1aSopenharmony_ci AV_PIX_FMT_X2RGB10, 58cabdff1aSopenharmony_ci AV_PIX_FMT_X2BGR10, 59cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP, 60cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP16, // Truncated to 10bits 61cabdff1aSopenharmony_ci AV_PIX_FMT_CUDA, 62cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 63cabdff1aSopenharmony_ci AV_PIX_FMT_D3D11, 64cabdff1aSopenharmony_ci#endif 65cabdff1aSopenharmony_ci AV_PIX_FMT_NONE 66cabdff1aSopenharmony_ci}; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ciconst AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { 69cabdff1aSopenharmony_ci HW_CONFIG_ENCODER_FRAMES(CUDA, CUDA), 70cabdff1aSopenharmony_ci HW_CONFIG_ENCODER_DEVICE(NONE, CUDA), 71cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 72cabdff1aSopenharmony_ci HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA), 73cabdff1aSopenharmony_ci HW_CONFIG_ENCODER_DEVICE(NONE, D3D11VA), 74cabdff1aSopenharmony_ci#endif 75cabdff1aSopenharmony_ci NULL, 76cabdff1aSopenharmony_ci}; 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci#define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \ 79cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_P016 || \ 80cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_YUV444P16 || \ 81cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_GBRP16) 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci#define IS_YUV444(pix_fmt) (pix_fmt == AV_PIX_FMT_YUV444P || \ 84cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_YUV444P16 || \ 85cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_GBRP || \ 86cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_GBRP16) 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci#define IS_GBRP(pix_fmt) (pix_fmt == AV_PIX_FMT_GBRP || \ 89cabdff1aSopenharmony_ci pix_fmt == AV_PIX_FMT_GBRP16) 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_cistatic const struct { 92cabdff1aSopenharmony_ci NVENCSTATUS nverr; 93cabdff1aSopenharmony_ci int averr; 94cabdff1aSopenharmony_ci const char *desc; 95cabdff1aSopenharmony_ci} nvenc_errors[] = { 96cabdff1aSopenharmony_ci { NV_ENC_SUCCESS, 0, "success" }, 97cabdff1aSopenharmony_ci { NV_ENC_ERR_NO_ENCODE_DEVICE, AVERROR(ENOENT), "no encode device" }, 98cabdff1aSopenharmony_ci { NV_ENC_ERR_UNSUPPORTED_DEVICE, AVERROR(ENOSYS), "unsupported device" }, 99cabdff1aSopenharmony_ci { NV_ENC_ERR_INVALID_ENCODERDEVICE, AVERROR(EINVAL), "invalid encoder device" }, 100cabdff1aSopenharmony_ci { NV_ENC_ERR_INVALID_DEVICE, AVERROR(EINVAL), "invalid device" }, 101cabdff1aSopenharmony_ci { NV_ENC_ERR_DEVICE_NOT_EXIST, AVERROR(EIO), "device does not exist" }, 102cabdff1aSopenharmony_ci { NV_ENC_ERR_INVALID_PTR, AVERROR(EFAULT), "invalid ptr" }, 103cabdff1aSopenharmony_ci { NV_ENC_ERR_INVALID_EVENT, AVERROR(EINVAL), "invalid event" }, 104cabdff1aSopenharmony_ci { NV_ENC_ERR_INVALID_PARAM, AVERROR(EINVAL), "invalid param" }, 105cabdff1aSopenharmony_ci { NV_ENC_ERR_INVALID_CALL, AVERROR(EINVAL), "invalid call" }, 106cabdff1aSopenharmony_ci { NV_ENC_ERR_OUT_OF_MEMORY, AVERROR(ENOMEM), "out of memory" }, 107cabdff1aSopenharmony_ci { NV_ENC_ERR_ENCODER_NOT_INITIALIZED, AVERROR(EINVAL), "encoder not initialized" }, 108cabdff1aSopenharmony_ci { NV_ENC_ERR_UNSUPPORTED_PARAM, AVERROR(ENOSYS), "unsupported param" }, 109cabdff1aSopenharmony_ci { NV_ENC_ERR_LOCK_BUSY, AVERROR(EAGAIN), "lock busy" }, 110cabdff1aSopenharmony_ci { NV_ENC_ERR_NOT_ENOUGH_BUFFER, AVERROR_BUFFER_TOO_SMALL, "not enough buffer"}, 111cabdff1aSopenharmony_ci { NV_ENC_ERR_INVALID_VERSION, AVERROR(EINVAL), "invalid version" }, 112cabdff1aSopenharmony_ci { NV_ENC_ERR_MAP_FAILED, AVERROR(EIO), "map failed" }, 113cabdff1aSopenharmony_ci { NV_ENC_ERR_NEED_MORE_INPUT, AVERROR(EAGAIN), "need more input" }, 114cabdff1aSopenharmony_ci { NV_ENC_ERR_ENCODER_BUSY, AVERROR(EAGAIN), "encoder busy" }, 115cabdff1aSopenharmony_ci { NV_ENC_ERR_EVENT_NOT_REGISTERD, AVERROR(EBADF), "event not registered" }, 116cabdff1aSopenharmony_ci { NV_ENC_ERR_GENERIC, AVERROR_UNKNOWN, "generic error" }, 117cabdff1aSopenharmony_ci { NV_ENC_ERR_INCOMPATIBLE_CLIENT_KEY, AVERROR(EINVAL), "incompatible client key" }, 118cabdff1aSopenharmony_ci { NV_ENC_ERR_UNIMPLEMENTED, AVERROR(ENOSYS), "unimplemented" }, 119cabdff1aSopenharmony_ci { NV_ENC_ERR_RESOURCE_REGISTER_FAILED, AVERROR(EIO), "resource register failed" }, 120cabdff1aSopenharmony_ci { NV_ENC_ERR_RESOURCE_NOT_REGISTERED, AVERROR(EBADF), "resource not registered" }, 121cabdff1aSopenharmony_ci { NV_ENC_ERR_RESOURCE_NOT_MAPPED, AVERROR(EBADF), "resource not mapped" }, 122cabdff1aSopenharmony_ci}; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_cistatic int nvenc_map_error(NVENCSTATUS err, const char **desc) 125cabdff1aSopenharmony_ci{ 126cabdff1aSopenharmony_ci int i; 127cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(nvenc_errors); i++) { 128cabdff1aSopenharmony_ci if (nvenc_errors[i].nverr == err) { 129cabdff1aSopenharmony_ci if (desc) 130cabdff1aSopenharmony_ci *desc = nvenc_errors[i].desc; 131cabdff1aSopenharmony_ci return nvenc_errors[i].averr; 132cabdff1aSopenharmony_ci } 133cabdff1aSopenharmony_ci } 134cabdff1aSopenharmony_ci if (desc) 135cabdff1aSopenharmony_ci *desc = "unknown error"; 136cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 137cabdff1aSopenharmony_ci} 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_cistatic int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err, 140cabdff1aSopenharmony_ci const char *error_string) 141cabdff1aSopenharmony_ci{ 142cabdff1aSopenharmony_ci const char *desc; 143cabdff1aSopenharmony_ci const char *details = "(no details)"; 144cabdff1aSopenharmony_ci int ret = nvenc_map_error(err, &desc); 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_GETLASTERRORSTRING 147cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 148cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs; 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci if (p_nvenc && ctx->nvencoder) 151cabdff1aSopenharmony_ci details = p_nvenc->nvEncGetLastErrorString(ctx->nvencoder); 152cabdff1aSopenharmony_ci#endif 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "%s: %s (%d): %s\n", error_string, desc, err, details); 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci return ret; 157cabdff1aSopenharmony_ci} 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_citypedef struct GUIDTuple { 160cabdff1aSopenharmony_ci const GUID guid; 161cabdff1aSopenharmony_ci int flags; 162cabdff1aSopenharmony_ci} GUIDTuple; 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci#define PRESET_ALIAS(alias, name, ...) \ 165cabdff1aSopenharmony_ci [PRESET_ ## alias] = { NV_ENC_PRESET_ ## name ## _GUID, __VA_ARGS__ } 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci#define PRESET(name, ...) PRESET_ALIAS(name, name, __VA_ARGS__) 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_cistatic void nvenc_map_preset(NvencContext *ctx) 170cabdff1aSopenharmony_ci{ 171cabdff1aSopenharmony_ci GUIDTuple presets[] = { 172cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_NEW_PRESETS 173cabdff1aSopenharmony_ci PRESET(P1), 174cabdff1aSopenharmony_ci PRESET(P2), 175cabdff1aSopenharmony_ci PRESET(P3), 176cabdff1aSopenharmony_ci PRESET(P4), 177cabdff1aSopenharmony_ci PRESET(P5), 178cabdff1aSopenharmony_ci PRESET(P6), 179cabdff1aSopenharmony_ci PRESET(P7), 180cabdff1aSopenharmony_ci PRESET_ALIAS(SLOW, P7, NVENC_TWO_PASSES), 181cabdff1aSopenharmony_ci PRESET_ALIAS(MEDIUM, P4, NVENC_ONE_PASS), 182cabdff1aSopenharmony_ci PRESET_ALIAS(FAST, P1, NVENC_ONE_PASS), 183cabdff1aSopenharmony_ci // Compat aliases 184cabdff1aSopenharmony_ci PRESET_ALIAS(DEFAULT, P4, NVENC_DEPRECATED_PRESET), 185cabdff1aSopenharmony_ci PRESET_ALIAS(HP, P1, NVENC_DEPRECATED_PRESET), 186cabdff1aSopenharmony_ci PRESET_ALIAS(HQ, P7, NVENC_DEPRECATED_PRESET), 187cabdff1aSopenharmony_ci PRESET_ALIAS(BD, P5, NVENC_DEPRECATED_PRESET), 188cabdff1aSopenharmony_ci PRESET_ALIAS(LOW_LATENCY_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY), 189cabdff1aSopenharmony_ci PRESET_ALIAS(LOW_LATENCY_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY), 190cabdff1aSopenharmony_ci PRESET_ALIAS(LOW_LATENCY_HQ, P7, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY), 191cabdff1aSopenharmony_ci PRESET_ALIAS(LOSSLESS_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS), 192cabdff1aSopenharmony_ci PRESET_ALIAS(LOSSLESS_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS), 193cabdff1aSopenharmony_ci#else 194cabdff1aSopenharmony_ci PRESET(DEFAULT), 195cabdff1aSopenharmony_ci PRESET(HP), 196cabdff1aSopenharmony_ci PRESET(HQ), 197cabdff1aSopenharmony_ci PRESET(BD), 198cabdff1aSopenharmony_ci PRESET_ALIAS(SLOW, HQ, NVENC_TWO_PASSES), 199cabdff1aSopenharmony_ci PRESET_ALIAS(MEDIUM, HQ, NVENC_ONE_PASS), 200cabdff1aSopenharmony_ci PRESET_ALIAS(FAST, HP, NVENC_ONE_PASS), 201cabdff1aSopenharmony_ci PRESET(LOW_LATENCY_DEFAULT, NVENC_LOWLATENCY), 202cabdff1aSopenharmony_ci PRESET(LOW_LATENCY_HP, NVENC_LOWLATENCY), 203cabdff1aSopenharmony_ci PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY), 204cabdff1aSopenharmony_ci PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS), 205cabdff1aSopenharmony_ci PRESET(LOSSLESS_HP, NVENC_LOSSLESS), 206cabdff1aSopenharmony_ci#endif 207cabdff1aSopenharmony_ci }; 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci GUIDTuple *t = &presets[ctx->preset]; 210cabdff1aSopenharmony_ci 211cabdff1aSopenharmony_ci ctx->init_encode_params.presetGUID = t->guid; 212cabdff1aSopenharmony_ci ctx->flags = t->flags; 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_NEW_PRESETS 215cabdff1aSopenharmony_ci if (ctx->tuning_info == NV_ENC_TUNING_INFO_LOSSLESS) 216cabdff1aSopenharmony_ci ctx->flags |= NVENC_LOSSLESS; 217cabdff1aSopenharmony_ci#endif 218cabdff1aSopenharmony_ci} 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci#undef PRESET 221cabdff1aSopenharmony_ci#undef PRESET_ALIAS 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_cistatic void nvenc_print_driver_requirement(AVCodecContext *avctx, int level) 224cabdff1aSopenharmony_ci{ 225cabdff1aSopenharmony_ci#if NVENCAPI_CHECK_VERSION(11, 2) 226cabdff1aSopenharmony_ci const char *minver = "(unknown)"; 227cabdff1aSopenharmony_ci#elif NVENCAPI_CHECK_VERSION(11, 1) 228cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 229cabdff1aSopenharmony_ci const char *minver = "471.41"; 230cabdff1aSopenharmony_ci# else 231cabdff1aSopenharmony_ci const char *minver = "470.57.02"; 232cabdff1aSopenharmony_ci# endif 233cabdff1aSopenharmony_ci#elif NVENCAPI_CHECK_VERSION(11, 0) 234cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 235cabdff1aSopenharmony_ci const char *minver = "456.71"; 236cabdff1aSopenharmony_ci# else 237cabdff1aSopenharmony_ci const char *minver = "455.28"; 238cabdff1aSopenharmony_ci# endif 239cabdff1aSopenharmony_ci#elif NVENCAPI_CHECK_VERSION(10, 0) 240cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 241cabdff1aSopenharmony_ci const char *minver = "450.51"; 242cabdff1aSopenharmony_ci# else 243cabdff1aSopenharmony_ci const char *minver = "445.87"; 244cabdff1aSopenharmony_ci# endif 245cabdff1aSopenharmony_ci#elif NVENCAPI_CHECK_VERSION(9, 1) 246cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 247cabdff1aSopenharmony_ci const char *minver = "436.15"; 248cabdff1aSopenharmony_ci# else 249cabdff1aSopenharmony_ci const char *minver = "435.21"; 250cabdff1aSopenharmony_ci# endif 251cabdff1aSopenharmony_ci#elif NVENCAPI_CHECK_VERSION(9, 0) 252cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 253cabdff1aSopenharmony_ci const char *minver = "418.81"; 254cabdff1aSopenharmony_ci# else 255cabdff1aSopenharmony_ci const char *minver = "418.30"; 256cabdff1aSopenharmony_ci# endif 257cabdff1aSopenharmony_ci#elif NVENCAPI_CHECK_VERSION(8, 2) 258cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 259cabdff1aSopenharmony_ci const char *minver = "397.93"; 260cabdff1aSopenharmony_ci# else 261cabdff1aSopenharmony_ci const char *minver = "396.24"; 262cabdff1aSopenharmony_ci#endif 263cabdff1aSopenharmony_ci#elif NVENCAPI_CHECK_VERSION(8, 1) 264cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 265cabdff1aSopenharmony_ci const char *minver = "390.77"; 266cabdff1aSopenharmony_ci# else 267cabdff1aSopenharmony_ci const char *minver = "390.25"; 268cabdff1aSopenharmony_ci# endif 269cabdff1aSopenharmony_ci#else 270cabdff1aSopenharmony_ci# if defined(_WIN32) || defined(__CYGWIN__) 271cabdff1aSopenharmony_ci const char *minver = "378.66"; 272cabdff1aSopenharmony_ci# else 273cabdff1aSopenharmony_ci const char *minver = "378.13"; 274cabdff1aSopenharmony_ci# endif 275cabdff1aSopenharmony_ci#endif 276cabdff1aSopenharmony_ci av_log(avctx, level, "The minimum required Nvidia driver for nvenc is %s or newer\n", minver); 277cabdff1aSopenharmony_ci} 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_cistatic av_cold int nvenc_load_libraries(AVCodecContext *avctx) 280cabdff1aSopenharmony_ci{ 281cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 282cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 283cabdff1aSopenharmony_ci NVENCSTATUS err; 284cabdff1aSopenharmony_ci uint32_t nvenc_max_ver; 285cabdff1aSopenharmony_ci int ret; 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci ret = cuda_load_functions(&dl_fn->cuda_dl, avctx); 288cabdff1aSopenharmony_ci if (ret < 0) 289cabdff1aSopenharmony_ci return ret; 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci ret = nvenc_load_functions(&dl_fn->nvenc_dl, avctx); 292cabdff1aSopenharmony_ci if (ret < 0) { 293cabdff1aSopenharmony_ci nvenc_print_driver_requirement(avctx, AV_LOG_ERROR); 294cabdff1aSopenharmony_ci return ret; 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci err = dl_fn->nvenc_dl->NvEncodeAPIGetMaxSupportedVersion(&nvenc_max_ver); 298cabdff1aSopenharmony_ci if (err != NV_ENC_SUCCESS) 299cabdff1aSopenharmony_ci return nvenc_print_error(avctx, err, "Failed to query nvenc max version"); 300cabdff1aSopenharmony_ci 301cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Loaded Nvenc version %d.%d\n", nvenc_max_ver >> 4, nvenc_max_ver & 0xf); 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci if ((NVENCAPI_MAJOR_VERSION << 4 | NVENCAPI_MINOR_VERSION) > nvenc_max_ver) { 304cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Driver does not support the required nvenc API version. " 305cabdff1aSopenharmony_ci "Required: %d.%d Found: %d.%d\n", 306cabdff1aSopenharmony_ci NVENCAPI_MAJOR_VERSION, NVENCAPI_MINOR_VERSION, 307cabdff1aSopenharmony_ci nvenc_max_ver >> 4, nvenc_max_ver & 0xf); 308cabdff1aSopenharmony_ci nvenc_print_driver_requirement(avctx, AV_LOG_ERROR); 309cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 310cabdff1aSopenharmony_ci } 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_ci dl_fn->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER; 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ci err = dl_fn->nvenc_dl->NvEncodeAPICreateInstance(&dl_fn->nvenc_funcs); 315cabdff1aSopenharmony_ci if (err != NV_ENC_SUCCESS) 316cabdff1aSopenharmony_ci return nvenc_print_error(avctx, err, "Failed to create nvenc instance"); 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Nvenc initialized successfully\n"); 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_ci return 0; 321cabdff1aSopenharmony_ci} 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_cistatic int nvenc_push_context(AVCodecContext *avctx) 324cabdff1aSopenharmony_ci{ 325cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 326cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci if (ctx->d3d11_device) 329cabdff1aSopenharmony_ci return 0; 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ci return CHECK_CU(dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context)); 332cabdff1aSopenharmony_ci} 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_cistatic int nvenc_pop_context(AVCodecContext *avctx) 335cabdff1aSopenharmony_ci{ 336cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 337cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 338cabdff1aSopenharmony_ci CUcontext dummy; 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_ci if (ctx->d3d11_device) 341cabdff1aSopenharmony_ci return 0; 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci return CHECK_CU(dl_fn->cuda_dl->cuCtxPopCurrent(&dummy)); 344cabdff1aSopenharmony_ci} 345cabdff1aSopenharmony_ci 346cabdff1aSopenharmony_cistatic av_cold int nvenc_open_session(AVCodecContext *avctx) 347cabdff1aSopenharmony_ci{ 348cabdff1aSopenharmony_ci NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = { 0 }; 349cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 350cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs; 351cabdff1aSopenharmony_ci NVENCSTATUS ret; 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ci params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER; 354cabdff1aSopenharmony_ci params.apiVersion = NVENCAPI_VERSION; 355cabdff1aSopenharmony_ci if (ctx->d3d11_device) { 356cabdff1aSopenharmony_ci params.device = ctx->d3d11_device; 357cabdff1aSopenharmony_ci params.deviceType = NV_ENC_DEVICE_TYPE_DIRECTX; 358cabdff1aSopenharmony_ci } else { 359cabdff1aSopenharmony_ci params.device = ctx->cu_context; 360cabdff1aSopenharmony_ci params.deviceType = NV_ENC_DEVICE_TYPE_CUDA; 361cabdff1aSopenharmony_ci } 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_ci ret = p_nvenc->nvEncOpenEncodeSessionEx(¶ms, &ctx->nvencoder); 364cabdff1aSopenharmony_ci if (ret != NV_ENC_SUCCESS) { 365cabdff1aSopenharmony_ci ctx->nvencoder = NULL; 366cabdff1aSopenharmony_ci return nvenc_print_error(avctx, ret, "OpenEncodeSessionEx failed"); 367cabdff1aSopenharmony_ci } 368cabdff1aSopenharmony_ci 369cabdff1aSopenharmony_ci return 0; 370cabdff1aSopenharmony_ci} 371cabdff1aSopenharmony_ci 372cabdff1aSopenharmony_cistatic int nvenc_check_codec_support(AVCodecContext *avctx) 373cabdff1aSopenharmony_ci{ 374cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 375cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs; 376cabdff1aSopenharmony_ci int i, ret, count = 0; 377cabdff1aSopenharmony_ci GUID *guids = NULL; 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_ci ret = p_nvenc->nvEncGetEncodeGUIDCount(ctx->nvencoder, &count); 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_ci if (ret != NV_ENC_SUCCESS || !count) 382cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 383cabdff1aSopenharmony_ci 384cabdff1aSopenharmony_ci guids = av_malloc(count * sizeof(GUID)); 385cabdff1aSopenharmony_ci if (!guids) 386cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 387cabdff1aSopenharmony_ci 388cabdff1aSopenharmony_ci ret = p_nvenc->nvEncGetEncodeGUIDs(ctx->nvencoder, guids, count, &count); 389cabdff1aSopenharmony_ci if (ret != NV_ENC_SUCCESS) { 390cabdff1aSopenharmony_ci ret = AVERROR(ENOSYS); 391cabdff1aSopenharmony_ci goto fail; 392cabdff1aSopenharmony_ci } 393cabdff1aSopenharmony_ci 394cabdff1aSopenharmony_ci ret = AVERROR(ENOSYS); 395cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 396cabdff1aSopenharmony_ci if (!memcmp(&guids[i], &ctx->init_encode_params.encodeGUID, sizeof(*guids))) { 397cabdff1aSopenharmony_ci ret = 0; 398cabdff1aSopenharmony_ci break; 399cabdff1aSopenharmony_ci } 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_cifail: 403cabdff1aSopenharmony_ci av_free(guids); 404cabdff1aSopenharmony_ci 405cabdff1aSopenharmony_ci return ret; 406cabdff1aSopenharmony_ci} 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_cistatic int nvenc_check_cap(AVCodecContext *avctx, NV_ENC_CAPS cap) 409cabdff1aSopenharmony_ci{ 410cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 411cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs; 412cabdff1aSopenharmony_ci NV_ENC_CAPS_PARAM params = { 0 }; 413cabdff1aSopenharmony_ci int ret, val = 0; 414cabdff1aSopenharmony_ci 415cabdff1aSopenharmony_ci params.version = NV_ENC_CAPS_PARAM_VER; 416cabdff1aSopenharmony_ci params.capsToQuery = cap; 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_ci ret = p_nvenc->nvEncGetEncodeCaps(ctx->nvencoder, ctx->init_encode_params.encodeGUID, ¶ms, &val); 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci if (ret == NV_ENC_SUCCESS) 421cabdff1aSopenharmony_ci return val; 422cabdff1aSopenharmony_ci return 0; 423cabdff1aSopenharmony_ci} 424cabdff1aSopenharmony_ci 425cabdff1aSopenharmony_cistatic int nvenc_check_capabilities(AVCodecContext *avctx) 426cabdff1aSopenharmony_ci{ 427cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 428cabdff1aSopenharmony_ci int ret; 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci ret = nvenc_check_codec_support(avctx); 431cabdff1aSopenharmony_ci if (ret < 0) { 432cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Codec not supported\n"); 433cabdff1aSopenharmony_ci return ret; 434cabdff1aSopenharmony_ci } 435cabdff1aSopenharmony_ci 436cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE); 437cabdff1aSopenharmony_ci if (IS_YUV444(ctx->data_pix_fmt) && ret <= 0) { 438cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "YUV444P not supported\n"); 439cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 440cabdff1aSopenharmony_ci } 441cabdff1aSopenharmony_ci 442cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE); 443cabdff1aSopenharmony_ci if (ctx->flags & NVENC_LOSSLESS && ret <= 0) { 444cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Lossless encoding not supported\n"); 445cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 446cabdff1aSopenharmony_ci } 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_WIDTH_MAX); 449cabdff1aSopenharmony_ci if (ret < avctx->width) { 450cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Width %d exceeds %d\n", 451cabdff1aSopenharmony_ci avctx->width, ret); 452cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 453cabdff1aSopenharmony_ci } 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_HEIGHT_MAX); 456cabdff1aSopenharmony_ci if (ret < avctx->height) { 457cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Height %d exceeds %d\n", 458cabdff1aSopenharmony_ci avctx->height, ret); 459cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 460cabdff1aSopenharmony_ci } 461cabdff1aSopenharmony_ci 462cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_NUM_MAX_BFRAMES); 463cabdff1aSopenharmony_ci if (ret < avctx->max_b_frames) { 464cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Max B-frames %d exceed %d\n", 465cabdff1aSopenharmony_ci avctx->max_b_frames, ret); 466cabdff1aSopenharmony_ci 467cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 468cabdff1aSopenharmony_ci } 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_FIELD_ENCODING); 471cabdff1aSopenharmony_ci if (ret < 1 && avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { 472cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 473cabdff1aSopenharmony_ci "Interlaced encoding is not supported. Supported level: %d\n", 474cabdff1aSopenharmony_ci ret); 475cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 476cabdff1aSopenharmony_ci } 477cabdff1aSopenharmony_ci 478cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_10BIT_ENCODE); 479cabdff1aSopenharmony_ci if (IS_10BIT(ctx->data_pix_fmt) && ret <= 0) { 480cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "10 bit encode not supported\n"); 481cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 482cabdff1aSopenharmony_ci } 483cabdff1aSopenharmony_ci 484cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOOKAHEAD); 485cabdff1aSopenharmony_ci if (ctx->rc_lookahead > 0 && ret <= 0) { 486cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "RC lookahead not supported\n"); 487cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 488cabdff1aSopenharmony_ci } 489cabdff1aSopenharmony_ci 490cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_AQ); 491cabdff1aSopenharmony_ci if (ctx->temporal_aq > 0 && ret <= 0) { 492cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Temporal AQ not supported\n"); 493cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 494cabdff1aSopenharmony_ci } 495cabdff1aSopenharmony_ci 496cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_WEIGHTED_PREDICTION); 497cabdff1aSopenharmony_ci if (ctx->weighted_pred > 0 && ret <= 0) { 498cabdff1aSopenharmony_ci av_log (avctx, AV_LOG_WARNING, "Weighted Prediction not supported\n"); 499cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 500cabdff1aSopenharmony_ci } 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_CABAC); 503cabdff1aSopenharmony_ci if (ctx->coder == NV_ENC_H264_ENTROPY_CODING_MODE_CABAC && ret <= 0) { 504cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "CABAC entropy coding not supported\n"); 505cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 506cabdff1aSopenharmony_ci } 507cabdff1aSopenharmony_ci 508cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_BFRAME_REF_MODE 509cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE); 510cabdff1aSopenharmony_ci if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1 && ret != 3) { 511cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Each B frame as reference is not supported\n"); 512cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 513cabdff1aSopenharmony_ci } else if (ctx->b_ref_mode != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) { 514cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "B frames as references are not supported\n"); 515cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 516cabdff1aSopenharmony_ci } 517cabdff1aSopenharmony_ci#else 518cabdff1aSopenharmony_ci if (ctx->b_ref_mode != 0) { 519cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "B frames as references need SDK 8.1 at build time\n"); 520cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 521cabdff1aSopenharmony_ci } 522cabdff1aSopenharmony_ci#endif 523cabdff1aSopenharmony_ci 524cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES 525cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_MULTIPLE_REF_FRAMES); 526cabdff1aSopenharmony_ci if(avctx->refs != NV_ENC_NUM_REF_FRAMES_AUTOSELECT && ret <= 0) { 527cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Multiple reference frames are not supported by the device\n"); 528cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 529cabdff1aSopenharmony_ci } 530cabdff1aSopenharmony_ci#else 531cabdff1aSopenharmony_ci if(avctx->refs != 0) { 532cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Multiple reference frames need SDK 9.1 at build time\n"); 533cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 534cabdff1aSopenharmony_ci } 535cabdff1aSopenharmony_ci#endif 536cabdff1aSopenharmony_ci 537cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH 538cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SINGLE_SLICE_INTRA_REFRESH); 539cabdff1aSopenharmony_ci if(ctx->single_slice_intra_refresh && ret <= 0) { 540cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Single slice intra refresh not supported by the device\n"); 541cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 542cabdff1aSopenharmony_ci } 543cabdff1aSopenharmony_ci#else 544cabdff1aSopenharmony_ci if(ctx->single_slice_intra_refresh) { 545cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Single slice intra refresh needs SDK 11.1 at build time\n"); 546cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 547cabdff1aSopenharmony_ci } 548cabdff1aSopenharmony_ci#endif 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_INTRA_REFRESH); 551cabdff1aSopenharmony_ci if((ctx->intra_refresh || ctx->single_slice_intra_refresh) && ret <= 0) { 552cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Intra refresh not supported by the device\n"); 553cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 554cabdff1aSopenharmony_ci } 555cabdff1aSopenharmony_ci 556cabdff1aSopenharmony_ci#ifndef NVENC_HAVE_HEVC_CONSTRAINED_ENCODING 557cabdff1aSopenharmony_ci if (ctx->constrained_encoding && avctx->codec->id == AV_CODEC_ID_HEVC) { 558cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "HEVC constrained encoding needs SDK 10.0 at build time\n"); 559cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 560cabdff1aSopenharmony_ci } 561cabdff1aSopenharmony_ci#endif 562cabdff1aSopenharmony_ci 563cabdff1aSopenharmony_ci ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_CONSTRAINED_ENCODING); 564cabdff1aSopenharmony_ci if(ctx->constrained_encoding && ret <= 0) { 565cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Constrained encoding not supported by the device\n"); 566cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 567cabdff1aSopenharmony_ci } 568cabdff1aSopenharmony_ci 569cabdff1aSopenharmony_ci ctx->support_dyn_bitrate = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE); 570cabdff1aSopenharmony_ci 571cabdff1aSopenharmony_ci return 0; 572cabdff1aSopenharmony_ci} 573cabdff1aSopenharmony_ci 574cabdff1aSopenharmony_cistatic av_cold int nvenc_check_device(AVCodecContext *avctx, int idx) 575cabdff1aSopenharmony_ci{ 576cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 577cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 578cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 579cabdff1aSopenharmony_ci char name[128] = { 0}; 580cabdff1aSopenharmony_ci int major, minor, ret; 581cabdff1aSopenharmony_ci CUdevice cu_device; 582cabdff1aSopenharmony_ci int loglevel = AV_LOG_VERBOSE; 583cabdff1aSopenharmony_ci 584cabdff1aSopenharmony_ci if (ctx->device == LIST_DEVICES) 585cabdff1aSopenharmony_ci loglevel = AV_LOG_INFO; 586cabdff1aSopenharmony_ci 587cabdff1aSopenharmony_ci ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceGet(&cu_device, idx)); 588cabdff1aSopenharmony_ci if (ret < 0) 589cabdff1aSopenharmony_ci return ret; 590cabdff1aSopenharmony_ci 591cabdff1aSopenharmony_ci ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceGetName(name, sizeof(name), cu_device)); 592cabdff1aSopenharmony_ci if (ret < 0) 593cabdff1aSopenharmony_ci return ret; 594cabdff1aSopenharmony_ci 595cabdff1aSopenharmony_ci ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceComputeCapability(&major, &minor, cu_device)); 596cabdff1aSopenharmony_ci if (ret < 0) 597cabdff1aSopenharmony_ci return ret; 598cabdff1aSopenharmony_ci 599cabdff1aSopenharmony_ci av_log(avctx, loglevel, "[ GPU #%d - < %s > has Compute SM %d.%d ]\n", idx, name, major, minor); 600cabdff1aSopenharmony_ci if (((major << 4) | minor) < NVENC_CAP) { 601cabdff1aSopenharmony_ci av_log(avctx, loglevel, "does not support NVENC\n"); 602cabdff1aSopenharmony_ci goto fail; 603cabdff1aSopenharmony_ci } 604cabdff1aSopenharmony_ci 605cabdff1aSopenharmony_ci if (ctx->device != idx && ctx->device != ANY_DEVICE) 606cabdff1aSopenharmony_ci return -1; 607cabdff1aSopenharmony_ci 608cabdff1aSopenharmony_ci ret = CHECK_CU(dl_fn->cuda_dl->cuCtxCreate(&ctx->cu_context_internal, 0, cu_device)); 609cabdff1aSopenharmony_ci if (ret < 0) 610cabdff1aSopenharmony_ci goto fail; 611cabdff1aSopenharmony_ci 612cabdff1aSopenharmony_ci ctx->cu_context = ctx->cu_context_internal; 613cabdff1aSopenharmony_ci ctx->cu_stream = NULL; 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci if ((ret = nvenc_pop_context(avctx)) < 0) 616cabdff1aSopenharmony_ci goto fail2; 617cabdff1aSopenharmony_ci 618cabdff1aSopenharmony_ci if ((ret = nvenc_open_session(avctx)) < 0) 619cabdff1aSopenharmony_ci goto fail2; 620cabdff1aSopenharmony_ci 621cabdff1aSopenharmony_ci if ((ret = nvenc_check_capabilities(avctx)) < 0) 622cabdff1aSopenharmony_ci goto fail3; 623cabdff1aSopenharmony_ci 624cabdff1aSopenharmony_ci av_log(avctx, loglevel, "supports NVENC\n"); 625cabdff1aSopenharmony_ci 626cabdff1aSopenharmony_ci dl_fn->nvenc_device_count++; 627cabdff1aSopenharmony_ci 628cabdff1aSopenharmony_ci if (ctx->device == idx || ctx->device == ANY_DEVICE) 629cabdff1aSopenharmony_ci return 0; 630cabdff1aSopenharmony_ci 631cabdff1aSopenharmony_cifail3: 632cabdff1aSopenharmony_ci if ((ret = nvenc_push_context(avctx)) < 0) 633cabdff1aSopenharmony_ci return ret; 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci p_nvenc->nvEncDestroyEncoder(ctx->nvencoder); 636cabdff1aSopenharmony_ci ctx->nvencoder = NULL; 637cabdff1aSopenharmony_ci 638cabdff1aSopenharmony_ci if ((ret = nvenc_pop_context(avctx)) < 0) 639cabdff1aSopenharmony_ci return ret; 640cabdff1aSopenharmony_ci 641cabdff1aSopenharmony_cifail2: 642cabdff1aSopenharmony_ci CHECK_CU(dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal)); 643cabdff1aSopenharmony_ci ctx->cu_context_internal = NULL; 644cabdff1aSopenharmony_ci 645cabdff1aSopenharmony_cifail: 646cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 647cabdff1aSopenharmony_ci} 648cabdff1aSopenharmony_ci 649cabdff1aSopenharmony_cistatic av_cold int nvenc_setup_device(AVCodecContext *avctx) 650cabdff1aSopenharmony_ci{ 651cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 652cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 653cabdff1aSopenharmony_ci 654cabdff1aSopenharmony_ci switch (avctx->codec->id) { 655cabdff1aSopenharmony_ci case AV_CODEC_ID_H264: 656cabdff1aSopenharmony_ci ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_H264_GUID; 657cabdff1aSopenharmony_ci break; 658cabdff1aSopenharmony_ci case AV_CODEC_ID_HEVC: 659cabdff1aSopenharmony_ci ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_HEVC_GUID; 660cabdff1aSopenharmony_ci break; 661cabdff1aSopenharmony_ci default: 662cabdff1aSopenharmony_ci return AVERROR_BUG; 663cabdff1aSopenharmony_ci } 664cabdff1aSopenharmony_ci 665cabdff1aSopenharmony_ci nvenc_map_preset(ctx); 666cabdff1aSopenharmony_ci 667cabdff1aSopenharmony_ci if (ctx->flags & NVENC_DEPRECATED_PRESET) 668cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "The selected preset is deprecated. Use p1 to p7 + -tune or fast/medium/slow.\n"); 669cabdff1aSopenharmony_ci 670cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11 || avctx->hw_frames_ctx || avctx->hw_device_ctx) { 671cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx; 672cabdff1aSopenharmony_ci AVHWDeviceContext *hwdev_ctx; 673cabdff1aSopenharmony_ci AVCUDADeviceContext *cuda_device_hwctx = NULL; 674cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 675cabdff1aSopenharmony_ci AVD3D11VADeviceContext *d3d11_device_hwctx = NULL; 676cabdff1aSopenharmony_ci#endif 677cabdff1aSopenharmony_ci int ret; 678cabdff1aSopenharmony_ci 679cabdff1aSopenharmony_ci if (avctx->hw_frames_ctx) { 680cabdff1aSopenharmony_ci frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 681cabdff1aSopenharmony_ci if (frames_ctx->format == AV_PIX_FMT_CUDA) 682cabdff1aSopenharmony_ci cuda_device_hwctx = frames_ctx->device_ctx->hwctx; 683cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 684cabdff1aSopenharmony_ci else if (frames_ctx->format == AV_PIX_FMT_D3D11) 685cabdff1aSopenharmony_ci d3d11_device_hwctx = frames_ctx->device_ctx->hwctx; 686cabdff1aSopenharmony_ci#endif 687cabdff1aSopenharmony_ci else 688cabdff1aSopenharmony_ci return AVERROR(EINVAL); 689cabdff1aSopenharmony_ci } else if (avctx->hw_device_ctx) { 690cabdff1aSopenharmony_ci hwdev_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data; 691cabdff1aSopenharmony_ci if (hwdev_ctx->type == AV_HWDEVICE_TYPE_CUDA) 692cabdff1aSopenharmony_ci cuda_device_hwctx = hwdev_ctx->hwctx; 693cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 694cabdff1aSopenharmony_ci else if (hwdev_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) 695cabdff1aSopenharmony_ci d3d11_device_hwctx = hwdev_ctx->hwctx; 696cabdff1aSopenharmony_ci#endif 697cabdff1aSopenharmony_ci else 698cabdff1aSopenharmony_ci return AVERROR(EINVAL); 699cabdff1aSopenharmony_ci } else { 700cabdff1aSopenharmony_ci return AVERROR(EINVAL); 701cabdff1aSopenharmony_ci } 702cabdff1aSopenharmony_ci 703cabdff1aSopenharmony_ci if (cuda_device_hwctx) { 704cabdff1aSopenharmony_ci ctx->cu_context = cuda_device_hwctx->cuda_ctx; 705cabdff1aSopenharmony_ci ctx->cu_stream = cuda_device_hwctx->stream; 706cabdff1aSopenharmony_ci } 707cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 708cabdff1aSopenharmony_ci else if (d3d11_device_hwctx) { 709cabdff1aSopenharmony_ci ctx->d3d11_device = d3d11_device_hwctx->device; 710cabdff1aSopenharmony_ci ID3D11Device_AddRef(ctx->d3d11_device); 711cabdff1aSopenharmony_ci } 712cabdff1aSopenharmony_ci#endif 713cabdff1aSopenharmony_ci 714cabdff1aSopenharmony_ci ret = nvenc_open_session(avctx); 715cabdff1aSopenharmony_ci if (ret < 0) 716cabdff1aSopenharmony_ci return ret; 717cabdff1aSopenharmony_ci 718cabdff1aSopenharmony_ci ret = nvenc_check_capabilities(avctx); 719cabdff1aSopenharmony_ci if (ret < 0) { 720cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_FATAL, "Provided device doesn't support required NVENC features\n"); 721cabdff1aSopenharmony_ci return ret; 722cabdff1aSopenharmony_ci } 723cabdff1aSopenharmony_ci } else { 724cabdff1aSopenharmony_ci int i, nb_devices = 0; 725cabdff1aSopenharmony_ci 726cabdff1aSopenharmony_ci if (CHECK_CU(dl_fn->cuda_dl->cuInit(0)) < 0) 727cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 728cabdff1aSopenharmony_ci 729cabdff1aSopenharmony_ci if (CHECK_CU(dl_fn->cuda_dl->cuDeviceGetCount(&nb_devices)) < 0) 730cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 731cabdff1aSopenharmony_ci 732cabdff1aSopenharmony_ci if (!nb_devices) { 733cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_FATAL, "No CUDA capable devices found\n"); 734cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 735cabdff1aSopenharmony_ci } 736cabdff1aSopenharmony_ci 737cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "%d CUDA capable devices found\n", nb_devices); 738cabdff1aSopenharmony_ci 739cabdff1aSopenharmony_ci dl_fn->nvenc_device_count = 0; 740cabdff1aSopenharmony_ci for (i = 0; i < nb_devices; ++i) { 741cabdff1aSopenharmony_ci if ((nvenc_check_device(avctx, i)) >= 0 && ctx->device != LIST_DEVICES) 742cabdff1aSopenharmony_ci return 0; 743cabdff1aSopenharmony_ci } 744cabdff1aSopenharmony_ci 745cabdff1aSopenharmony_ci if (ctx->device == LIST_DEVICES) 746cabdff1aSopenharmony_ci return AVERROR_EXIT; 747cabdff1aSopenharmony_ci 748cabdff1aSopenharmony_ci if (!dl_fn->nvenc_device_count) { 749cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_FATAL, "No capable devices found\n"); 750cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 751cabdff1aSopenharmony_ci } 752cabdff1aSopenharmony_ci 753cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_FATAL, "Requested GPU %d, but only %d GPUs are available!\n", ctx->device, nb_devices); 754cabdff1aSopenharmony_ci return AVERROR(EINVAL); 755cabdff1aSopenharmony_ci } 756cabdff1aSopenharmony_ci 757cabdff1aSopenharmony_ci return 0; 758cabdff1aSopenharmony_ci} 759cabdff1aSopenharmony_ci 760cabdff1aSopenharmony_cistatic av_cold void set_constqp(AVCodecContext *avctx) 761cabdff1aSopenharmony_ci{ 762cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 763cabdff1aSopenharmony_ci NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams; 764cabdff1aSopenharmony_ci 765cabdff1aSopenharmony_ci rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; 766cabdff1aSopenharmony_ci 767cabdff1aSopenharmony_ci if (ctx->init_qp_p >= 0) { 768cabdff1aSopenharmony_ci rc->constQP.qpInterP = ctx->init_qp_p; 769cabdff1aSopenharmony_ci if (ctx->init_qp_i >= 0 && ctx->init_qp_b >= 0) { 770cabdff1aSopenharmony_ci rc->constQP.qpIntra = ctx->init_qp_i; 771cabdff1aSopenharmony_ci rc->constQP.qpInterB = ctx->init_qp_b; 772cabdff1aSopenharmony_ci } else if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) { 773cabdff1aSopenharmony_ci rc->constQP.qpIntra = av_clip( 774cabdff1aSopenharmony_ci rc->constQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51); 775cabdff1aSopenharmony_ci rc->constQP.qpInterB = av_clip( 776cabdff1aSopenharmony_ci rc->constQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51); 777cabdff1aSopenharmony_ci } else { 778cabdff1aSopenharmony_ci rc->constQP.qpIntra = rc->constQP.qpInterP; 779cabdff1aSopenharmony_ci rc->constQP.qpInterB = rc->constQP.qpInterP; 780cabdff1aSopenharmony_ci } 781cabdff1aSopenharmony_ci } else if (ctx->cqp >= 0) { 782cabdff1aSopenharmony_ci rc->constQP.qpInterP = rc->constQP.qpInterB = rc->constQP.qpIntra = ctx->cqp; 783cabdff1aSopenharmony_ci if (avctx->b_quant_factor != 0.0) 784cabdff1aSopenharmony_ci rc->constQP.qpInterB = av_clip(ctx->cqp * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51); 785cabdff1aSopenharmony_ci if (avctx->i_quant_factor != 0.0) 786cabdff1aSopenharmony_ci rc->constQP.qpIntra = av_clip(ctx->cqp * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51); 787cabdff1aSopenharmony_ci } 788cabdff1aSopenharmony_ci 789cabdff1aSopenharmony_ci avctx->qmin = -1; 790cabdff1aSopenharmony_ci avctx->qmax = -1; 791cabdff1aSopenharmony_ci} 792cabdff1aSopenharmony_ci 793cabdff1aSopenharmony_cistatic av_cold void set_vbr(AVCodecContext *avctx) 794cabdff1aSopenharmony_ci{ 795cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 796cabdff1aSopenharmony_ci NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams; 797cabdff1aSopenharmony_ci int qp_inter_p; 798cabdff1aSopenharmony_ci 799cabdff1aSopenharmony_ci if (avctx->qmin >= 0 && avctx->qmax >= 0) { 800cabdff1aSopenharmony_ci rc->enableMinQP = 1; 801cabdff1aSopenharmony_ci rc->enableMaxQP = 1; 802cabdff1aSopenharmony_ci 803cabdff1aSopenharmony_ci rc->minQP.qpInterB = avctx->qmin; 804cabdff1aSopenharmony_ci rc->minQP.qpInterP = avctx->qmin; 805cabdff1aSopenharmony_ci rc->minQP.qpIntra = avctx->qmin; 806cabdff1aSopenharmony_ci 807cabdff1aSopenharmony_ci rc->maxQP.qpInterB = avctx->qmax; 808cabdff1aSopenharmony_ci rc->maxQP.qpInterP = avctx->qmax; 809cabdff1aSopenharmony_ci rc->maxQP.qpIntra = avctx->qmax; 810cabdff1aSopenharmony_ci 811cabdff1aSopenharmony_ci qp_inter_p = (avctx->qmax + 3 * avctx->qmin) / 4; // biased towards Qmin 812cabdff1aSopenharmony_ci } else if (avctx->qmin >= 0) { 813cabdff1aSopenharmony_ci rc->enableMinQP = 1; 814cabdff1aSopenharmony_ci 815cabdff1aSopenharmony_ci rc->minQP.qpInterB = avctx->qmin; 816cabdff1aSopenharmony_ci rc->minQP.qpInterP = avctx->qmin; 817cabdff1aSopenharmony_ci rc->minQP.qpIntra = avctx->qmin; 818cabdff1aSopenharmony_ci 819cabdff1aSopenharmony_ci qp_inter_p = avctx->qmin; 820cabdff1aSopenharmony_ci } else { 821cabdff1aSopenharmony_ci qp_inter_p = 26; // default to 26 822cabdff1aSopenharmony_ci } 823cabdff1aSopenharmony_ci 824cabdff1aSopenharmony_ci rc->enableInitialRCQP = 1; 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_ci if (ctx->init_qp_p < 0) { 827cabdff1aSopenharmony_ci rc->initialRCQP.qpInterP = qp_inter_p; 828cabdff1aSopenharmony_ci } else { 829cabdff1aSopenharmony_ci rc->initialRCQP.qpInterP = ctx->init_qp_p; 830cabdff1aSopenharmony_ci } 831cabdff1aSopenharmony_ci 832cabdff1aSopenharmony_ci if (ctx->init_qp_i < 0) { 833cabdff1aSopenharmony_ci if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) { 834cabdff1aSopenharmony_ci rc->initialRCQP.qpIntra = av_clip( 835cabdff1aSopenharmony_ci rc->initialRCQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51); 836cabdff1aSopenharmony_ci } else { 837cabdff1aSopenharmony_ci rc->initialRCQP.qpIntra = rc->initialRCQP.qpInterP; 838cabdff1aSopenharmony_ci } 839cabdff1aSopenharmony_ci } else { 840cabdff1aSopenharmony_ci rc->initialRCQP.qpIntra = ctx->init_qp_i; 841cabdff1aSopenharmony_ci } 842cabdff1aSopenharmony_ci 843cabdff1aSopenharmony_ci if (ctx->init_qp_b < 0) { 844cabdff1aSopenharmony_ci if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) { 845cabdff1aSopenharmony_ci rc->initialRCQP.qpInterB = av_clip( 846cabdff1aSopenharmony_ci rc->initialRCQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51); 847cabdff1aSopenharmony_ci } else { 848cabdff1aSopenharmony_ci rc->initialRCQP.qpInterB = rc->initialRCQP.qpInterP; 849cabdff1aSopenharmony_ci } 850cabdff1aSopenharmony_ci } else { 851cabdff1aSopenharmony_ci rc->initialRCQP.qpInterB = ctx->init_qp_b; 852cabdff1aSopenharmony_ci } 853cabdff1aSopenharmony_ci} 854cabdff1aSopenharmony_ci 855cabdff1aSopenharmony_cistatic av_cold void set_lossless(AVCodecContext *avctx) 856cabdff1aSopenharmony_ci{ 857cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 858cabdff1aSopenharmony_ci NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams; 859cabdff1aSopenharmony_ci 860cabdff1aSopenharmony_ci rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; 861cabdff1aSopenharmony_ci rc->constQP.qpInterB = 0; 862cabdff1aSopenharmony_ci rc->constQP.qpInterP = 0; 863cabdff1aSopenharmony_ci rc->constQP.qpIntra = 0; 864cabdff1aSopenharmony_ci 865cabdff1aSopenharmony_ci avctx->qmin = -1; 866cabdff1aSopenharmony_ci avctx->qmax = -1; 867cabdff1aSopenharmony_ci} 868cabdff1aSopenharmony_ci 869cabdff1aSopenharmony_cistatic void nvenc_override_rate_control(AVCodecContext *avctx) 870cabdff1aSopenharmony_ci{ 871cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 872cabdff1aSopenharmony_ci NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams; 873cabdff1aSopenharmony_ci 874cabdff1aSopenharmony_ci switch (ctx->rc) { 875cabdff1aSopenharmony_ci case NV_ENC_PARAMS_RC_CONSTQP: 876cabdff1aSopenharmony_ci set_constqp(avctx); 877cabdff1aSopenharmony_ci return; 878cabdff1aSopenharmony_ci case NV_ENC_PARAMS_RC_VBR_MINQP: 879cabdff1aSopenharmony_ci if (avctx->qmin < 0) { 880cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 881cabdff1aSopenharmony_ci "The variable bitrate rate-control requires " 882cabdff1aSopenharmony_ci "the 'qmin' option set.\n"); 883cabdff1aSopenharmony_ci set_vbr(avctx); 884cabdff1aSopenharmony_ci return; 885cabdff1aSopenharmony_ci } 886cabdff1aSopenharmony_ci /* fall through */ 887cabdff1aSopenharmony_ci case NV_ENC_PARAMS_RC_VBR_HQ: 888cabdff1aSopenharmony_ci case NV_ENC_PARAMS_RC_VBR: 889cabdff1aSopenharmony_ci set_vbr(avctx); 890cabdff1aSopenharmony_ci break; 891cabdff1aSopenharmony_ci case NV_ENC_PARAMS_RC_CBR: 892cabdff1aSopenharmony_ci case NV_ENC_PARAMS_RC_CBR_HQ: 893cabdff1aSopenharmony_ci case NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ: 894cabdff1aSopenharmony_ci break; 895cabdff1aSopenharmony_ci } 896cabdff1aSopenharmony_ci 897cabdff1aSopenharmony_ci rc->rateControlMode = ctx->rc; 898cabdff1aSopenharmony_ci} 899cabdff1aSopenharmony_ci 900cabdff1aSopenharmony_cistatic av_cold int nvenc_recalc_surfaces(AVCodecContext *avctx) 901cabdff1aSopenharmony_ci{ 902cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 903cabdff1aSopenharmony_ci // default minimum of 4 surfaces 904cabdff1aSopenharmony_ci // multiply by 2 for number of NVENCs on gpu (hardcode to 2) 905cabdff1aSopenharmony_ci // another multiply by 2 to avoid blocking next PBB group 906cabdff1aSopenharmony_ci int nb_surfaces = FFMAX(4, ctx->encode_config.frameIntervalP * 2 * 2); 907cabdff1aSopenharmony_ci 908cabdff1aSopenharmony_ci // lookahead enabled 909cabdff1aSopenharmony_ci if (ctx->rc_lookahead > 0) { 910cabdff1aSopenharmony_ci // +1 is to account for lkd_bound calculation later 911cabdff1aSopenharmony_ci // +4 is to allow sufficient pipelining with lookahead 912cabdff1aSopenharmony_ci nb_surfaces = FFMAX(1, FFMAX(nb_surfaces, ctx->rc_lookahead + ctx->encode_config.frameIntervalP + 1 + 4)); 913cabdff1aSopenharmony_ci if (nb_surfaces > ctx->nb_surfaces && ctx->nb_surfaces > 0) 914cabdff1aSopenharmony_ci { 915cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 916cabdff1aSopenharmony_ci "Defined rc_lookahead requires more surfaces, " 917cabdff1aSopenharmony_ci "increasing used surfaces %d -> %d\n", ctx->nb_surfaces, nb_surfaces); 918cabdff1aSopenharmony_ci } 919cabdff1aSopenharmony_ci ctx->nb_surfaces = FFMAX(nb_surfaces, ctx->nb_surfaces); 920cabdff1aSopenharmony_ci } else { 921cabdff1aSopenharmony_ci if (ctx->encode_config.frameIntervalP > 1 && ctx->nb_surfaces < nb_surfaces && ctx->nb_surfaces > 0) 922cabdff1aSopenharmony_ci { 923cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 924cabdff1aSopenharmony_ci "Defined b-frame requires more surfaces, " 925cabdff1aSopenharmony_ci "increasing used surfaces %d -> %d\n", ctx->nb_surfaces, nb_surfaces); 926cabdff1aSopenharmony_ci ctx->nb_surfaces = FFMAX(ctx->nb_surfaces, nb_surfaces); 927cabdff1aSopenharmony_ci } 928cabdff1aSopenharmony_ci else if (ctx->nb_surfaces <= 0) 929cabdff1aSopenharmony_ci ctx->nb_surfaces = nb_surfaces; 930cabdff1aSopenharmony_ci // otherwise use user specified value 931cabdff1aSopenharmony_ci } 932cabdff1aSopenharmony_ci 933cabdff1aSopenharmony_ci ctx->nb_surfaces = FFMAX(1, FFMIN(MAX_REGISTERED_FRAMES, ctx->nb_surfaces)); 934cabdff1aSopenharmony_ci ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1); 935cabdff1aSopenharmony_ci 936cabdff1aSopenharmony_ci return 0; 937cabdff1aSopenharmony_ci} 938cabdff1aSopenharmony_ci 939cabdff1aSopenharmony_cistatic av_cold void nvenc_setup_rate_control(AVCodecContext *avctx) 940cabdff1aSopenharmony_ci{ 941cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 942cabdff1aSopenharmony_ci 943cabdff1aSopenharmony_ci if (avctx->global_quality > 0) 944cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Using global_quality with nvenc is deprecated. Use qp instead.\n"); 945cabdff1aSopenharmony_ci 946cabdff1aSopenharmony_ci if (ctx->cqp < 0 && avctx->global_quality > 0) 947cabdff1aSopenharmony_ci ctx->cqp = avctx->global_quality; 948cabdff1aSopenharmony_ci 949cabdff1aSopenharmony_ci if (avctx->bit_rate > 0) { 950cabdff1aSopenharmony_ci ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate; 951cabdff1aSopenharmony_ci } else if (ctx->encode_config.rcParams.averageBitRate > 0) { 952cabdff1aSopenharmony_ci ctx->encode_config.rcParams.maxBitRate = ctx->encode_config.rcParams.averageBitRate; 953cabdff1aSopenharmony_ci } 954cabdff1aSopenharmony_ci 955cabdff1aSopenharmony_ci if (avctx->rc_max_rate > 0) 956cabdff1aSopenharmony_ci ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate; 957cabdff1aSopenharmony_ci 958cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_MULTIPASS 959cabdff1aSopenharmony_ci ctx->encode_config.rcParams.multiPass = ctx->multipass; 960cabdff1aSopenharmony_ci 961cabdff1aSopenharmony_ci if (ctx->flags & NVENC_ONE_PASS) 962cabdff1aSopenharmony_ci ctx->encode_config.rcParams.multiPass = NV_ENC_MULTI_PASS_DISABLED; 963cabdff1aSopenharmony_ci if (ctx->flags & NVENC_TWO_PASSES || ctx->twopass > 0) 964cabdff1aSopenharmony_ci ctx->encode_config.rcParams.multiPass = NV_ENC_TWO_PASS_FULL_RESOLUTION; 965cabdff1aSopenharmony_ci 966cabdff1aSopenharmony_ci if (ctx->rc < 0) { 967cabdff1aSopenharmony_ci if (ctx->cbr) { 968cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_CBR; 969cabdff1aSopenharmony_ci } else if (ctx->cqp >= 0) { 970cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_CONSTQP; 971cabdff1aSopenharmony_ci } else if (ctx->quality >= 0.0f) { 972cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_VBR; 973cabdff1aSopenharmony_ci } 974cabdff1aSopenharmony_ci } 975cabdff1aSopenharmony_ci#else 976cabdff1aSopenharmony_ci if (ctx->rc < 0) { 977cabdff1aSopenharmony_ci if (ctx->flags & NVENC_ONE_PASS) 978cabdff1aSopenharmony_ci ctx->twopass = 0; 979cabdff1aSopenharmony_ci if (ctx->flags & NVENC_TWO_PASSES) 980cabdff1aSopenharmony_ci ctx->twopass = 1; 981cabdff1aSopenharmony_ci 982cabdff1aSopenharmony_ci if (ctx->twopass < 0) 983cabdff1aSopenharmony_ci ctx->twopass = (ctx->flags & NVENC_LOWLATENCY) != 0; 984cabdff1aSopenharmony_ci 985cabdff1aSopenharmony_ci if (ctx->cbr) { 986cabdff1aSopenharmony_ci if (ctx->twopass) { 987cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ; 988cabdff1aSopenharmony_ci } else { 989cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_CBR; 990cabdff1aSopenharmony_ci } 991cabdff1aSopenharmony_ci } else if (ctx->cqp >= 0) { 992cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_CONSTQP; 993cabdff1aSopenharmony_ci } else if (ctx->twopass) { 994cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_VBR_HQ; 995cabdff1aSopenharmony_ci } else if (avctx->qmin >= 0 && avctx->qmax >= 0) { 996cabdff1aSopenharmony_ci ctx->rc = NV_ENC_PARAMS_RC_VBR_MINQP; 997cabdff1aSopenharmony_ci } 998cabdff1aSopenharmony_ci } 999cabdff1aSopenharmony_ci#endif 1000cabdff1aSopenharmony_ci 1001cabdff1aSopenharmony_ci if (ctx->rc >= 0 && ctx->rc & RC_MODE_DEPRECATED) { 1002cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Specified rc mode is deprecated.\n"); 1003cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Use -rc constqp/cbr/vbr, -tune and -multipass instead.\n"); 1004cabdff1aSopenharmony_ci 1005cabdff1aSopenharmony_ci ctx->rc &= ~RC_MODE_DEPRECATED; 1006cabdff1aSopenharmony_ci } 1007cabdff1aSopenharmony_ci 1008cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_QP_CHROMA_OFFSETS 1009cabdff1aSopenharmony_ci ctx->encode_config.rcParams.cbQPIndexOffset = ctx->qp_cb_offset; 1010cabdff1aSopenharmony_ci ctx->encode_config.rcParams.crQPIndexOffset = ctx->qp_cr_offset; 1011cabdff1aSopenharmony_ci#else 1012cabdff1aSopenharmony_ci if (ctx->qp_cb_offset || ctx->qp_cr_offset) 1013cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Failed setting QP CB/CR offsets, SDK 11.1 or greater required at compile time.\n"); 1014cabdff1aSopenharmony_ci#endif 1015cabdff1aSopenharmony_ci 1016cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_LDKFS 1017cabdff1aSopenharmony_ci if (ctx->ldkfs) 1018cabdff1aSopenharmony_ci ctx->encode_config.rcParams.lowDelayKeyFrameScale = ctx->ldkfs; 1019cabdff1aSopenharmony_ci#endif 1020cabdff1aSopenharmony_ci 1021cabdff1aSopenharmony_ci if (ctx->flags & NVENC_LOSSLESS) { 1022cabdff1aSopenharmony_ci set_lossless(avctx); 1023cabdff1aSopenharmony_ci } else if (ctx->rc >= 0) { 1024cabdff1aSopenharmony_ci nvenc_override_rate_control(avctx); 1025cabdff1aSopenharmony_ci } else { 1026cabdff1aSopenharmony_ci ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR; 1027cabdff1aSopenharmony_ci set_vbr(avctx); 1028cabdff1aSopenharmony_ci } 1029cabdff1aSopenharmony_ci 1030cabdff1aSopenharmony_ci if (avctx->rc_buffer_size > 0) { 1031cabdff1aSopenharmony_ci ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size; 1032cabdff1aSopenharmony_ci } else if (ctx->encode_config.rcParams.averageBitRate > 0) { 1033cabdff1aSopenharmony_ci avctx->rc_buffer_size = ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate; 1034cabdff1aSopenharmony_ci } 1035cabdff1aSopenharmony_ci 1036cabdff1aSopenharmony_ci if (ctx->aq) { 1037cabdff1aSopenharmony_ci ctx->encode_config.rcParams.enableAQ = 1; 1038cabdff1aSopenharmony_ci ctx->encode_config.rcParams.aqStrength = ctx->aq_strength; 1039cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "AQ enabled.\n"); 1040cabdff1aSopenharmony_ci } 1041cabdff1aSopenharmony_ci 1042cabdff1aSopenharmony_ci if (ctx->temporal_aq) { 1043cabdff1aSopenharmony_ci ctx->encode_config.rcParams.enableTemporalAQ = 1; 1044cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Temporal AQ enabled.\n"); 1045cabdff1aSopenharmony_ci } 1046cabdff1aSopenharmony_ci 1047cabdff1aSopenharmony_ci if (ctx->rc_lookahead > 0) { 1048cabdff1aSopenharmony_ci int lkd_bound = FFMIN(ctx->nb_surfaces, ctx->async_depth) - 1049cabdff1aSopenharmony_ci ctx->encode_config.frameIntervalP - 4; 1050cabdff1aSopenharmony_ci 1051cabdff1aSopenharmony_ci if (lkd_bound < 0) { 1052cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 1053cabdff1aSopenharmony_ci "Lookahead not enabled. Increase buffer delay (-delay).\n"); 1054cabdff1aSopenharmony_ci } else { 1055cabdff1aSopenharmony_ci ctx->encode_config.rcParams.enableLookahead = 1; 1056cabdff1aSopenharmony_ci ctx->encode_config.rcParams.lookaheadDepth = av_clip(ctx->rc_lookahead, 0, lkd_bound); 1057cabdff1aSopenharmony_ci ctx->encode_config.rcParams.disableIadapt = ctx->no_scenecut; 1058cabdff1aSopenharmony_ci ctx->encode_config.rcParams.disableBadapt = !ctx->b_adapt; 1059cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, 1060cabdff1aSopenharmony_ci "Lookahead enabled: depth %d, scenecut %s, B-adapt %s.\n", 1061cabdff1aSopenharmony_ci ctx->encode_config.rcParams.lookaheadDepth, 1062cabdff1aSopenharmony_ci ctx->encode_config.rcParams.disableIadapt ? "disabled" : "enabled", 1063cabdff1aSopenharmony_ci ctx->encode_config.rcParams.disableBadapt ? "disabled" : "enabled"); 1064cabdff1aSopenharmony_ci } 1065cabdff1aSopenharmony_ci } 1066cabdff1aSopenharmony_ci 1067cabdff1aSopenharmony_ci if (ctx->strict_gop) { 1068cabdff1aSopenharmony_ci ctx->encode_config.rcParams.strictGOPTarget = 1; 1069cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Strict GOP target enabled.\n"); 1070cabdff1aSopenharmony_ci } 1071cabdff1aSopenharmony_ci 1072cabdff1aSopenharmony_ci if (ctx->nonref_p) 1073cabdff1aSopenharmony_ci ctx->encode_config.rcParams.enableNonRefP = 1; 1074cabdff1aSopenharmony_ci 1075cabdff1aSopenharmony_ci if (ctx->zerolatency) 1076cabdff1aSopenharmony_ci ctx->encode_config.rcParams.zeroReorderDelay = 1; 1077cabdff1aSopenharmony_ci 1078cabdff1aSopenharmony_ci if (ctx->quality) { 1079cabdff1aSopenharmony_ci //convert from float to fixed point 8.8 1080cabdff1aSopenharmony_ci int tmp_quality = (int)(ctx->quality * 256.0f); 1081cabdff1aSopenharmony_ci ctx->encode_config.rcParams.targetQuality = (uint8_t)(tmp_quality >> 8); 1082cabdff1aSopenharmony_ci ctx->encode_config.rcParams.targetQualityLSB = (uint8_t)(tmp_quality & 0xff); 1083cabdff1aSopenharmony_ci 1084cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "CQ(%d) mode enabled.\n", tmp_quality); 1085cabdff1aSopenharmony_ci 1086cabdff1aSopenharmony_ci // CQ mode shall discard avg bitrate/vbv buffer size and honor only max bitrate 1087cabdff1aSopenharmony_ci ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate = 0; 1088cabdff1aSopenharmony_ci ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size = 0; 1089cabdff1aSopenharmony_ci ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate; 1090cabdff1aSopenharmony_ci } 1091cabdff1aSopenharmony_ci} 1092cabdff1aSopenharmony_ci 1093cabdff1aSopenharmony_cistatic av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) 1094cabdff1aSopenharmony_ci{ 1095cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1096cabdff1aSopenharmony_ci NV_ENC_CONFIG *cc = &ctx->encode_config; 1097cabdff1aSopenharmony_ci NV_ENC_CONFIG_H264 *h264 = &cc->encodeCodecConfig.h264Config; 1098cabdff1aSopenharmony_ci NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui = &h264->h264VUIParameters; 1099cabdff1aSopenharmony_ci 1100cabdff1aSopenharmony_ci vui->colourMatrix = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace; 1101cabdff1aSopenharmony_ci vui->colourPrimaries = avctx->color_primaries; 1102cabdff1aSopenharmony_ci vui->transferCharacteristics = avctx->color_trc; 1103cabdff1aSopenharmony_ci vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG 1104cabdff1aSopenharmony_ci || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P); 1105cabdff1aSopenharmony_ci 1106cabdff1aSopenharmony_ci vui->colourDescriptionPresentFlag = 1107cabdff1aSopenharmony_ci (vui->colourMatrix != 2 || vui->colourPrimaries != 2 || vui->transferCharacteristics != 2); 1108cabdff1aSopenharmony_ci 1109cabdff1aSopenharmony_ci vui->videoSignalTypePresentFlag = 1110cabdff1aSopenharmony_ci (vui->colourDescriptionPresentFlag 1111cabdff1aSopenharmony_ci || vui->videoFormat != 5 1112cabdff1aSopenharmony_ci || vui->videoFullRangeFlag != 0); 1113cabdff1aSopenharmony_ci 1114cabdff1aSopenharmony_ci h264->sliceMode = 3; 1115cabdff1aSopenharmony_ci h264->sliceModeData = avctx->slices > 0 ? avctx->slices : 1; 1116cabdff1aSopenharmony_ci 1117cabdff1aSopenharmony_ci if (ctx->intra_refresh) { 1118cabdff1aSopenharmony_ci h264->enableIntraRefresh = 1; 1119cabdff1aSopenharmony_ci h264->intraRefreshPeriod = avctx->gop_size; 1120cabdff1aSopenharmony_ci h264->intraRefreshCnt = avctx->gop_size - 1; 1121cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH 1122cabdff1aSopenharmony_ci h264->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; 1123cabdff1aSopenharmony_ci#endif 1124cabdff1aSopenharmony_ci } 1125cabdff1aSopenharmony_ci 1126cabdff1aSopenharmony_ci if (ctx->constrained_encoding) 1127cabdff1aSopenharmony_ci h264->enableConstrainedEncoding = 1; 1128cabdff1aSopenharmony_ci 1129cabdff1aSopenharmony_ci h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; 1130cabdff1aSopenharmony_ci h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; 1131cabdff1aSopenharmony_ci h264->outputAUD = ctx->aud; 1132cabdff1aSopenharmony_ci 1133cabdff1aSopenharmony_ci if (ctx->dpb_size >= 0) { 1134cabdff1aSopenharmony_ci /* 0 means "let the hardware decide" */ 1135cabdff1aSopenharmony_ci h264->maxNumRefFrames = ctx->dpb_size; 1136cabdff1aSopenharmony_ci } 1137cabdff1aSopenharmony_ci 1138cabdff1aSopenharmony_ci if (ctx->intra_refresh) { 1139cabdff1aSopenharmony_ci h264->idrPeriod = NVENC_INFINITE_GOPLENGTH; 1140cabdff1aSopenharmony_ci } else if (avctx->gop_size >= 0) { 1141cabdff1aSopenharmony_ci h264->idrPeriod = avctx->gop_size; 1142cabdff1aSopenharmony_ci } 1143cabdff1aSopenharmony_ci 1144cabdff1aSopenharmony_ci if (IS_CBR(cc->rcParams.rateControlMode)) { 1145cabdff1aSopenharmony_ci h264->outputBufferingPeriodSEI = 1; 1146cabdff1aSopenharmony_ci } 1147cabdff1aSopenharmony_ci 1148cabdff1aSopenharmony_ci h264->outputPictureTimingSEI = 1; 1149cabdff1aSopenharmony_ci 1150cabdff1aSopenharmony_ci if (cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || 1151cabdff1aSopenharmony_ci cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_CBR_HQ || 1152cabdff1aSopenharmony_ci cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_VBR_HQ) { 1153cabdff1aSopenharmony_ci h264->adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE; 1154cabdff1aSopenharmony_ci h264->fmoMode = NV_ENC_H264_FMO_DISABLE; 1155cabdff1aSopenharmony_ci } 1156cabdff1aSopenharmony_ci 1157cabdff1aSopenharmony_ci if (ctx->flags & NVENC_LOSSLESS) { 1158cabdff1aSopenharmony_ci h264->qpPrimeYZeroTransformBypassFlag = 1; 1159cabdff1aSopenharmony_ci } else { 1160cabdff1aSopenharmony_ci switch(ctx->profile) { 1161cabdff1aSopenharmony_ci case NV_ENC_H264_PROFILE_BASELINE: 1162cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID; 1163cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_H264_BASELINE; 1164cabdff1aSopenharmony_ci break; 1165cabdff1aSopenharmony_ci case NV_ENC_H264_PROFILE_MAIN: 1166cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID; 1167cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_H264_MAIN; 1168cabdff1aSopenharmony_ci break; 1169cabdff1aSopenharmony_ci case NV_ENC_H264_PROFILE_HIGH: 1170cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID; 1171cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_H264_HIGH; 1172cabdff1aSopenharmony_ci break; 1173cabdff1aSopenharmony_ci case NV_ENC_H264_PROFILE_HIGH_444P: 1174cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID; 1175cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE; 1176cabdff1aSopenharmony_ci break; 1177cabdff1aSopenharmony_ci } 1178cabdff1aSopenharmony_ci } 1179cabdff1aSopenharmony_ci 1180cabdff1aSopenharmony_ci // force setting profile as high444p if input is AV_PIX_FMT_YUV444P 1181cabdff1aSopenharmony_ci if (IS_YUV444(ctx->data_pix_fmt)) { 1182cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID; 1183cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE; 1184cabdff1aSopenharmony_ci } 1185cabdff1aSopenharmony_ci 1186cabdff1aSopenharmony_ci h264->chromaFormatIDC = avctx->profile == FF_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1; 1187cabdff1aSopenharmony_ci 1188cabdff1aSopenharmony_ci h264->level = ctx->level; 1189cabdff1aSopenharmony_ci 1190cabdff1aSopenharmony_ci if (ctx->coder >= 0) 1191cabdff1aSopenharmony_ci h264->entropyCodingMode = ctx->coder; 1192cabdff1aSopenharmony_ci 1193cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_BFRAME_REF_MODE 1194cabdff1aSopenharmony_ci h264->useBFramesAsRef = ctx->b_ref_mode; 1195cabdff1aSopenharmony_ci#endif 1196cabdff1aSopenharmony_ci 1197cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES 1198cabdff1aSopenharmony_ci h264->numRefL0 = avctx->refs; 1199cabdff1aSopenharmony_ci h264->numRefL1 = avctx->refs; 1200cabdff1aSopenharmony_ci#endif 1201cabdff1aSopenharmony_ci 1202cabdff1aSopenharmony_ci return 0; 1203cabdff1aSopenharmony_ci} 1204cabdff1aSopenharmony_ci 1205cabdff1aSopenharmony_cistatic av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) 1206cabdff1aSopenharmony_ci{ 1207cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1208cabdff1aSopenharmony_ci NV_ENC_CONFIG *cc = &ctx->encode_config; 1209cabdff1aSopenharmony_ci NV_ENC_CONFIG_HEVC *hevc = &cc->encodeCodecConfig.hevcConfig; 1210cabdff1aSopenharmony_ci NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui = &hevc->hevcVUIParameters; 1211cabdff1aSopenharmony_ci 1212cabdff1aSopenharmony_ci vui->colourMatrix = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace; 1213cabdff1aSopenharmony_ci vui->colourPrimaries = avctx->color_primaries; 1214cabdff1aSopenharmony_ci vui->transferCharacteristics = avctx->color_trc; 1215cabdff1aSopenharmony_ci vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG 1216cabdff1aSopenharmony_ci || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P); 1217cabdff1aSopenharmony_ci 1218cabdff1aSopenharmony_ci vui->colourDescriptionPresentFlag = 1219cabdff1aSopenharmony_ci (vui->colourMatrix != 2 || vui->colourPrimaries != 2 || vui->transferCharacteristics != 2); 1220cabdff1aSopenharmony_ci 1221cabdff1aSopenharmony_ci vui->videoSignalTypePresentFlag = 1222cabdff1aSopenharmony_ci (vui->colourDescriptionPresentFlag 1223cabdff1aSopenharmony_ci || vui->videoFormat != 5 1224cabdff1aSopenharmony_ci || vui->videoFullRangeFlag != 0); 1225cabdff1aSopenharmony_ci 1226cabdff1aSopenharmony_ci hevc->sliceMode = 3; 1227cabdff1aSopenharmony_ci hevc->sliceModeData = avctx->slices > 0 ? avctx->slices : 1; 1228cabdff1aSopenharmony_ci 1229cabdff1aSopenharmony_ci if (ctx->intra_refresh) { 1230cabdff1aSopenharmony_ci hevc->enableIntraRefresh = 1; 1231cabdff1aSopenharmony_ci hevc->intraRefreshPeriod = avctx->gop_size; 1232cabdff1aSopenharmony_ci hevc->intraRefreshCnt = avctx->gop_size - 1; 1233cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH 1234cabdff1aSopenharmony_ci hevc->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; 1235cabdff1aSopenharmony_ci#endif 1236cabdff1aSopenharmony_ci } 1237cabdff1aSopenharmony_ci 1238cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_HEVC_CONSTRAINED_ENCODING 1239cabdff1aSopenharmony_ci if (ctx->constrained_encoding) 1240cabdff1aSopenharmony_ci hevc->enableConstrainedEncoding = 1; 1241cabdff1aSopenharmony_ci#endif 1242cabdff1aSopenharmony_ci 1243cabdff1aSopenharmony_ci hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; 1244cabdff1aSopenharmony_ci hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; 1245cabdff1aSopenharmony_ci hevc->outputAUD = ctx->aud; 1246cabdff1aSopenharmony_ci 1247cabdff1aSopenharmony_ci if (ctx->dpb_size >= 0) { 1248cabdff1aSopenharmony_ci /* 0 means "let the hardware decide" */ 1249cabdff1aSopenharmony_ci hevc->maxNumRefFramesInDPB = ctx->dpb_size; 1250cabdff1aSopenharmony_ci } 1251cabdff1aSopenharmony_ci 1252cabdff1aSopenharmony_ci if (ctx->intra_refresh) { 1253cabdff1aSopenharmony_ci hevc->idrPeriod = NVENC_INFINITE_GOPLENGTH; 1254cabdff1aSopenharmony_ci } else if (avctx->gop_size >= 0) { 1255cabdff1aSopenharmony_ci hevc->idrPeriod = avctx->gop_size; 1256cabdff1aSopenharmony_ci } 1257cabdff1aSopenharmony_ci 1258cabdff1aSopenharmony_ci if (IS_CBR(cc->rcParams.rateControlMode)) { 1259cabdff1aSopenharmony_ci hevc->outputBufferingPeriodSEI = 1; 1260cabdff1aSopenharmony_ci } 1261cabdff1aSopenharmony_ci 1262cabdff1aSopenharmony_ci hevc->outputPictureTimingSEI = 1; 1263cabdff1aSopenharmony_ci 1264cabdff1aSopenharmony_ci switch (ctx->profile) { 1265cabdff1aSopenharmony_ci case NV_ENC_HEVC_PROFILE_MAIN: 1266cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID; 1267cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_HEVC_MAIN; 1268cabdff1aSopenharmony_ci break; 1269cabdff1aSopenharmony_ci case NV_ENC_HEVC_PROFILE_MAIN_10: 1270cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID; 1271cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_HEVC_MAIN_10; 1272cabdff1aSopenharmony_ci break; 1273cabdff1aSopenharmony_ci case NV_ENC_HEVC_PROFILE_REXT: 1274cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID; 1275cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_HEVC_REXT; 1276cabdff1aSopenharmony_ci break; 1277cabdff1aSopenharmony_ci } 1278cabdff1aSopenharmony_ci 1279cabdff1aSopenharmony_ci // force setting profile as main10 if input is 10 bit 1280cabdff1aSopenharmony_ci if (IS_10BIT(ctx->data_pix_fmt)) { 1281cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID; 1282cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_HEVC_MAIN_10; 1283cabdff1aSopenharmony_ci } 1284cabdff1aSopenharmony_ci 1285cabdff1aSopenharmony_ci // force setting profile as rext if input is yuv444 1286cabdff1aSopenharmony_ci if (IS_YUV444(ctx->data_pix_fmt)) { 1287cabdff1aSopenharmony_ci cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID; 1288cabdff1aSopenharmony_ci avctx->profile = FF_PROFILE_HEVC_REXT; 1289cabdff1aSopenharmony_ci } 1290cabdff1aSopenharmony_ci 1291cabdff1aSopenharmony_ci hevc->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1; 1292cabdff1aSopenharmony_ci 1293cabdff1aSopenharmony_ci hevc->pixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0; 1294cabdff1aSopenharmony_ci 1295cabdff1aSopenharmony_ci hevc->level = ctx->level; 1296cabdff1aSopenharmony_ci 1297cabdff1aSopenharmony_ci hevc->tier = ctx->tier; 1298cabdff1aSopenharmony_ci 1299cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_HEVC_BFRAME_REF_MODE 1300cabdff1aSopenharmony_ci hevc->useBFramesAsRef = ctx->b_ref_mode; 1301cabdff1aSopenharmony_ci#endif 1302cabdff1aSopenharmony_ci 1303cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES 1304cabdff1aSopenharmony_ci hevc->numRefL0 = avctx->refs; 1305cabdff1aSopenharmony_ci hevc->numRefL1 = avctx->refs; 1306cabdff1aSopenharmony_ci#endif 1307cabdff1aSopenharmony_ci 1308cabdff1aSopenharmony_ci return 0; 1309cabdff1aSopenharmony_ci} 1310cabdff1aSopenharmony_ci 1311cabdff1aSopenharmony_cistatic av_cold int nvenc_setup_codec_config(AVCodecContext *avctx) 1312cabdff1aSopenharmony_ci{ 1313cabdff1aSopenharmony_ci switch (avctx->codec->id) { 1314cabdff1aSopenharmony_ci case AV_CODEC_ID_H264: 1315cabdff1aSopenharmony_ci return nvenc_setup_h264_config(avctx); 1316cabdff1aSopenharmony_ci case AV_CODEC_ID_HEVC: 1317cabdff1aSopenharmony_ci return nvenc_setup_hevc_config(avctx); 1318cabdff1aSopenharmony_ci /* Earlier switch/case will return if unknown codec is passed. */ 1319cabdff1aSopenharmony_ci } 1320cabdff1aSopenharmony_ci 1321cabdff1aSopenharmony_ci return 0; 1322cabdff1aSopenharmony_ci} 1323cabdff1aSopenharmony_ci 1324cabdff1aSopenharmony_cistatic void compute_dar(AVCodecContext *avctx, int *dw, int *dh) { 1325cabdff1aSopenharmony_ci int sw, sh; 1326cabdff1aSopenharmony_ci 1327cabdff1aSopenharmony_ci sw = avctx->width; 1328cabdff1aSopenharmony_ci sh = avctx->height; 1329cabdff1aSopenharmony_ci 1330cabdff1aSopenharmony_ci if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { 1331cabdff1aSopenharmony_ci sw *= avctx->sample_aspect_ratio.num; 1332cabdff1aSopenharmony_ci sh *= avctx->sample_aspect_ratio.den; 1333cabdff1aSopenharmony_ci } 1334cabdff1aSopenharmony_ci 1335cabdff1aSopenharmony_ci av_reduce(dw, dh, sw, sh, 1024 * 1024); 1336cabdff1aSopenharmony_ci} 1337cabdff1aSopenharmony_ci 1338cabdff1aSopenharmony_cistatic av_cold int nvenc_setup_encoder(AVCodecContext *avctx) 1339cabdff1aSopenharmony_ci{ 1340cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1341cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 1342cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 1343cabdff1aSopenharmony_ci 1344cabdff1aSopenharmony_ci NV_ENC_PRESET_CONFIG preset_config = { 0 }; 1345cabdff1aSopenharmony_ci NVENCSTATUS nv_status = NV_ENC_SUCCESS; 1346cabdff1aSopenharmony_ci AVCPBProperties *cpb_props; 1347cabdff1aSopenharmony_ci int res = 0; 1348cabdff1aSopenharmony_ci int dw, dh; 1349cabdff1aSopenharmony_ci 1350cabdff1aSopenharmony_ci ctx->encode_config.version = NV_ENC_CONFIG_VER; 1351cabdff1aSopenharmony_ci ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER; 1352cabdff1aSopenharmony_ci 1353cabdff1aSopenharmony_ci ctx->init_encode_params.encodeHeight = avctx->height; 1354cabdff1aSopenharmony_ci ctx->init_encode_params.encodeWidth = avctx->width; 1355cabdff1aSopenharmony_ci 1356cabdff1aSopenharmony_ci ctx->init_encode_params.encodeConfig = &ctx->encode_config; 1357cabdff1aSopenharmony_ci 1358cabdff1aSopenharmony_ci preset_config.version = NV_ENC_PRESET_CONFIG_VER; 1359cabdff1aSopenharmony_ci preset_config.presetCfg.version = NV_ENC_CONFIG_VER; 1360cabdff1aSopenharmony_ci 1361cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_NEW_PRESETS 1362cabdff1aSopenharmony_ci ctx->init_encode_params.tuningInfo = ctx->tuning_info; 1363cabdff1aSopenharmony_ci 1364cabdff1aSopenharmony_ci if (ctx->flags & NVENC_LOSSLESS) 1365cabdff1aSopenharmony_ci ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOSSLESS; 1366cabdff1aSopenharmony_ci else if (ctx->flags & NVENC_LOWLATENCY) 1367cabdff1aSopenharmony_ci ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOW_LATENCY; 1368cabdff1aSopenharmony_ci 1369cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder, 1370cabdff1aSopenharmony_ci ctx->init_encode_params.encodeGUID, 1371cabdff1aSopenharmony_ci ctx->init_encode_params.presetGUID, 1372cabdff1aSopenharmony_ci ctx->init_encode_params.tuningInfo, 1373cabdff1aSopenharmony_ci &preset_config); 1374cabdff1aSopenharmony_ci#else 1375cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder, 1376cabdff1aSopenharmony_ci ctx->init_encode_params.encodeGUID, 1377cabdff1aSopenharmony_ci ctx->init_encode_params.presetGUID, 1378cabdff1aSopenharmony_ci &preset_config); 1379cabdff1aSopenharmony_ci#endif 1380cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) 1381cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration"); 1382cabdff1aSopenharmony_ci 1383cabdff1aSopenharmony_ci memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config)); 1384cabdff1aSopenharmony_ci 1385cabdff1aSopenharmony_ci ctx->encode_config.version = NV_ENC_CONFIG_VER; 1386cabdff1aSopenharmony_ci 1387cabdff1aSopenharmony_ci compute_dar(avctx, &dw, &dh); 1388cabdff1aSopenharmony_ci ctx->init_encode_params.darHeight = dh; 1389cabdff1aSopenharmony_ci ctx->init_encode_params.darWidth = dw; 1390cabdff1aSopenharmony_ci 1391cabdff1aSopenharmony_ci if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { 1392cabdff1aSopenharmony_ci ctx->init_encode_params.frameRateNum = avctx->framerate.num; 1393cabdff1aSopenharmony_ci ctx->init_encode_params.frameRateDen = avctx->framerate.den; 1394cabdff1aSopenharmony_ci } else { 1395cabdff1aSopenharmony_ci ctx->init_encode_params.frameRateNum = avctx->time_base.den; 1396cabdff1aSopenharmony_ci ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame; 1397cabdff1aSopenharmony_ci } 1398cabdff1aSopenharmony_ci 1399cabdff1aSopenharmony_ci ctx->init_encode_params.enableEncodeAsync = 0; 1400cabdff1aSopenharmony_ci ctx->init_encode_params.enablePTD = 1; 1401cabdff1aSopenharmony_ci 1402cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_NEW_PRESETS 1403cabdff1aSopenharmony_ci /* If lookahead isn't set from CLI, use value from preset. 1404cabdff1aSopenharmony_ci * P6 & P7 presets may enable lookahead for better quality. 1405cabdff1aSopenharmony_ci * */ 1406cabdff1aSopenharmony_ci if (ctx->rc_lookahead == 0 && ctx->encode_config.rcParams.enableLookahead) 1407cabdff1aSopenharmony_ci ctx->rc_lookahead = ctx->encode_config.rcParams.lookaheadDepth; 1408cabdff1aSopenharmony_ci#endif 1409cabdff1aSopenharmony_ci 1410cabdff1aSopenharmony_ci if (ctx->weighted_pred == 1) 1411cabdff1aSopenharmony_ci ctx->init_encode_params.enableWeightedPrediction = 1; 1412cabdff1aSopenharmony_ci 1413cabdff1aSopenharmony_ci if (ctx->bluray_compat) { 1414cabdff1aSopenharmony_ci ctx->aud = 1; 1415cabdff1aSopenharmony_ci ctx->dpb_size = FFMIN(FFMAX(avctx->refs, 0), 6); 1416cabdff1aSopenharmony_ci avctx->max_b_frames = FFMIN(avctx->max_b_frames, 3); 1417cabdff1aSopenharmony_ci switch (avctx->codec->id) { 1418cabdff1aSopenharmony_ci case AV_CODEC_ID_H264: 1419cabdff1aSopenharmony_ci /* maximum level depends on used resolution */ 1420cabdff1aSopenharmony_ci break; 1421cabdff1aSopenharmony_ci case AV_CODEC_ID_HEVC: 1422cabdff1aSopenharmony_ci ctx->level = NV_ENC_LEVEL_HEVC_51; 1423cabdff1aSopenharmony_ci ctx->tier = NV_ENC_TIER_HEVC_HIGH; 1424cabdff1aSopenharmony_ci break; 1425cabdff1aSopenharmony_ci } 1426cabdff1aSopenharmony_ci } 1427cabdff1aSopenharmony_ci 1428cabdff1aSopenharmony_ci if (avctx->gop_size > 0) { 1429cabdff1aSopenharmony_ci if (avctx->max_b_frames >= 0) { 1430cabdff1aSopenharmony_ci /* 0 is intra-only, 1 is I/P only, 2 is one B-Frame, 3 two B-frames, and so on. */ 1431cabdff1aSopenharmony_ci ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1; 1432cabdff1aSopenharmony_ci } 1433cabdff1aSopenharmony_ci 1434cabdff1aSopenharmony_ci ctx->encode_config.gopLength = avctx->gop_size; 1435cabdff1aSopenharmony_ci } else if (avctx->gop_size == 0) { 1436cabdff1aSopenharmony_ci ctx->encode_config.frameIntervalP = 0; 1437cabdff1aSopenharmony_ci ctx->encode_config.gopLength = 1; 1438cabdff1aSopenharmony_ci } 1439cabdff1aSopenharmony_ci 1440cabdff1aSopenharmony_ci /* force to enable intra refresh */ 1441cabdff1aSopenharmony_ci if(ctx->single_slice_intra_refresh) 1442cabdff1aSopenharmony_ci ctx->intra_refresh = 1; 1443cabdff1aSopenharmony_ci 1444cabdff1aSopenharmony_ci if (ctx->intra_refresh) 1445cabdff1aSopenharmony_ci ctx->encode_config.gopLength = NVENC_INFINITE_GOPLENGTH; 1446cabdff1aSopenharmony_ci 1447cabdff1aSopenharmony_ci nvenc_recalc_surfaces(avctx); 1448cabdff1aSopenharmony_ci 1449cabdff1aSopenharmony_ci nvenc_setup_rate_control(avctx); 1450cabdff1aSopenharmony_ci 1451cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { 1452cabdff1aSopenharmony_ci ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD; 1453cabdff1aSopenharmony_ci } else { 1454cabdff1aSopenharmony_ci ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME; 1455cabdff1aSopenharmony_ci } 1456cabdff1aSopenharmony_ci 1457cabdff1aSopenharmony_ci res = nvenc_setup_codec_config(avctx); 1458cabdff1aSopenharmony_ci if (res) 1459cabdff1aSopenharmony_ci return res; 1460cabdff1aSopenharmony_ci 1461cabdff1aSopenharmony_ci res = nvenc_push_context(avctx); 1462cabdff1aSopenharmony_ci if (res < 0) 1463cabdff1aSopenharmony_ci return res; 1464cabdff1aSopenharmony_ci 1465cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params); 1466cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1467cabdff1aSopenharmony_ci nvenc_pop_context(avctx); 1468cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "InitializeEncoder failed"); 1469cabdff1aSopenharmony_ci } 1470cabdff1aSopenharmony_ci 1471cabdff1aSopenharmony_ci#ifdef NVENC_HAVE_CUSTREAM_PTR 1472cabdff1aSopenharmony_ci if (ctx->cu_context) { 1473cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncSetIOCudaStreams(ctx->nvencoder, &ctx->cu_stream, &ctx->cu_stream); 1474cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1475cabdff1aSopenharmony_ci nvenc_pop_context(avctx); 1476cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "SetIOCudaStreams failed"); 1477cabdff1aSopenharmony_ci } 1478cabdff1aSopenharmony_ci } 1479cabdff1aSopenharmony_ci#endif 1480cabdff1aSopenharmony_ci 1481cabdff1aSopenharmony_ci res = nvenc_pop_context(avctx); 1482cabdff1aSopenharmony_ci if (res < 0) 1483cabdff1aSopenharmony_ci return res; 1484cabdff1aSopenharmony_ci 1485cabdff1aSopenharmony_ci if (ctx->encode_config.frameIntervalP > 1) 1486cabdff1aSopenharmony_ci avctx->has_b_frames = 2; 1487cabdff1aSopenharmony_ci 1488cabdff1aSopenharmony_ci if (ctx->encode_config.rcParams.averageBitRate > 0) 1489cabdff1aSopenharmony_ci avctx->bit_rate = ctx->encode_config.rcParams.averageBitRate; 1490cabdff1aSopenharmony_ci 1491cabdff1aSopenharmony_ci cpb_props = ff_add_cpb_side_data(avctx); 1492cabdff1aSopenharmony_ci if (!cpb_props) 1493cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1494cabdff1aSopenharmony_ci cpb_props->max_bitrate = ctx->encode_config.rcParams.maxBitRate; 1495cabdff1aSopenharmony_ci cpb_props->avg_bitrate = avctx->bit_rate; 1496cabdff1aSopenharmony_ci cpb_props->buffer_size = ctx->encode_config.rcParams.vbvBufferSize; 1497cabdff1aSopenharmony_ci 1498cabdff1aSopenharmony_ci return 0; 1499cabdff1aSopenharmony_ci} 1500cabdff1aSopenharmony_ci 1501cabdff1aSopenharmony_cistatic NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum AVPixelFormat pix_fmt) 1502cabdff1aSopenharmony_ci{ 1503cabdff1aSopenharmony_ci switch (pix_fmt) { 1504cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: 1505cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_YV12_PL; 1506cabdff1aSopenharmony_ci case AV_PIX_FMT_NV12: 1507cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_NV12_PL; 1508cabdff1aSopenharmony_ci case AV_PIX_FMT_P010: 1509cabdff1aSopenharmony_ci case AV_PIX_FMT_P016: 1510cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_YUV420_10BIT; 1511cabdff1aSopenharmony_ci case AV_PIX_FMT_GBRP: 1512cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P: 1513cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_YUV444_PL; 1514cabdff1aSopenharmony_ci case AV_PIX_FMT_GBRP16: 1515cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P16: 1516cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_YUV444_10BIT; 1517cabdff1aSopenharmony_ci case AV_PIX_FMT_0RGB32: 1518cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB32: 1519cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_ARGB; 1520cabdff1aSopenharmony_ci case AV_PIX_FMT_0BGR32: 1521cabdff1aSopenharmony_ci case AV_PIX_FMT_BGR32: 1522cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_ABGR; 1523cabdff1aSopenharmony_ci case AV_PIX_FMT_X2RGB10: 1524cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_ARGB10; 1525cabdff1aSopenharmony_ci case AV_PIX_FMT_X2BGR10: 1526cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_ABGR10; 1527cabdff1aSopenharmony_ci default: 1528cabdff1aSopenharmony_ci return NV_ENC_BUFFER_FORMAT_UNDEFINED; 1529cabdff1aSopenharmony_ci } 1530cabdff1aSopenharmony_ci} 1531cabdff1aSopenharmony_ci 1532cabdff1aSopenharmony_cistatic av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) 1533cabdff1aSopenharmony_ci{ 1534cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1535cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 1536cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 1537cabdff1aSopenharmony_ci NvencSurface* tmp_surface = &ctx->surfaces[idx]; 1538cabdff1aSopenharmony_ci 1539cabdff1aSopenharmony_ci NVENCSTATUS nv_status; 1540cabdff1aSopenharmony_ci NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 }; 1541cabdff1aSopenharmony_ci allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER; 1542cabdff1aSopenharmony_ci 1543cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { 1544cabdff1aSopenharmony_ci ctx->surfaces[idx].in_ref = av_frame_alloc(); 1545cabdff1aSopenharmony_ci if (!ctx->surfaces[idx].in_ref) 1546cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1547cabdff1aSopenharmony_ci } else { 1548cabdff1aSopenharmony_ci NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 }; 1549cabdff1aSopenharmony_ci 1550cabdff1aSopenharmony_ci ctx->surfaces[idx].format = nvenc_map_buffer_format(ctx->data_pix_fmt); 1551cabdff1aSopenharmony_ci if (ctx->surfaces[idx].format == NV_ENC_BUFFER_FORMAT_UNDEFINED) { 1552cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n", 1553cabdff1aSopenharmony_ci av_get_pix_fmt_name(ctx->data_pix_fmt)); 1554cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1555cabdff1aSopenharmony_ci } 1556cabdff1aSopenharmony_ci 1557cabdff1aSopenharmony_ci allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER; 1558cabdff1aSopenharmony_ci allocSurf.width = avctx->width; 1559cabdff1aSopenharmony_ci allocSurf.height = avctx->height; 1560cabdff1aSopenharmony_ci allocSurf.bufferFmt = ctx->surfaces[idx].format; 1561cabdff1aSopenharmony_ci 1562cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf); 1563cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1564cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "CreateInputBuffer failed"); 1565cabdff1aSopenharmony_ci } 1566cabdff1aSopenharmony_ci 1567cabdff1aSopenharmony_ci ctx->surfaces[idx].input_surface = allocSurf.inputBuffer; 1568cabdff1aSopenharmony_ci ctx->surfaces[idx].width = allocSurf.width; 1569cabdff1aSopenharmony_ci ctx->surfaces[idx].height = allocSurf.height; 1570cabdff1aSopenharmony_ci } 1571cabdff1aSopenharmony_ci 1572cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut); 1573cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1574cabdff1aSopenharmony_ci int err = nvenc_print_error(avctx, nv_status, "CreateBitstreamBuffer failed"); 1575cabdff1aSopenharmony_ci if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11) 1576cabdff1aSopenharmony_ci p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[idx].input_surface); 1577cabdff1aSopenharmony_ci av_frame_free(&ctx->surfaces[idx].in_ref); 1578cabdff1aSopenharmony_ci return err; 1579cabdff1aSopenharmony_ci } 1580cabdff1aSopenharmony_ci 1581cabdff1aSopenharmony_ci ctx->surfaces[idx].output_surface = allocOut.bitstreamBuffer; 1582cabdff1aSopenharmony_ci 1583cabdff1aSopenharmony_ci av_fifo_write(ctx->unused_surface_queue, &tmp_surface, 1); 1584cabdff1aSopenharmony_ci 1585cabdff1aSopenharmony_ci return 0; 1586cabdff1aSopenharmony_ci} 1587cabdff1aSopenharmony_ci 1588cabdff1aSopenharmony_cistatic av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) 1589cabdff1aSopenharmony_ci{ 1590cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1591cabdff1aSopenharmony_ci int i, res = 0, res2; 1592cabdff1aSopenharmony_ci 1593cabdff1aSopenharmony_ci ctx->surfaces = av_calloc(ctx->nb_surfaces, sizeof(*ctx->surfaces)); 1594cabdff1aSopenharmony_ci if (!ctx->surfaces) 1595cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1596cabdff1aSopenharmony_ci 1597cabdff1aSopenharmony_ci ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0); 1598cabdff1aSopenharmony_ci if (!ctx->timestamp_list) 1599cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1600cabdff1aSopenharmony_ci 1601cabdff1aSopenharmony_ci ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); 1602cabdff1aSopenharmony_ci if (!ctx->unused_surface_queue) 1603cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1604cabdff1aSopenharmony_ci 1605cabdff1aSopenharmony_ci ctx->output_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); 1606cabdff1aSopenharmony_ci if (!ctx->output_surface_queue) 1607cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1608cabdff1aSopenharmony_ci ctx->output_surface_ready_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); 1609cabdff1aSopenharmony_ci if (!ctx->output_surface_ready_queue) 1610cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1611cabdff1aSopenharmony_ci 1612cabdff1aSopenharmony_ci res = nvenc_push_context(avctx); 1613cabdff1aSopenharmony_ci if (res < 0) 1614cabdff1aSopenharmony_ci return res; 1615cabdff1aSopenharmony_ci 1616cabdff1aSopenharmony_ci for (i = 0; i < ctx->nb_surfaces; i++) { 1617cabdff1aSopenharmony_ci if ((res = nvenc_alloc_surface(avctx, i)) < 0) 1618cabdff1aSopenharmony_ci goto fail; 1619cabdff1aSopenharmony_ci } 1620cabdff1aSopenharmony_ci 1621cabdff1aSopenharmony_cifail: 1622cabdff1aSopenharmony_ci res2 = nvenc_pop_context(avctx); 1623cabdff1aSopenharmony_ci if (res2 < 0) 1624cabdff1aSopenharmony_ci return res2; 1625cabdff1aSopenharmony_ci 1626cabdff1aSopenharmony_ci return res; 1627cabdff1aSopenharmony_ci} 1628cabdff1aSopenharmony_ci 1629cabdff1aSopenharmony_cistatic av_cold int nvenc_setup_extradata(AVCodecContext *avctx) 1630cabdff1aSopenharmony_ci{ 1631cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1632cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 1633cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 1634cabdff1aSopenharmony_ci 1635cabdff1aSopenharmony_ci NVENCSTATUS nv_status; 1636cabdff1aSopenharmony_ci uint32_t outSize = 0; 1637cabdff1aSopenharmony_ci char tmpHeader[256]; 1638cabdff1aSopenharmony_ci NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 }; 1639cabdff1aSopenharmony_ci payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER; 1640cabdff1aSopenharmony_ci 1641cabdff1aSopenharmony_ci payload.spsppsBuffer = tmpHeader; 1642cabdff1aSopenharmony_ci payload.inBufferSize = sizeof(tmpHeader); 1643cabdff1aSopenharmony_ci payload.outSPSPPSPayloadSize = &outSize; 1644cabdff1aSopenharmony_ci 1645cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncGetSequenceParams(ctx->nvencoder, &payload); 1646cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1647cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "GetSequenceParams failed"); 1648cabdff1aSopenharmony_ci } 1649cabdff1aSopenharmony_ci 1650cabdff1aSopenharmony_ci avctx->extradata_size = outSize; 1651cabdff1aSopenharmony_ci avctx->extradata = av_mallocz(outSize + AV_INPUT_BUFFER_PADDING_SIZE); 1652cabdff1aSopenharmony_ci 1653cabdff1aSopenharmony_ci if (!avctx->extradata) { 1654cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1655cabdff1aSopenharmony_ci } 1656cabdff1aSopenharmony_ci 1657cabdff1aSopenharmony_ci memcpy(avctx->extradata, tmpHeader, outSize); 1658cabdff1aSopenharmony_ci 1659cabdff1aSopenharmony_ci return 0; 1660cabdff1aSopenharmony_ci} 1661cabdff1aSopenharmony_ci 1662cabdff1aSopenharmony_ciav_cold int ff_nvenc_encode_close(AVCodecContext *avctx) 1663cabdff1aSopenharmony_ci{ 1664cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1665cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 1666cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 1667cabdff1aSopenharmony_ci int i, res; 1668cabdff1aSopenharmony_ci 1669cabdff1aSopenharmony_ci /* the encoder has to be flushed before it can be closed */ 1670cabdff1aSopenharmony_ci if (ctx->nvencoder) { 1671cabdff1aSopenharmony_ci NV_ENC_PIC_PARAMS params = { .version = NV_ENC_PIC_PARAMS_VER, 1672cabdff1aSopenharmony_ci .encodePicFlags = NV_ENC_PIC_FLAG_EOS }; 1673cabdff1aSopenharmony_ci 1674cabdff1aSopenharmony_ci res = nvenc_push_context(avctx); 1675cabdff1aSopenharmony_ci if (res < 0) 1676cabdff1aSopenharmony_ci return res; 1677cabdff1aSopenharmony_ci 1678cabdff1aSopenharmony_ci p_nvenc->nvEncEncodePicture(ctx->nvencoder, ¶ms); 1679cabdff1aSopenharmony_ci } 1680cabdff1aSopenharmony_ci 1681cabdff1aSopenharmony_ci av_fifo_freep2(&ctx->timestamp_list); 1682cabdff1aSopenharmony_ci av_fifo_freep2(&ctx->output_surface_ready_queue); 1683cabdff1aSopenharmony_ci av_fifo_freep2(&ctx->output_surface_queue); 1684cabdff1aSopenharmony_ci av_fifo_freep2(&ctx->unused_surface_queue); 1685cabdff1aSopenharmony_ci 1686cabdff1aSopenharmony_ci if (ctx->surfaces && (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11)) { 1687cabdff1aSopenharmony_ci for (i = 0; i < ctx->nb_registered_frames; i++) { 1688cabdff1aSopenharmony_ci if (ctx->registered_frames[i].mapped) 1689cabdff1aSopenharmony_ci p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[i].in_map.mappedResource); 1690cabdff1aSopenharmony_ci if (ctx->registered_frames[i].regptr) 1691cabdff1aSopenharmony_ci p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr); 1692cabdff1aSopenharmony_ci } 1693cabdff1aSopenharmony_ci ctx->nb_registered_frames = 0; 1694cabdff1aSopenharmony_ci } 1695cabdff1aSopenharmony_ci 1696cabdff1aSopenharmony_ci if (ctx->surfaces) { 1697cabdff1aSopenharmony_ci for (i = 0; i < ctx->nb_surfaces; ++i) { 1698cabdff1aSopenharmony_ci if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11) 1699cabdff1aSopenharmony_ci p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[i].input_surface); 1700cabdff1aSopenharmony_ci av_frame_free(&ctx->surfaces[i].in_ref); 1701cabdff1aSopenharmony_ci p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->surfaces[i].output_surface); 1702cabdff1aSopenharmony_ci } 1703cabdff1aSopenharmony_ci } 1704cabdff1aSopenharmony_ci av_freep(&ctx->surfaces); 1705cabdff1aSopenharmony_ci ctx->nb_surfaces = 0; 1706cabdff1aSopenharmony_ci 1707cabdff1aSopenharmony_ci av_frame_free(&ctx->frame); 1708cabdff1aSopenharmony_ci 1709cabdff1aSopenharmony_ci av_freep(&ctx->sei_data); 1710cabdff1aSopenharmony_ci 1711cabdff1aSopenharmony_ci if (ctx->nvencoder) { 1712cabdff1aSopenharmony_ci p_nvenc->nvEncDestroyEncoder(ctx->nvencoder); 1713cabdff1aSopenharmony_ci 1714cabdff1aSopenharmony_ci res = nvenc_pop_context(avctx); 1715cabdff1aSopenharmony_ci if (res < 0) 1716cabdff1aSopenharmony_ci return res; 1717cabdff1aSopenharmony_ci } 1718cabdff1aSopenharmony_ci ctx->nvencoder = NULL; 1719cabdff1aSopenharmony_ci 1720cabdff1aSopenharmony_ci if (ctx->cu_context_internal) 1721cabdff1aSopenharmony_ci CHECK_CU(dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal)); 1722cabdff1aSopenharmony_ci ctx->cu_context = ctx->cu_context_internal = NULL; 1723cabdff1aSopenharmony_ci 1724cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 1725cabdff1aSopenharmony_ci if (ctx->d3d11_device) { 1726cabdff1aSopenharmony_ci ID3D11Device_Release(ctx->d3d11_device); 1727cabdff1aSopenharmony_ci ctx->d3d11_device = NULL; 1728cabdff1aSopenharmony_ci } 1729cabdff1aSopenharmony_ci#endif 1730cabdff1aSopenharmony_ci 1731cabdff1aSopenharmony_ci nvenc_free_functions(&dl_fn->nvenc_dl); 1732cabdff1aSopenharmony_ci cuda_free_functions(&dl_fn->cuda_dl); 1733cabdff1aSopenharmony_ci 1734cabdff1aSopenharmony_ci dl_fn->nvenc_device_count = 0; 1735cabdff1aSopenharmony_ci 1736cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Nvenc unloaded\n"); 1737cabdff1aSopenharmony_ci 1738cabdff1aSopenharmony_ci return 0; 1739cabdff1aSopenharmony_ci} 1740cabdff1aSopenharmony_ci 1741cabdff1aSopenharmony_ciav_cold int ff_nvenc_encode_init(AVCodecContext *avctx) 1742cabdff1aSopenharmony_ci{ 1743cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1744cabdff1aSopenharmony_ci int ret; 1745cabdff1aSopenharmony_ci 1746cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { 1747cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx; 1748cabdff1aSopenharmony_ci if (!avctx->hw_frames_ctx) { 1749cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 1750cabdff1aSopenharmony_ci "hw_frames_ctx must be set when using GPU frames as input\n"); 1751cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1752cabdff1aSopenharmony_ci } 1753cabdff1aSopenharmony_ci frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 1754cabdff1aSopenharmony_ci if (frames_ctx->format != avctx->pix_fmt) { 1755cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 1756cabdff1aSopenharmony_ci "hw_frames_ctx must match the GPU frame type\n"); 1757cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1758cabdff1aSopenharmony_ci } 1759cabdff1aSopenharmony_ci ctx->data_pix_fmt = frames_ctx->sw_format; 1760cabdff1aSopenharmony_ci } else { 1761cabdff1aSopenharmony_ci ctx->data_pix_fmt = avctx->pix_fmt; 1762cabdff1aSopenharmony_ci } 1763cabdff1aSopenharmony_ci 1764cabdff1aSopenharmony_ci ctx->frame = av_frame_alloc(); 1765cabdff1aSopenharmony_ci if (!ctx->frame) 1766cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1767cabdff1aSopenharmony_ci 1768cabdff1aSopenharmony_ci if ((ret = nvenc_load_libraries(avctx)) < 0) 1769cabdff1aSopenharmony_ci return ret; 1770cabdff1aSopenharmony_ci 1771cabdff1aSopenharmony_ci if ((ret = nvenc_setup_device(avctx)) < 0) 1772cabdff1aSopenharmony_ci return ret; 1773cabdff1aSopenharmony_ci 1774cabdff1aSopenharmony_ci if ((ret = nvenc_setup_encoder(avctx)) < 0) 1775cabdff1aSopenharmony_ci return ret; 1776cabdff1aSopenharmony_ci 1777cabdff1aSopenharmony_ci if ((ret = nvenc_setup_surfaces(avctx)) < 0) 1778cabdff1aSopenharmony_ci return ret; 1779cabdff1aSopenharmony_ci 1780cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { 1781cabdff1aSopenharmony_ci if ((ret = nvenc_setup_extradata(avctx)) < 0) 1782cabdff1aSopenharmony_ci return ret; 1783cabdff1aSopenharmony_ci } 1784cabdff1aSopenharmony_ci 1785cabdff1aSopenharmony_ci return 0; 1786cabdff1aSopenharmony_ci} 1787cabdff1aSopenharmony_ci 1788cabdff1aSopenharmony_cistatic NvencSurface *get_free_frame(NvencContext *ctx) 1789cabdff1aSopenharmony_ci{ 1790cabdff1aSopenharmony_ci NvencSurface *tmp_surf; 1791cabdff1aSopenharmony_ci 1792cabdff1aSopenharmony_ci if (av_fifo_read(ctx->unused_surface_queue, &tmp_surf, 1) < 0) 1793cabdff1aSopenharmony_ci // queue empty 1794cabdff1aSopenharmony_ci return NULL; 1795cabdff1aSopenharmony_ci 1796cabdff1aSopenharmony_ci return tmp_surf; 1797cabdff1aSopenharmony_ci} 1798cabdff1aSopenharmony_ci 1799cabdff1aSopenharmony_cistatic int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *nv_surface, 1800cabdff1aSopenharmony_ci NV_ENC_LOCK_INPUT_BUFFER *lock_buffer_params, const AVFrame *frame) 1801cabdff1aSopenharmony_ci{ 1802cabdff1aSopenharmony_ci int dst_linesize[4] = { 1803cabdff1aSopenharmony_ci lock_buffer_params->pitch, 1804cabdff1aSopenharmony_ci lock_buffer_params->pitch, 1805cabdff1aSopenharmony_ci lock_buffer_params->pitch, 1806cabdff1aSopenharmony_ci lock_buffer_params->pitch 1807cabdff1aSopenharmony_ci }; 1808cabdff1aSopenharmony_ci uint8_t *dst_data[4]; 1809cabdff1aSopenharmony_ci int ret; 1810cabdff1aSopenharmony_ci 1811cabdff1aSopenharmony_ci if (frame->format == AV_PIX_FMT_YUV420P) 1812cabdff1aSopenharmony_ci dst_linesize[1] = dst_linesize[2] >>= 1; 1813cabdff1aSopenharmony_ci 1814cabdff1aSopenharmony_ci ret = av_image_fill_pointers(dst_data, frame->format, nv_surface->height, 1815cabdff1aSopenharmony_ci lock_buffer_params->bufferDataPtr, dst_linesize); 1816cabdff1aSopenharmony_ci if (ret < 0) 1817cabdff1aSopenharmony_ci return ret; 1818cabdff1aSopenharmony_ci 1819cabdff1aSopenharmony_ci if (frame->format == AV_PIX_FMT_YUV420P) 1820cabdff1aSopenharmony_ci FFSWAP(uint8_t*, dst_data[1], dst_data[2]); 1821cabdff1aSopenharmony_ci 1822cabdff1aSopenharmony_ci av_image_copy(dst_data, dst_linesize, 1823cabdff1aSopenharmony_ci (const uint8_t**)frame->data, frame->linesize, frame->format, 1824cabdff1aSopenharmony_ci avctx->width, avctx->height); 1825cabdff1aSopenharmony_ci 1826cabdff1aSopenharmony_ci return 0; 1827cabdff1aSopenharmony_ci} 1828cabdff1aSopenharmony_ci 1829cabdff1aSopenharmony_cistatic int nvenc_find_free_reg_resource(AVCodecContext *avctx) 1830cabdff1aSopenharmony_ci{ 1831cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1832cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 1833cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 1834cabdff1aSopenharmony_ci NVENCSTATUS nv_status; 1835cabdff1aSopenharmony_ci 1836cabdff1aSopenharmony_ci int i, first_round; 1837cabdff1aSopenharmony_ci 1838cabdff1aSopenharmony_ci if (ctx->nb_registered_frames == FF_ARRAY_ELEMS(ctx->registered_frames)) { 1839cabdff1aSopenharmony_ci for (first_round = 1; first_round >= 0; first_round--) { 1840cabdff1aSopenharmony_ci for (i = 0; i < ctx->nb_registered_frames; i++) { 1841cabdff1aSopenharmony_ci if (!ctx->registered_frames[i].mapped) { 1842cabdff1aSopenharmony_ci if (ctx->registered_frames[i].regptr) { 1843cabdff1aSopenharmony_ci if (first_round) 1844cabdff1aSopenharmony_ci continue; 1845cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr); 1846cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) 1847cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "Failed unregistering unused input resource"); 1848cabdff1aSopenharmony_ci ctx->registered_frames[i].ptr = NULL; 1849cabdff1aSopenharmony_ci ctx->registered_frames[i].regptr = NULL; 1850cabdff1aSopenharmony_ci } 1851cabdff1aSopenharmony_ci return i; 1852cabdff1aSopenharmony_ci } 1853cabdff1aSopenharmony_ci } 1854cabdff1aSopenharmony_ci } 1855cabdff1aSopenharmony_ci } else { 1856cabdff1aSopenharmony_ci return ctx->nb_registered_frames++; 1857cabdff1aSopenharmony_ci } 1858cabdff1aSopenharmony_ci 1859cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Too many registered CUDA frames\n"); 1860cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1861cabdff1aSopenharmony_ci} 1862cabdff1aSopenharmony_ci 1863cabdff1aSopenharmony_cistatic int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) 1864cabdff1aSopenharmony_ci{ 1865cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1866cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 1867cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 1868cabdff1aSopenharmony_ci 1869cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frame->hw_frames_ctx->data; 1870cabdff1aSopenharmony_ci NV_ENC_REGISTER_RESOURCE reg = { 0 }; 1871cabdff1aSopenharmony_ci int i, idx, ret; 1872cabdff1aSopenharmony_ci 1873cabdff1aSopenharmony_ci for (i = 0; i < ctx->nb_registered_frames; i++) { 1874cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_CUDA && ctx->registered_frames[i].ptr == frame->data[0]) 1875cabdff1aSopenharmony_ci return i; 1876cabdff1aSopenharmony_ci else if (avctx->pix_fmt == AV_PIX_FMT_D3D11 && ctx->registered_frames[i].ptr == frame->data[0] && ctx->registered_frames[i].ptr_index == (intptr_t)frame->data[1]) 1877cabdff1aSopenharmony_ci return i; 1878cabdff1aSopenharmony_ci } 1879cabdff1aSopenharmony_ci 1880cabdff1aSopenharmony_ci idx = nvenc_find_free_reg_resource(avctx); 1881cabdff1aSopenharmony_ci if (idx < 0) 1882cabdff1aSopenharmony_ci return idx; 1883cabdff1aSopenharmony_ci 1884cabdff1aSopenharmony_ci reg.version = NV_ENC_REGISTER_RESOURCE_VER; 1885cabdff1aSopenharmony_ci reg.width = frames_ctx->width; 1886cabdff1aSopenharmony_ci reg.height = frames_ctx->height; 1887cabdff1aSopenharmony_ci reg.pitch = frame->linesize[0]; 1888cabdff1aSopenharmony_ci reg.resourceToRegister = frame->data[0]; 1889cabdff1aSopenharmony_ci 1890cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { 1891cabdff1aSopenharmony_ci reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR; 1892cabdff1aSopenharmony_ci } 1893cabdff1aSopenharmony_ci else if (avctx->pix_fmt == AV_PIX_FMT_D3D11) { 1894cabdff1aSopenharmony_ci reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX; 1895cabdff1aSopenharmony_ci reg.subResourceIndex = (intptr_t)frame->data[1]; 1896cabdff1aSopenharmony_ci } 1897cabdff1aSopenharmony_ci 1898cabdff1aSopenharmony_ci reg.bufferFormat = nvenc_map_buffer_format(frames_ctx->sw_format); 1899cabdff1aSopenharmony_ci if (reg.bufferFormat == NV_ENC_BUFFER_FORMAT_UNDEFINED) { 1900cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n", 1901cabdff1aSopenharmony_ci av_get_pix_fmt_name(frames_ctx->sw_format)); 1902cabdff1aSopenharmony_ci return AVERROR(EINVAL); 1903cabdff1aSopenharmony_ci } 1904cabdff1aSopenharmony_ci 1905cabdff1aSopenharmony_ci ret = p_nvenc->nvEncRegisterResource(ctx->nvencoder, ®); 1906cabdff1aSopenharmony_ci if (ret != NV_ENC_SUCCESS) { 1907cabdff1aSopenharmony_ci nvenc_print_error(avctx, ret, "Error registering an input resource"); 1908cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 1909cabdff1aSopenharmony_ci } 1910cabdff1aSopenharmony_ci 1911cabdff1aSopenharmony_ci ctx->registered_frames[idx].ptr = frame->data[0]; 1912cabdff1aSopenharmony_ci ctx->registered_frames[idx].ptr_index = reg.subResourceIndex; 1913cabdff1aSopenharmony_ci ctx->registered_frames[idx].regptr = reg.registeredResource; 1914cabdff1aSopenharmony_ci return idx; 1915cabdff1aSopenharmony_ci} 1916cabdff1aSopenharmony_ci 1917cabdff1aSopenharmony_cistatic int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame, 1918cabdff1aSopenharmony_ci NvencSurface *nvenc_frame) 1919cabdff1aSopenharmony_ci{ 1920cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1921cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 1922cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 1923cabdff1aSopenharmony_ci 1924cabdff1aSopenharmony_ci int res; 1925cabdff1aSopenharmony_ci NVENCSTATUS nv_status; 1926cabdff1aSopenharmony_ci 1927cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { 1928cabdff1aSopenharmony_ci int reg_idx = nvenc_register_frame(avctx, frame); 1929cabdff1aSopenharmony_ci if (reg_idx < 0) { 1930cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not register an input HW frame\n"); 1931cabdff1aSopenharmony_ci return reg_idx; 1932cabdff1aSopenharmony_ci } 1933cabdff1aSopenharmony_ci 1934cabdff1aSopenharmony_ci res = av_frame_ref(nvenc_frame->in_ref, frame); 1935cabdff1aSopenharmony_ci if (res < 0) 1936cabdff1aSopenharmony_ci return res; 1937cabdff1aSopenharmony_ci 1938cabdff1aSopenharmony_ci if (!ctx->registered_frames[reg_idx].mapped) { 1939cabdff1aSopenharmony_ci ctx->registered_frames[reg_idx].in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER; 1940cabdff1aSopenharmony_ci ctx->registered_frames[reg_idx].in_map.registeredResource = ctx->registered_frames[reg_idx].regptr; 1941cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &ctx->registered_frames[reg_idx].in_map); 1942cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1943cabdff1aSopenharmony_ci av_frame_unref(nvenc_frame->in_ref); 1944cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "Error mapping an input resource"); 1945cabdff1aSopenharmony_ci } 1946cabdff1aSopenharmony_ci } 1947cabdff1aSopenharmony_ci 1948cabdff1aSopenharmony_ci ctx->registered_frames[reg_idx].mapped += 1; 1949cabdff1aSopenharmony_ci 1950cabdff1aSopenharmony_ci nvenc_frame->reg_idx = reg_idx; 1951cabdff1aSopenharmony_ci nvenc_frame->input_surface = ctx->registered_frames[reg_idx].in_map.mappedResource; 1952cabdff1aSopenharmony_ci nvenc_frame->format = ctx->registered_frames[reg_idx].in_map.mappedBufferFmt; 1953cabdff1aSopenharmony_ci nvenc_frame->pitch = frame->linesize[0]; 1954cabdff1aSopenharmony_ci 1955cabdff1aSopenharmony_ci return 0; 1956cabdff1aSopenharmony_ci } else { 1957cabdff1aSopenharmony_ci NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 }; 1958cabdff1aSopenharmony_ci 1959cabdff1aSopenharmony_ci lockBufferParams.version = NV_ENC_LOCK_INPUT_BUFFER_VER; 1960cabdff1aSopenharmony_ci lockBufferParams.inputBuffer = nvenc_frame->input_surface; 1961cabdff1aSopenharmony_ci 1962cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams); 1963cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1964cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "Failed locking nvenc input buffer"); 1965cabdff1aSopenharmony_ci } 1966cabdff1aSopenharmony_ci 1967cabdff1aSopenharmony_ci nvenc_frame->pitch = lockBufferParams.pitch; 1968cabdff1aSopenharmony_ci res = nvenc_copy_frame(avctx, nvenc_frame, &lockBufferParams, frame); 1969cabdff1aSopenharmony_ci 1970cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncUnlockInputBuffer(ctx->nvencoder, nvenc_frame->input_surface); 1971cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 1972cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "Failed unlocking input buffer!"); 1973cabdff1aSopenharmony_ci } 1974cabdff1aSopenharmony_ci 1975cabdff1aSopenharmony_ci return res; 1976cabdff1aSopenharmony_ci } 1977cabdff1aSopenharmony_ci} 1978cabdff1aSopenharmony_ci 1979cabdff1aSopenharmony_cistatic void nvenc_codec_specific_pic_params(AVCodecContext *avctx, 1980cabdff1aSopenharmony_ci NV_ENC_PIC_PARAMS *params, 1981cabdff1aSopenharmony_ci NV_ENC_SEI_PAYLOAD *sei_data, 1982cabdff1aSopenharmony_ci int sei_count) 1983cabdff1aSopenharmony_ci{ 1984cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 1985cabdff1aSopenharmony_ci 1986cabdff1aSopenharmony_ci switch (avctx->codec->id) { 1987cabdff1aSopenharmony_ci case AV_CODEC_ID_H264: 1988cabdff1aSopenharmony_ci params->codecPicParams.h264PicParams.sliceMode = 1989cabdff1aSopenharmony_ci ctx->encode_config.encodeCodecConfig.h264Config.sliceMode; 1990cabdff1aSopenharmony_ci params->codecPicParams.h264PicParams.sliceModeData = 1991cabdff1aSopenharmony_ci ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData; 1992cabdff1aSopenharmony_ci if (sei_count > 0) { 1993cabdff1aSopenharmony_ci params->codecPicParams.h264PicParams.seiPayloadArray = sei_data; 1994cabdff1aSopenharmony_ci params->codecPicParams.h264PicParams.seiPayloadArrayCnt = sei_count; 1995cabdff1aSopenharmony_ci } 1996cabdff1aSopenharmony_ci 1997cabdff1aSopenharmony_ci break; 1998cabdff1aSopenharmony_ci case AV_CODEC_ID_HEVC: 1999cabdff1aSopenharmony_ci params->codecPicParams.hevcPicParams.sliceMode = 2000cabdff1aSopenharmony_ci ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode; 2001cabdff1aSopenharmony_ci params->codecPicParams.hevcPicParams.sliceModeData = 2002cabdff1aSopenharmony_ci ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData; 2003cabdff1aSopenharmony_ci if (sei_count > 0) { 2004cabdff1aSopenharmony_ci params->codecPicParams.hevcPicParams.seiPayloadArray = sei_data; 2005cabdff1aSopenharmony_ci params->codecPicParams.hevcPicParams.seiPayloadArrayCnt = sei_count; 2006cabdff1aSopenharmony_ci } 2007cabdff1aSopenharmony_ci 2008cabdff1aSopenharmony_ci break; 2009cabdff1aSopenharmony_ci } 2010cabdff1aSopenharmony_ci} 2011cabdff1aSopenharmony_ci 2012cabdff1aSopenharmony_cistatic inline void timestamp_queue_enqueue(AVFifo *queue, int64_t timestamp) 2013cabdff1aSopenharmony_ci{ 2014cabdff1aSopenharmony_ci av_fifo_write(queue, ×tamp, 1); 2015cabdff1aSopenharmony_ci} 2016cabdff1aSopenharmony_ci 2017cabdff1aSopenharmony_cistatic inline int64_t timestamp_queue_dequeue(AVFifo *queue) 2018cabdff1aSopenharmony_ci{ 2019cabdff1aSopenharmony_ci int64_t timestamp = AV_NOPTS_VALUE; 2020cabdff1aSopenharmony_ci // The following call might fail if the queue is empty. 2021cabdff1aSopenharmony_ci av_fifo_read(queue, ×tamp, 1); 2022cabdff1aSopenharmony_ci 2023cabdff1aSopenharmony_ci return timestamp; 2024cabdff1aSopenharmony_ci} 2025cabdff1aSopenharmony_ci 2026cabdff1aSopenharmony_cistatic int nvenc_set_timestamp(AVCodecContext *avctx, 2027cabdff1aSopenharmony_ci NV_ENC_LOCK_BITSTREAM *params, 2028cabdff1aSopenharmony_ci AVPacket *pkt) 2029cabdff1aSopenharmony_ci{ 2030cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2031cabdff1aSopenharmony_ci 2032cabdff1aSopenharmony_ci pkt->pts = params->outputTimeStamp; 2033cabdff1aSopenharmony_ci pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list); 2034cabdff1aSopenharmony_ci 2035cabdff1aSopenharmony_ci pkt->dts -= FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1) * FFMAX(avctx->time_base.num, 1); 2036cabdff1aSopenharmony_ci 2037cabdff1aSopenharmony_ci return 0; 2038cabdff1aSopenharmony_ci} 2039cabdff1aSopenharmony_ci 2040cabdff1aSopenharmony_cistatic int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSurface *tmpoutsurf) 2041cabdff1aSopenharmony_ci{ 2042cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2043cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 2044cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 2045cabdff1aSopenharmony_ci 2046cabdff1aSopenharmony_ci uint32_t slice_mode_data; 2047cabdff1aSopenharmony_ci uint32_t *slice_offsets = NULL; 2048cabdff1aSopenharmony_ci NV_ENC_LOCK_BITSTREAM lock_params = { 0 }; 2049cabdff1aSopenharmony_ci NVENCSTATUS nv_status; 2050cabdff1aSopenharmony_ci int res = 0; 2051cabdff1aSopenharmony_ci 2052cabdff1aSopenharmony_ci enum AVPictureType pict_type; 2053cabdff1aSopenharmony_ci 2054cabdff1aSopenharmony_ci switch (avctx->codec->id) { 2055cabdff1aSopenharmony_ci case AV_CODEC_ID_H264: 2056cabdff1aSopenharmony_ci slice_mode_data = ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData; 2057cabdff1aSopenharmony_ci break; 2058cabdff1aSopenharmony_ci case AV_CODEC_ID_H265: 2059cabdff1aSopenharmony_ci slice_mode_data = ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData; 2060cabdff1aSopenharmony_ci break; 2061cabdff1aSopenharmony_ci default: 2062cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unknown codec name\n"); 2063cabdff1aSopenharmony_ci res = AVERROR(EINVAL); 2064cabdff1aSopenharmony_ci goto error; 2065cabdff1aSopenharmony_ci } 2066cabdff1aSopenharmony_ci slice_offsets = av_mallocz(slice_mode_data * sizeof(*slice_offsets)); 2067cabdff1aSopenharmony_ci 2068cabdff1aSopenharmony_ci if (!slice_offsets) { 2069cabdff1aSopenharmony_ci res = AVERROR(ENOMEM); 2070cabdff1aSopenharmony_ci goto error; 2071cabdff1aSopenharmony_ci } 2072cabdff1aSopenharmony_ci 2073cabdff1aSopenharmony_ci lock_params.version = NV_ENC_LOCK_BITSTREAM_VER; 2074cabdff1aSopenharmony_ci 2075cabdff1aSopenharmony_ci lock_params.doNotWait = 0; 2076cabdff1aSopenharmony_ci lock_params.outputBitstream = tmpoutsurf->output_surface; 2077cabdff1aSopenharmony_ci lock_params.sliceOffsets = slice_offsets; 2078cabdff1aSopenharmony_ci 2079cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncLockBitstream(ctx->nvencoder, &lock_params); 2080cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 2081cabdff1aSopenharmony_ci res = nvenc_print_error(avctx, nv_status, "Failed locking bitstream buffer"); 2082cabdff1aSopenharmony_ci goto error; 2083cabdff1aSopenharmony_ci } 2084cabdff1aSopenharmony_ci 2085cabdff1aSopenharmony_ci res = ff_get_encode_buffer(avctx, pkt, lock_params.bitstreamSizeInBytes, 0); 2086cabdff1aSopenharmony_ci 2087cabdff1aSopenharmony_ci if (res < 0) { 2088cabdff1aSopenharmony_ci p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface); 2089cabdff1aSopenharmony_ci goto error; 2090cabdff1aSopenharmony_ci } 2091cabdff1aSopenharmony_ci 2092cabdff1aSopenharmony_ci memcpy(pkt->data, lock_params.bitstreamBufferPtr, lock_params.bitstreamSizeInBytes); 2093cabdff1aSopenharmony_ci 2094cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface); 2095cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 2096cabdff1aSopenharmony_ci res = nvenc_print_error(avctx, nv_status, "Failed unlocking bitstream buffer, expect the gates of mordor to open"); 2097cabdff1aSopenharmony_ci goto error; 2098cabdff1aSopenharmony_ci } 2099cabdff1aSopenharmony_ci 2100cabdff1aSopenharmony_ci 2101cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) { 2102cabdff1aSopenharmony_ci ctx->registered_frames[tmpoutsurf->reg_idx].mapped -= 1; 2103cabdff1aSopenharmony_ci if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped == 0) { 2104cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].in_map.mappedResource); 2105cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS) { 2106cabdff1aSopenharmony_ci res = nvenc_print_error(avctx, nv_status, "Failed unmapping input resource"); 2107cabdff1aSopenharmony_ci goto error; 2108cabdff1aSopenharmony_ci } 2109cabdff1aSopenharmony_ci } else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) { 2110cabdff1aSopenharmony_ci res = AVERROR_BUG; 2111cabdff1aSopenharmony_ci goto error; 2112cabdff1aSopenharmony_ci } 2113cabdff1aSopenharmony_ci 2114cabdff1aSopenharmony_ci av_frame_unref(tmpoutsurf->in_ref); 2115cabdff1aSopenharmony_ci 2116cabdff1aSopenharmony_ci tmpoutsurf->input_surface = NULL; 2117cabdff1aSopenharmony_ci } 2118cabdff1aSopenharmony_ci 2119cabdff1aSopenharmony_ci switch (lock_params.pictureType) { 2120cabdff1aSopenharmony_ci case NV_ENC_PIC_TYPE_IDR: 2121cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 2122cabdff1aSopenharmony_ci case NV_ENC_PIC_TYPE_I: 2123cabdff1aSopenharmony_ci pict_type = AV_PICTURE_TYPE_I; 2124cabdff1aSopenharmony_ci break; 2125cabdff1aSopenharmony_ci case NV_ENC_PIC_TYPE_P: 2126cabdff1aSopenharmony_ci pict_type = AV_PICTURE_TYPE_P; 2127cabdff1aSopenharmony_ci break; 2128cabdff1aSopenharmony_ci case NV_ENC_PIC_TYPE_B: 2129cabdff1aSopenharmony_ci pict_type = AV_PICTURE_TYPE_B; 2130cabdff1aSopenharmony_ci break; 2131cabdff1aSopenharmony_ci case NV_ENC_PIC_TYPE_BI: 2132cabdff1aSopenharmony_ci pict_type = AV_PICTURE_TYPE_BI; 2133cabdff1aSopenharmony_ci break; 2134cabdff1aSopenharmony_ci default: 2135cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered, expect the output to be broken.\n"); 2136cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Please report this error and include as much information on how to reproduce it as possible.\n"); 2137cabdff1aSopenharmony_ci res = AVERROR_EXTERNAL; 2138cabdff1aSopenharmony_ci goto error; 2139cabdff1aSopenharmony_ci } 2140cabdff1aSopenharmony_ci 2141cabdff1aSopenharmony_ci ff_side_data_set_encoder_stats(pkt, 2142cabdff1aSopenharmony_ci (lock_params.frameAvgQP - 1) * FF_QP2LAMBDA, NULL, 0, pict_type); 2143cabdff1aSopenharmony_ci 2144cabdff1aSopenharmony_ci res = nvenc_set_timestamp(avctx, &lock_params, pkt); 2145cabdff1aSopenharmony_ci if (res < 0) 2146cabdff1aSopenharmony_ci goto error2; 2147cabdff1aSopenharmony_ci 2148cabdff1aSopenharmony_ci av_free(slice_offsets); 2149cabdff1aSopenharmony_ci 2150cabdff1aSopenharmony_ci return 0; 2151cabdff1aSopenharmony_ci 2152cabdff1aSopenharmony_cierror: 2153cabdff1aSopenharmony_ci timestamp_queue_dequeue(ctx->timestamp_list); 2154cabdff1aSopenharmony_ci 2155cabdff1aSopenharmony_cierror2: 2156cabdff1aSopenharmony_ci av_free(slice_offsets); 2157cabdff1aSopenharmony_ci 2158cabdff1aSopenharmony_ci return res; 2159cabdff1aSopenharmony_ci} 2160cabdff1aSopenharmony_ci 2161cabdff1aSopenharmony_cistatic int output_ready(AVCodecContext *avctx, int flush) 2162cabdff1aSopenharmony_ci{ 2163cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2164cabdff1aSopenharmony_ci int nb_ready, nb_pending; 2165cabdff1aSopenharmony_ci 2166cabdff1aSopenharmony_ci nb_ready = av_fifo_can_read(ctx->output_surface_ready_queue); 2167cabdff1aSopenharmony_ci nb_pending = av_fifo_can_read(ctx->output_surface_queue); 2168cabdff1aSopenharmony_ci if (flush) 2169cabdff1aSopenharmony_ci return nb_ready > 0; 2170cabdff1aSopenharmony_ci return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth); 2171cabdff1aSopenharmony_ci} 2172cabdff1aSopenharmony_ci 2173cabdff1aSopenharmony_cistatic int prepare_sei_data_array(AVCodecContext *avctx, const AVFrame *frame) 2174cabdff1aSopenharmony_ci{ 2175cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2176cabdff1aSopenharmony_ci int sei_count = 0; 2177cabdff1aSopenharmony_ci int i, res; 2178cabdff1aSopenharmony_ci 2179cabdff1aSopenharmony_ci if (ctx->a53_cc && av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC)) { 2180cabdff1aSopenharmony_ci void *a53_data = NULL; 2181cabdff1aSopenharmony_ci size_t a53_size = 0; 2182cabdff1aSopenharmony_ci 2183cabdff1aSopenharmony_ci if (ff_alloc_a53_sei(frame, 0, &a53_data, &a53_size) < 0) { 2184cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n"); 2185cabdff1aSopenharmony_ci } 2186cabdff1aSopenharmony_ci 2187cabdff1aSopenharmony_ci if (a53_data) { 2188cabdff1aSopenharmony_ci void *tmp = av_fast_realloc(ctx->sei_data, 2189cabdff1aSopenharmony_ci &ctx->sei_data_size, 2190cabdff1aSopenharmony_ci (sei_count + 1) * sizeof(*ctx->sei_data)); 2191cabdff1aSopenharmony_ci if (!tmp) { 2192cabdff1aSopenharmony_ci av_free(a53_data); 2193cabdff1aSopenharmony_ci res = AVERROR(ENOMEM); 2194cabdff1aSopenharmony_ci goto error; 2195cabdff1aSopenharmony_ci } else { 2196cabdff1aSopenharmony_ci ctx->sei_data = tmp; 2197cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payloadSize = (uint32_t)a53_size; 2198cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payloadType = 4; 2199cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payload = (uint8_t*)a53_data; 2200cabdff1aSopenharmony_ci sei_count++; 2201cabdff1aSopenharmony_ci } 2202cabdff1aSopenharmony_ci } 2203cabdff1aSopenharmony_ci } 2204cabdff1aSopenharmony_ci 2205cabdff1aSopenharmony_ci if (ctx->s12m_tc && av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE)) { 2206cabdff1aSopenharmony_ci void *tc_data = NULL; 2207cabdff1aSopenharmony_ci size_t tc_size = 0; 2208cabdff1aSopenharmony_ci 2209cabdff1aSopenharmony_ci if (ff_alloc_timecode_sei(frame, avctx->framerate, 0, &tc_data, &tc_size) < 0) { 2210cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Not enough memory for timecode sei, skipping\n"); 2211cabdff1aSopenharmony_ci } 2212cabdff1aSopenharmony_ci 2213cabdff1aSopenharmony_ci if (tc_data) { 2214cabdff1aSopenharmony_ci void *tmp = av_fast_realloc(ctx->sei_data, 2215cabdff1aSopenharmony_ci &ctx->sei_data_size, 2216cabdff1aSopenharmony_ci (sei_count + 1) * sizeof(*ctx->sei_data)); 2217cabdff1aSopenharmony_ci if (!tmp) { 2218cabdff1aSopenharmony_ci av_free(tc_data); 2219cabdff1aSopenharmony_ci res = AVERROR(ENOMEM); 2220cabdff1aSopenharmony_ci goto error; 2221cabdff1aSopenharmony_ci } else { 2222cabdff1aSopenharmony_ci ctx->sei_data = tmp; 2223cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payloadSize = (uint32_t)tc_size; 2224cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payloadType = SEI_TYPE_TIME_CODE; 2225cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payload = (uint8_t*)tc_data; 2226cabdff1aSopenharmony_ci sei_count++; 2227cabdff1aSopenharmony_ci } 2228cabdff1aSopenharmony_ci } 2229cabdff1aSopenharmony_ci } 2230cabdff1aSopenharmony_ci 2231cabdff1aSopenharmony_ci if (!ctx->udu_sei) 2232cabdff1aSopenharmony_ci return sei_count; 2233cabdff1aSopenharmony_ci 2234cabdff1aSopenharmony_ci for (i = 0; i < frame->nb_side_data; i++) { 2235cabdff1aSopenharmony_ci AVFrameSideData *side_data = frame->side_data[i]; 2236cabdff1aSopenharmony_ci void *tmp; 2237cabdff1aSopenharmony_ci 2238cabdff1aSopenharmony_ci if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) 2239cabdff1aSopenharmony_ci continue; 2240cabdff1aSopenharmony_ci 2241cabdff1aSopenharmony_ci tmp = av_fast_realloc(ctx->sei_data, 2242cabdff1aSopenharmony_ci &ctx->sei_data_size, 2243cabdff1aSopenharmony_ci (sei_count + 1) * sizeof(*ctx->sei_data)); 2244cabdff1aSopenharmony_ci if (!tmp) { 2245cabdff1aSopenharmony_ci res = AVERROR(ENOMEM); 2246cabdff1aSopenharmony_ci goto error; 2247cabdff1aSopenharmony_ci } else { 2248cabdff1aSopenharmony_ci ctx->sei_data = tmp; 2249cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payloadSize = side_data->size; 2250cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payloadType = SEI_TYPE_USER_DATA_UNREGISTERED; 2251cabdff1aSopenharmony_ci ctx->sei_data[sei_count].payload = av_memdup(side_data->data, side_data->size); 2252cabdff1aSopenharmony_ci 2253cabdff1aSopenharmony_ci if (!ctx->sei_data[sei_count].payload) { 2254cabdff1aSopenharmony_ci res = AVERROR(ENOMEM); 2255cabdff1aSopenharmony_ci goto error; 2256cabdff1aSopenharmony_ci } 2257cabdff1aSopenharmony_ci 2258cabdff1aSopenharmony_ci sei_count++; 2259cabdff1aSopenharmony_ci } 2260cabdff1aSopenharmony_ci } 2261cabdff1aSopenharmony_ci 2262cabdff1aSopenharmony_ci return sei_count; 2263cabdff1aSopenharmony_ci 2264cabdff1aSopenharmony_cierror: 2265cabdff1aSopenharmony_ci for (i = 0; i < sei_count; i++) 2266cabdff1aSopenharmony_ci av_freep(&(ctx->sei_data[i].payload)); 2267cabdff1aSopenharmony_ci 2268cabdff1aSopenharmony_ci return res; 2269cabdff1aSopenharmony_ci} 2270cabdff1aSopenharmony_ci 2271cabdff1aSopenharmony_cistatic void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame) 2272cabdff1aSopenharmony_ci{ 2273cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2274cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs; 2275cabdff1aSopenharmony_ci NVENCSTATUS ret; 2276cabdff1aSopenharmony_ci 2277cabdff1aSopenharmony_ci NV_ENC_RECONFIGURE_PARAMS params = { 0 }; 2278cabdff1aSopenharmony_ci int needs_reconfig = 0; 2279cabdff1aSopenharmony_ci int needs_encode_config = 0; 2280cabdff1aSopenharmony_ci int reconfig_bitrate = 0, reconfig_dar = 0; 2281cabdff1aSopenharmony_ci int dw, dh; 2282cabdff1aSopenharmony_ci 2283cabdff1aSopenharmony_ci params.version = NV_ENC_RECONFIGURE_PARAMS_VER; 2284cabdff1aSopenharmony_ci params.reInitEncodeParams = ctx->init_encode_params; 2285cabdff1aSopenharmony_ci 2286cabdff1aSopenharmony_ci compute_dar(avctx, &dw, &dh); 2287cabdff1aSopenharmony_ci if (dw != ctx->init_encode_params.darWidth || dh != ctx->init_encode_params.darHeight) { 2288cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, 2289cabdff1aSopenharmony_ci "aspect ratio change (DAR): %d:%d -> %d:%d\n", 2290cabdff1aSopenharmony_ci ctx->init_encode_params.darWidth, 2291cabdff1aSopenharmony_ci ctx->init_encode_params.darHeight, dw, dh); 2292cabdff1aSopenharmony_ci 2293cabdff1aSopenharmony_ci params.reInitEncodeParams.darHeight = dh; 2294cabdff1aSopenharmony_ci params.reInitEncodeParams.darWidth = dw; 2295cabdff1aSopenharmony_ci 2296cabdff1aSopenharmony_ci needs_reconfig = 1; 2297cabdff1aSopenharmony_ci reconfig_dar = 1; 2298cabdff1aSopenharmony_ci } 2299cabdff1aSopenharmony_ci 2300cabdff1aSopenharmony_ci if (ctx->rc != NV_ENC_PARAMS_RC_CONSTQP && ctx->support_dyn_bitrate) { 2301cabdff1aSopenharmony_ci if (avctx->bit_rate > 0 && params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate != avctx->bit_rate) { 2302cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, 2303cabdff1aSopenharmony_ci "avg bitrate change: %d -> %d\n", 2304cabdff1aSopenharmony_ci params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate, 2305cabdff1aSopenharmony_ci (uint32_t)avctx->bit_rate); 2306cabdff1aSopenharmony_ci 2307cabdff1aSopenharmony_ci params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate = avctx->bit_rate; 2308cabdff1aSopenharmony_ci reconfig_bitrate = 1; 2309cabdff1aSopenharmony_ci } 2310cabdff1aSopenharmony_ci 2311cabdff1aSopenharmony_ci if (avctx->rc_max_rate > 0 && ctx->encode_config.rcParams.maxBitRate != avctx->rc_max_rate) { 2312cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, 2313cabdff1aSopenharmony_ci "max bitrate change: %d -> %d\n", 2314cabdff1aSopenharmony_ci params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate, 2315cabdff1aSopenharmony_ci (uint32_t)avctx->rc_max_rate); 2316cabdff1aSopenharmony_ci 2317cabdff1aSopenharmony_ci params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate = avctx->rc_max_rate; 2318cabdff1aSopenharmony_ci reconfig_bitrate = 1; 2319cabdff1aSopenharmony_ci } 2320cabdff1aSopenharmony_ci 2321cabdff1aSopenharmony_ci if (avctx->rc_buffer_size > 0 && ctx->encode_config.rcParams.vbvBufferSize != avctx->rc_buffer_size) { 2322cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, 2323cabdff1aSopenharmony_ci "vbv buffer size change: %d -> %d\n", 2324cabdff1aSopenharmony_ci params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize, 2325cabdff1aSopenharmony_ci avctx->rc_buffer_size); 2326cabdff1aSopenharmony_ci 2327cabdff1aSopenharmony_ci params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize = avctx->rc_buffer_size; 2328cabdff1aSopenharmony_ci reconfig_bitrate = 1; 2329cabdff1aSopenharmony_ci } 2330cabdff1aSopenharmony_ci 2331cabdff1aSopenharmony_ci if (reconfig_bitrate) { 2332cabdff1aSopenharmony_ci params.resetEncoder = 1; 2333cabdff1aSopenharmony_ci params.forceIDR = 1; 2334cabdff1aSopenharmony_ci 2335cabdff1aSopenharmony_ci needs_encode_config = 1; 2336cabdff1aSopenharmony_ci needs_reconfig = 1; 2337cabdff1aSopenharmony_ci } 2338cabdff1aSopenharmony_ci } 2339cabdff1aSopenharmony_ci 2340cabdff1aSopenharmony_ci if (!needs_encode_config) 2341cabdff1aSopenharmony_ci params.reInitEncodeParams.encodeConfig = NULL; 2342cabdff1aSopenharmony_ci 2343cabdff1aSopenharmony_ci if (needs_reconfig) { 2344cabdff1aSopenharmony_ci ret = p_nvenc->nvEncReconfigureEncoder(ctx->nvencoder, ¶ms); 2345cabdff1aSopenharmony_ci if (ret != NV_ENC_SUCCESS) { 2346cabdff1aSopenharmony_ci nvenc_print_error(avctx, ret, "failed to reconfigure nvenc"); 2347cabdff1aSopenharmony_ci } else { 2348cabdff1aSopenharmony_ci if (reconfig_dar) { 2349cabdff1aSopenharmony_ci ctx->init_encode_params.darHeight = dh; 2350cabdff1aSopenharmony_ci ctx->init_encode_params.darWidth = dw; 2351cabdff1aSopenharmony_ci } 2352cabdff1aSopenharmony_ci 2353cabdff1aSopenharmony_ci if (reconfig_bitrate) { 2354cabdff1aSopenharmony_ci ctx->encode_config.rcParams.averageBitRate = params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate; 2355cabdff1aSopenharmony_ci ctx->encode_config.rcParams.maxBitRate = params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate; 2356cabdff1aSopenharmony_ci ctx->encode_config.rcParams.vbvBufferSize = params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize; 2357cabdff1aSopenharmony_ci } 2358cabdff1aSopenharmony_ci 2359cabdff1aSopenharmony_ci } 2360cabdff1aSopenharmony_ci } 2361cabdff1aSopenharmony_ci} 2362cabdff1aSopenharmony_ci 2363cabdff1aSopenharmony_cistatic int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) 2364cabdff1aSopenharmony_ci{ 2365cabdff1aSopenharmony_ci NVENCSTATUS nv_status; 2366cabdff1aSopenharmony_ci NvencSurface *tmp_out_surf, *in_surf; 2367cabdff1aSopenharmony_ci int res, res2; 2368cabdff1aSopenharmony_ci int sei_count = 0; 2369cabdff1aSopenharmony_ci int i; 2370cabdff1aSopenharmony_ci 2371cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2372cabdff1aSopenharmony_ci NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; 2373cabdff1aSopenharmony_ci NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; 2374cabdff1aSopenharmony_ci 2375cabdff1aSopenharmony_ci NV_ENC_PIC_PARAMS pic_params = { 0 }; 2376cabdff1aSopenharmony_ci pic_params.version = NV_ENC_PIC_PARAMS_VER; 2377cabdff1aSopenharmony_ci 2378cabdff1aSopenharmony_ci if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder) 2379cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2380cabdff1aSopenharmony_ci 2381cabdff1aSopenharmony_ci if (frame && frame->buf[0]) { 2382cabdff1aSopenharmony_ci in_surf = get_free_frame(ctx); 2383cabdff1aSopenharmony_ci if (!in_surf) 2384cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 2385cabdff1aSopenharmony_ci 2386cabdff1aSopenharmony_ci res = nvenc_push_context(avctx); 2387cabdff1aSopenharmony_ci if (res < 0) 2388cabdff1aSopenharmony_ci return res; 2389cabdff1aSopenharmony_ci 2390cabdff1aSopenharmony_ci reconfig_encoder(avctx, frame); 2391cabdff1aSopenharmony_ci 2392cabdff1aSopenharmony_ci res = nvenc_upload_frame(avctx, frame, in_surf); 2393cabdff1aSopenharmony_ci 2394cabdff1aSopenharmony_ci res2 = nvenc_pop_context(avctx); 2395cabdff1aSopenharmony_ci if (res2 < 0) 2396cabdff1aSopenharmony_ci return res2; 2397cabdff1aSopenharmony_ci 2398cabdff1aSopenharmony_ci if (res) 2399cabdff1aSopenharmony_ci return res; 2400cabdff1aSopenharmony_ci 2401cabdff1aSopenharmony_ci pic_params.inputBuffer = in_surf->input_surface; 2402cabdff1aSopenharmony_ci pic_params.bufferFmt = in_surf->format; 2403cabdff1aSopenharmony_ci pic_params.inputWidth = in_surf->width; 2404cabdff1aSopenharmony_ci pic_params.inputHeight = in_surf->height; 2405cabdff1aSopenharmony_ci pic_params.inputPitch = in_surf->pitch; 2406cabdff1aSopenharmony_ci pic_params.outputBitstream = in_surf->output_surface; 2407cabdff1aSopenharmony_ci 2408cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { 2409cabdff1aSopenharmony_ci if (frame->top_field_first) 2410cabdff1aSopenharmony_ci pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM; 2411cabdff1aSopenharmony_ci else 2412cabdff1aSopenharmony_ci pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP; 2413cabdff1aSopenharmony_ci } else { 2414cabdff1aSopenharmony_ci pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FRAME; 2415cabdff1aSopenharmony_ci } 2416cabdff1aSopenharmony_ci 2417cabdff1aSopenharmony_ci if (ctx->forced_idr >= 0 && frame->pict_type == AV_PICTURE_TYPE_I) { 2418cabdff1aSopenharmony_ci pic_params.encodePicFlags = 2419cabdff1aSopenharmony_ci ctx->forced_idr ? NV_ENC_PIC_FLAG_FORCEIDR : NV_ENC_PIC_FLAG_FORCEINTRA; 2420cabdff1aSopenharmony_ci } else { 2421cabdff1aSopenharmony_ci pic_params.encodePicFlags = 0; 2422cabdff1aSopenharmony_ci } 2423cabdff1aSopenharmony_ci 2424cabdff1aSopenharmony_ci pic_params.inputTimeStamp = frame->pts; 2425cabdff1aSopenharmony_ci 2426cabdff1aSopenharmony_ci if (ctx->extra_sei) { 2427cabdff1aSopenharmony_ci res = prepare_sei_data_array(avctx, frame); 2428cabdff1aSopenharmony_ci if (res < 0) 2429cabdff1aSopenharmony_ci return res; 2430cabdff1aSopenharmony_ci sei_count = res; 2431cabdff1aSopenharmony_ci } 2432cabdff1aSopenharmony_ci 2433cabdff1aSopenharmony_ci nvenc_codec_specific_pic_params(avctx, &pic_params, ctx->sei_data, sei_count); 2434cabdff1aSopenharmony_ci } else { 2435cabdff1aSopenharmony_ci pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; 2436cabdff1aSopenharmony_ci } 2437cabdff1aSopenharmony_ci 2438cabdff1aSopenharmony_ci res = nvenc_push_context(avctx); 2439cabdff1aSopenharmony_ci if (res < 0) 2440cabdff1aSopenharmony_ci return res; 2441cabdff1aSopenharmony_ci 2442cabdff1aSopenharmony_ci nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params); 2443cabdff1aSopenharmony_ci 2444cabdff1aSopenharmony_ci for (i = 0; i < sei_count; i++) 2445cabdff1aSopenharmony_ci av_freep(&(ctx->sei_data[i].payload)); 2446cabdff1aSopenharmony_ci 2447cabdff1aSopenharmony_ci res = nvenc_pop_context(avctx); 2448cabdff1aSopenharmony_ci if (res < 0) 2449cabdff1aSopenharmony_ci return res; 2450cabdff1aSopenharmony_ci 2451cabdff1aSopenharmony_ci if (nv_status != NV_ENC_SUCCESS && 2452cabdff1aSopenharmony_ci nv_status != NV_ENC_ERR_NEED_MORE_INPUT) 2453cabdff1aSopenharmony_ci return nvenc_print_error(avctx, nv_status, "EncodePicture failed!"); 2454cabdff1aSopenharmony_ci 2455cabdff1aSopenharmony_ci if (frame && frame->buf[0]) { 2456cabdff1aSopenharmony_ci av_fifo_write(ctx->output_surface_queue, &in_surf, 1); 2457cabdff1aSopenharmony_ci timestamp_queue_enqueue(ctx->timestamp_list, frame->pts); 2458cabdff1aSopenharmony_ci } 2459cabdff1aSopenharmony_ci 2460cabdff1aSopenharmony_ci /* all the pending buffers are now ready for output */ 2461cabdff1aSopenharmony_ci if (nv_status == NV_ENC_SUCCESS) { 2462cabdff1aSopenharmony_ci while (av_fifo_read(ctx->output_surface_queue, &tmp_out_surf, 1) >= 0) 2463cabdff1aSopenharmony_ci av_fifo_write(ctx->output_surface_ready_queue, &tmp_out_surf, 1); 2464cabdff1aSopenharmony_ci } 2465cabdff1aSopenharmony_ci 2466cabdff1aSopenharmony_ci return 0; 2467cabdff1aSopenharmony_ci} 2468cabdff1aSopenharmony_ci 2469cabdff1aSopenharmony_ciint ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) 2470cabdff1aSopenharmony_ci{ 2471cabdff1aSopenharmony_ci NvencSurface *tmp_out_surf; 2472cabdff1aSopenharmony_ci int res, res2; 2473cabdff1aSopenharmony_ci 2474cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2475cabdff1aSopenharmony_ci 2476cabdff1aSopenharmony_ci AVFrame *frame = ctx->frame; 2477cabdff1aSopenharmony_ci 2478cabdff1aSopenharmony_ci if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder) 2479cabdff1aSopenharmony_ci return AVERROR(EINVAL); 2480cabdff1aSopenharmony_ci 2481cabdff1aSopenharmony_ci if (!frame->buf[0]) { 2482cabdff1aSopenharmony_ci res = ff_encode_get_frame(avctx, frame); 2483cabdff1aSopenharmony_ci if (res < 0 && res != AVERROR_EOF) 2484cabdff1aSopenharmony_ci return res; 2485cabdff1aSopenharmony_ci } 2486cabdff1aSopenharmony_ci 2487cabdff1aSopenharmony_ci res = nvenc_send_frame(avctx, frame); 2488cabdff1aSopenharmony_ci if (res < 0) { 2489cabdff1aSopenharmony_ci if (res != AVERROR(EAGAIN)) 2490cabdff1aSopenharmony_ci return res; 2491cabdff1aSopenharmony_ci } else 2492cabdff1aSopenharmony_ci av_frame_unref(frame); 2493cabdff1aSopenharmony_ci 2494cabdff1aSopenharmony_ci if (output_ready(avctx, avctx->internal->draining)) { 2495cabdff1aSopenharmony_ci av_fifo_read(ctx->output_surface_ready_queue, &tmp_out_surf, 1); 2496cabdff1aSopenharmony_ci 2497cabdff1aSopenharmony_ci res = nvenc_push_context(avctx); 2498cabdff1aSopenharmony_ci if (res < 0) 2499cabdff1aSopenharmony_ci return res; 2500cabdff1aSopenharmony_ci 2501cabdff1aSopenharmony_ci res = process_output_surface(avctx, pkt, tmp_out_surf); 2502cabdff1aSopenharmony_ci 2503cabdff1aSopenharmony_ci res2 = nvenc_pop_context(avctx); 2504cabdff1aSopenharmony_ci if (res2 < 0) 2505cabdff1aSopenharmony_ci return res2; 2506cabdff1aSopenharmony_ci 2507cabdff1aSopenharmony_ci if (res) 2508cabdff1aSopenharmony_ci return res; 2509cabdff1aSopenharmony_ci 2510cabdff1aSopenharmony_ci av_fifo_write(ctx->unused_surface_queue, &tmp_out_surf, 1); 2511cabdff1aSopenharmony_ci } else if (avctx->internal->draining) { 2512cabdff1aSopenharmony_ci return AVERROR_EOF; 2513cabdff1aSopenharmony_ci } else { 2514cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 2515cabdff1aSopenharmony_ci } 2516cabdff1aSopenharmony_ci 2517cabdff1aSopenharmony_ci return 0; 2518cabdff1aSopenharmony_ci} 2519cabdff1aSopenharmony_ci 2520cabdff1aSopenharmony_ciav_cold void ff_nvenc_encode_flush(AVCodecContext *avctx) 2521cabdff1aSopenharmony_ci{ 2522cabdff1aSopenharmony_ci NvencContext *ctx = avctx->priv_data; 2523cabdff1aSopenharmony_ci 2524cabdff1aSopenharmony_ci nvenc_send_frame(avctx, NULL); 2525cabdff1aSopenharmony_ci av_fifo_reset2(ctx->timestamp_list); 2526cabdff1aSopenharmony_ci} 2527