blob: 9875f02dc882515b8dac0594d11b1d939d0163a7 [file] [log] [blame]
Timo Rothenpieler2a428db2014-11-29 23:04:371/*
Timo Rothenpieler5c288a42022-11-05 20:17:372 * H.264/HEVC/AV1 hardware encoding using nvidia nvenc
Timo Rothenpielercac2df22016-08-28 17:51:223 * Copyright (c) 2016 Timo Rothenpieler <[email protected]>
Timo Rothenpieler2a428db2014-11-29 23:04:374 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
Andrey Turkin7aa16d52016-05-25 13:04:2822#include "config.h"
Martin Storsjöa78f1362022-02-23 12:56:4923#include "config_components.h"
Andrey Turkin7aa16d52016-05-25 13:04:2824
Timo Rothenpielera66835b2016-10-10 10:55:5925#include "nvenc.h"
Limin Wangfdead2a2020-06-28 02:34:1226#include "hevc_sei.h"
Timo Rothenpieler6362b8c2022-11-05 20:18:3627#if CONFIG_AV1_NVENC_ENCODER
28#include "av1.h"
29#endif
Timo Rothenpieler19e75fd2016-08-28 15:54:2930
Timo Rothenpielera66835b2016-10-10 10:55:5931#include "libavutil/hwcontext_cuda.h"
Andrey Turkin0d021cc2016-05-29 12:23:2632#include "libavutil/hwcontext.h"
Philip Langdale19d3d0c2018-11-11 06:47:2833#include "libavutil/cuda_check.h"
Timo Rothenpieler2a428db2014-11-29 23:04:3734#include "libavutil/imgutils.h"
Timo Rothenpieler2a428db2014-11-29 23:04:3735#include "libavutil/mem.h"
Philip Langdale27038692016-11-25 19:11:4536#include "libavutil/pixdesc.h"
Timo Rothenpielere7fbdda2022-11-10 12:05:5937#include "libavutil/mathematics.h"
James Almer0de01da2020-08-09 17:01:1638#include "atsc_a53.h"
James Almer827d6fe2020-06-09 21:31:3239#include "encode.h"
Timo Rothenpieler2a428db2014-11-29 23:04:3740#include "internal.h"
James Almer6e190392020-06-02 21:38:3341#include "packet_internal.h"
Andrey Turkina8cf25d2016-05-20 22:08:0642
Philip Langdale19d3d0c2018-11-11 06:47:2843#define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x)
44
Andrey Turkin0d021cc2016-05-29 12:23:2645#define NVENC_CAP 0x30
Timo Rothenpielerd2b46c12023-06-01 21:46:4646
47#ifndef NVENC_NO_DEPRECATED_RC
Timo Rothenpielercfbebe92017-05-09 11:57:3948#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR || \
49 rc == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || \
50 rc == NV_ENC_PARAMS_RC_CBR_HQ)
Timo Rothenpielerd2b46c12023-06-01 21:46:4651#else
52#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR)
53#endif
Andrey Turkinf84dfbc2016-05-25 16:39:5454
Andrey Turkin7aa16d52016-05-25 13:04:2855const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
56 AV_PIX_FMT_YUV420P,
57 AV_PIX_FMT_NV12,
Oliver Collyerd1bf8a32016-08-25 15:18:0358 AV_PIX_FMT_P010,
Andrey Turkin7aa16d52016-05-25 13:04:2859 AV_PIX_FMT_YUV444P,
Philip Langdale6a89cdc2018-02-25 17:08:0660 AV_PIX_FMT_P016, // Truncated to 10bits
61 AV_PIX_FMT_YUV444P16, // Truncated to 10bits
Sven C. Dack4aeb7a82016-09-07 13:35:1462 AV_PIX_FMT_0RGB32,
Timo Rothenpieler85bc6b52022-07-04 23:58:1063 AV_PIX_FMT_RGB32,
Sven C. Dack4aeb7a82016-09-07 13:35:1464 AV_PIX_FMT_0BGR32,
Timo Rothenpieler85bc6b52022-07-04 23:58:1065 AV_PIX_FMT_BGR32,
66 AV_PIX_FMT_X2RGB10,
67 AV_PIX_FMT_X2BGR10,
Timo Rothenpieler7555d6f2021-03-30 20:08:4968 AV_PIX_FMT_GBRP,
69 AV_PIX_FMT_GBRP16, // Truncated to 10bits
Andrey Turkin7aa16d52016-05-25 13:04:2870 AV_PIX_FMT_CUDA,
Hendrik Leppkesbff6d982017-11-11 15:51:5871#if CONFIG_D3D11VA
72 AV_PIX_FMT_D3D11,
73#endif
Andrey Turkin7aa16d52016-05-25 13:04:2874 AV_PIX_FMT_NONE
75};
Timo Rothenpieler2a428db2014-11-29 23:04:3776
Mark Thompsoncd322792020-11-08 18:51:1577const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = {
Mark Thompson1dff97b2020-04-13 15:33:1878 HW_CONFIG_ENCODER_FRAMES(CUDA, CUDA),
79 HW_CONFIG_ENCODER_DEVICE(NONE, CUDA),
80#if CONFIG_D3D11VA
81 HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA),
82 HW_CONFIG_ENCODER_DEVICE(NONE, D3D11VA),
83#endif
84 NULL,
85};
86
Timo Rothenpieler7555d6f2021-03-30 20:08:4987#define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \
88 pix_fmt == AV_PIX_FMT_P016 || \
89 pix_fmt == AV_PIX_FMT_YUV444P16 || \
Timo Rothenpielerc7a60122022-11-14 22:10:2090 pix_fmt == AV_PIX_FMT_X2RGB10 || \
91 pix_fmt == AV_PIX_FMT_X2BGR10 || \
Timo Rothenpieler7555d6f2021-03-30 20:08:4992 pix_fmt == AV_PIX_FMT_GBRP16)
Oliver Collyerd1bf8a32016-08-25 15:18:0393
Timo Rothenpieler7555d6f2021-03-30 20:08:4994#define IS_YUV444(pix_fmt) (pix_fmt == AV_PIX_FMT_YUV444P || \
95 pix_fmt == AV_PIX_FMT_YUV444P16 || \
96 pix_fmt == AV_PIX_FMT_GBRP || \
97 pix_fmt == AV_PIX_FMT_GBRP16)
98
99#define IS_GBRP(pix_fmt) (pix_fmt == AV_PIX_FMT_GBRP || \
100 pix_fmt == AV_PIX_FMT_GBRP16)
Oliver Collyerd1bf8a32016-08-25 15:18:03101
Andrey Turkine1691c42016-05-20 15:37:00102static const struct {
103 NVENCSTATUS nverr;
104 int averr;
105 const char *desc;
106} nvenc_errors[] = {
107 { NV_ENC_SUCCESS, 0, "success" },
108 { NV_ENC_ERR_NO_ENCODE_DEVICE, AVERROR(ENOENT), "no encode device" },
109 { NV_ENC_ERR_UNSUPPORTED_DEVICE, AVERROR(ENOSYS), "unsupported device" },
110 { NV_ENC_ERR_INVALID_ENCODERDEVICE, AVERROR(EINVAL), "invalid encoder device" },
111 { NV_ENC_ERR_INVALID_DEVICE, AVERROR(EINVAL), "invalid device" },
112 { NV_ENC_ERR_DEVICE_NOT_EXIST, AVERROR(EIO), "device does not exist" },
113 { NV_ENC_ERR_INVALID_PTR, AVERROR(EFAULT), "invalid ptr" },
114 { NV_ENC_ERR_INVALID_EVENT, AVERROR(EINVAL), "invalid event" },
115 { NV_ENC_ERR_INVALID_PARAM, AVERROR(EINVAL), "invalid param" },
116 { NV_ENC_ERR_INVALID_CALL, AVERROR(EINVAL), "invalid call" },
117 { NV_ENC_ERR_OUT_OF_MEMORY, AVERROR(ENOMEM), "out of memory" },
118 { NV_ENC_ERR_ENCODER_NOT_INITIALIZED, AVERROR(EINVAL), "encoder not initialized" },
119 { NV_ENC_ERR_UNSUPPORTED_PARAM, AVERROR(ENOSYS), "unsupported param" },
120 { NV_ENC_ERR_LOCK_BUSY, AVERROR(EAGAIN), "lock busy" },
James Almerdc482482016-09-24 18:31:00121 { NV_ENC_ERR_NOT_ENOUGH_BUFFER, AVERROR_BUFFER_TOO_SMALL, "not enough buffer"},
Andrey Turkine1691c42016-05-20 15:37:00122 { NV_ENC_ERR_INVALID_VERSION, AVERROR(EINVAL), "invalid version" },
123 { NV_ENC_ERR_MAP_FAILED, AVERROR(EIO), "map failed" },
124 { NV_ENC_ERR_NEED_MORE_INPUT, AVERROR(EAGAIN), "need more input" },
125 { NV_ENC_ERR_ENCODER_BUSY, AVERROR(EAGAIN), "encoder busy" },
126 { NV_ENC_ERR_EVENT_NOT_REGISTERD, AVERROR(EBADF), "event not registered" },
127 { NV_ENC_ERR_GENERIC, AVERROR_UNKNOWN, "generic error" },
128 { NV_ENC_ERR_INCOMPATIBLE_CLIENT_KEY, AVERROR(EINVAL), "incompatible client key" },
129 { NV_ENC_ERR_UNIMPLEMENTED, AVERROR(ENOSYS), "unimplemented" },
130 { NV_ENC_ERR_RESOURCE_REGISTER_FAILED, AVERROR(EIO), "resource register failed" },
131 { NV_ENC_ERR_RESOURCE_NOT_REGISTERED, AVERROR(EBADF), "resource not registered" },
132 { NV_ENC_ERR_RESOURCE_NOT_MAPPED, AVERROR(EBADF), "resource not mapped" },
133};
134
135static int nvenc_map_error(NVENCSTATUS err, const char **desc)
136{
137 int i;
138 for (i = 0; i < FF_ARRAY_ELEMS(nvenc_errors); i++) {
139 if (nvenc_errors[i].nverr == err) {
140 if (desc)
141 *desc = nvenc_errors[i].desc;
142 return nvenc_errors[i].averr;
143 }
144 }
145 if (desc)
146 *desc = "unknown error";
147 return AVERROR_UNKNOWN;
148}
149
Timo Rothenpielerab0ef1a2019-09-27 17:09:11150static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err,
Clément Bœschb7cc4eb2017-03-20 22:04:28151 const char *error_string)
Andrey Turkine1691c42016-05-20 15:37:00152{
153 const char *desc;
Timo Rothenpielerab0ef1a2019-09-27 17:09:11154 const char *details = "(no details)";
155 int ret = nvenc_map_error(err, &desc);
156
157#ifdef NVENC_HAVE_GETLASTERRORSTRING
158 NvencContext *ctx = avctx->priv_data;
159 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
160
161 if (p_nvenc && ctx->nvencoder)
162 details = p_nvenc->nvEncGetLastErrorString(ctx->nvencoder);
163#endif
164
165 av_log(avctx, AV_LOG_ERROR, "%s: %s (%d): %s\n", error_string, desc, err, details);
166
Andrey Turkine1691c42016-05-20 15:37:00167 return ret;
168}
169
Timo Rothenpieler988f2e92021-04-18 09:17:54170typedef struct GUIDTuple {
171 const GUID guid;
172 int flags;
173} GUIDTuple;
174
175#define PRESET_ALIAS(alias, name, ...) \
176 [PRESET_ ## alias] = { NV_ENC_PRESET_ ## name ## _GUID, __VA_ARGS__ }
177
178#define PRESET(name, ...) PRESET_ALIAS(name, name, __VA_ARGS__)
179
180static void nvenc_map_preset(NvencContext *ctx)
181{
182 GUIDTuple presets[] = {
183#ifdef NVENC_HAVE_NEW_PRESETS
184 PRESET(P1),
185 PRESET(P2),
186 PRESET(P3),
187 PRESET(P4),
188 PRESET(P5),
189 PRESET(P6),
190 PRESET(P7),
191 PRESET_ALIAS(SLOW, P7, NVENC_TWO_PASSES),
192 PRESET_ALIAS(MEDIUM, P4, NVENC_ONE_PASS),
193 PRESET_ALIAS(FAST, P1, NVENC_ONE_PASS),
194 // Compat aliases
195 PRESET_ALIAS(DEFAULT, P4, NVENC_DEPRECATED_PRESET),
196 PRESET_ALIAS(HP, P1, NVENC_DEPRECATED_PRESET),
197 PRESET_ALIAS(HQ, P7, NVENC_DEPRECATED_PRESET),
198 PRESET_ALIAS(BD, P5, NVENC_DEPRECATED_PRESET),
199 PRESET_ALIAS(LOW_LATENCY_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
200 PRESET_ALIAS(LOW_LATENCY_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
201 PRESET_ALIAS(LOW_LATENCY_HQ, P7, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
202 PRESET_ALIAS(LOSSLESS_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
203 PRESET_ALIAS(LOSSLESS_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
204#else
205 PRESET(DEFAULT),
206 PRESET(HP),
207 PRESET(HQ),
208 PRESET(BD),
209 PRESET_ALIAS(SLOW, HQ, NVENC_TWO_PASSES),
210 PRESET_ALIAS(MEDIUM, HQ, NVENC_ONE_PASS),
211 PRESET_ALIAS(FAST, HP, NVENC_ONE_PASS),
212 PRESET(LOW_LATENCY_DEFAULT, NVENC_LOWLATENCY),
213 PRESET(LOW_LATENCY_HP, NVENC_LOWLATENCY),
214 PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY),
215 PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS),
216 PRESET(LOSSLESS_HP, NVENC_LOSSLESS),
217#endif
218 };
219
220 GUIDTuple *t = &presets[ctx->preset];
221
222 ctx->init_encode_params.presetGUID = t->guid;
223 ctx->flags = t->flags;
224
225#ifdef NVENC_HAVE_NEW_PRESETS
226 if (ctx->tuning_info == NV_ENC_TUNING_INFO_LOSSLESS)
227 ctx->flags |= NVENC_LOSSLESS;
228#endif
229}
230
231#undef PRESET
232#undef PRESET_ALIAS
233
Timo Rothenpielercb3358b2017-06-01 09:55:25234static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level)
235{
Timo Rothenpieler5c288a42022-11-05 20:17:37236#if NVENCAPI_CHECK_VERSION(12, 1)
Timo Rothenpieler648f5c92019-09-23 13:47:27237 const char *minver = "(unknown)";
Timo Rothenpieler5c288a42022-11-05 20:17:37238#elif NVENCAPI_CHECK_VERSION(12, 0)
239# if defined(_WIN32) || defined(__CYGWIN__)
240 const char *minver = "522.25";
241# else
242 const char *minver = "520.56.06";
243# endif
Timo Rothenpielerac040852021-08-08 00:00:38244#elif NVENCAPI_CHECK_VERSION(11, 1)
245# if defined(_WIN32) || defined(__CYGWIN__)
246 const char *minver = "471.41";
247# else
248 const char *minver = "470.57.02";
249# endif
Timo Rothenpieler62073cf2020-10-17 21:10:42250#elif NVENCAPI_CHECK_VERSION(11, 0)
251# if defined(_WIN32) || defined(__CYGWIN__)
252 const char *minver = "456.71";
253# else
254 const char *minver = "455.28";
255# endif
Roman Arzumanyan9115d772020-03-19 08:35:29256#elif NVENCAPI_CHECK_VERSION(10, 0)
257# if defined(_WIN32) || defined(__CYGWIN__)
258 const char *minver = "450.51";
259# else
260 const char *minver = "445.87";
261# endif
Timo Rothenpieler648f5c92019-09-23 13:47:27262#elif NVENCAPI_CHECK_VERSION(9, 1)
263# if defined(_WIN32) || defined(__CYGWIN__)
Timo Rothenpieler89cbbe92019-09-24 10:00:00264 const char *minver = "436.15";
Timo Rothenpieler648f5c92019-09-23 13:47:27265# else
266 const char *minver = "435.21";
267# endif
268#elif NVENCAPI_CHECK_VERSION(9, 0)
Timo Rothenpieler1144d5c2019-03-09 23:25:31269# if defined(_WIN32) || defined(__CYGWIN__)
270 const char *minver = "418.81";
271# else
272 const char *minver = "418.30";
273# endif
274#elif NVENCAPI_CHECK_VERSION(8, 2)
275# if defined(_WIN32) || defined(__CYGWIN__)
276 const char *minver = "397.93";
277# else
278 const char *minver = "396.24";
279#endif
280#elif NVENCAPI_CHECK_VERSION(8, 1)
Timo Rothenpieler2108a672018-04-11 12:28:36281# if defined(_WIN32) || defined(__CYGWIN__)
282 const char *minver = "390.77";
283# else
284 const char *minver = "390.25";
285# endif
Timo Rothenpielercb3358b2017-06-01 09:55:25286#else
Timo Rothenpieler2108a672018-04-11 12:28:36287# if defined(_WIN32) || defined(__CYGWIN__)
288 const char *minver = "378.66";
289# else
Timo Rothenpielercb3358b2017-06-01 09:55:25290 const char *minver = "378.13";
Timo Rothenpieler2108a672018-04-11 12:28:36291# endif
Timo Rothenpielercb3358b2017-06-01 09:55:25292#endif
293 av_log(avctx, level, "The minimum required Nvidia driver for nvenc is %s or newer\n", minver);
294}
295
Andrey Turkin0d021cc2016-05-29 12:23:26296static av_cold int nvenc_load_libraries(AVCodecContext *avctx)
Timo Rothenpieler2a428db2014-11-29 23:04:37297{
Clément Bœschb7cc4eb2017-03-20 22:04:28298 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler2a428db2014-11-29 23:04:37299 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Andrey Turkin0d021cc2016-05-29 12:23:26300 NVENCSTATUS err;
Timo Rothenpielerdf615ef2016-08-28 17:46:44301 uint32_t nvenc_max_ver;
Timo Rothenpielera66835b2016-10-10 10:55:59302 int ret;
Timo Rothenpieler2a428db2014-11-29 23:04:37303
Mark Thompson1dc483a2017-11-18 17:16:14304 ret = cuda_load_functions(&dl_fn->cuda_dl, avctx);
Timo Rothenpielera66835b2016-10-10 10:55:59305 if (ret < 0)
306 return ret;
Timo Rothenpieler2a428db2014-11-29 23:04:37307
Mark Thompson1dc483a2017-11-18 17:16:14308 ret = nvenc_load_functions(&dl_fn->nvenc_dl, avctx);
Timo Rothenpielercb3358b2017-06-01 09:55:25309 if (ret < 0) {
310 nvenc_print_driver_requirement(avctx, AV_LOG_ERROR);
Timo Rothenpielera66835b2016-10-10 10:55:59311 return ret;
Timo Rothenpielercb3358b2017-06-01 09:55:25312 }
Timo Rothenpieler2a428db2014-11-29 23:04:37313
Timo Rothenpielera66835b2016-10-10 10:55:59314 err = dl_fn->nvenc_dl->NvEncodeAPIGetMaxSupportedVersion(&nvenc_max_ver);
Timo Rothenpielerdf615ef2016-08-28 17:46:44315 if (err != NV_ENC_SUCCESS)
316 return nvenc_print_error(avctx, err, "Failed to query nvenc max version");
317
318 av_log(avctx, AV_LOG_VERBOSE, "Loaded Nvenc version %d.%d\n", nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
319
320 if ((NVENCAPI_MAJOR_VERSION << 4 | NVENCAPI_MINOR_VERSION) > nvenc_max_ver) {
321 av_log(avctx, AV_LOG_ERROR, "Driver does not support the required nvenc API version. "
322 "Required: %d.%d Found: %d.%d\n",
323 NVENCAPI_MAJOR_VERSION, NVENCAPI_MINOR_VERSION,
324 nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
Timo Rothenpielercb3358b2017-06-01 09:55:25325 nvenc_print_driver_requirement(avctx, AV_LOG_ERROR);
Timo Rothenpielerdf615ef2016-08-28 17:46:44326 return AVERROR(ENOSYS);
327 }
328
Timo Rothenpieler2a428db2014-11-29 23:04:37329 dl_fn->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER;
330
Timo Rothenpielera66835b2016-10-10 10:55:59331 err = dl_fn->nvenc_dl->NvEncodeAPICreateInstance(&dl_fn->nvenc_funcs);
Andrey Turkin0d021cc2016-05-29 12:23:26332 if (err != NV_ENC_SUCCESS)
333 return nvenc_print_error(avctx, err, "Failed to create nvenc instance");
Timo Rothenpieler2a428db2014-11-29 23:04:37334
335 av_log(avctx, AV_LOG_VERBOSE, "Nvenc initialized successfully\n");
336
Andrey Turkin0d021cc2016-05-29 12:23:26337 return 0;
338}
Timo Rothenpieler2a428db2014-11-29 23:04:37339
Hendrik Leppkes6fcbf392017-11-11 15:13:24340static int nvenc_push_context(AVCodecContext *avctx)
341{
342 NvencContext *ctx = avctx->priv_data;
343 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Hendrik Leppkes6fcbf392017-11-11 15:13:24344
Hendrik Leppkesbff6d982017-11-11 15:51:58345 if (ctx->d3d11_device)
346 return 0;
347
Philip Langdale19d3d0c2018-11-11 06:47:28348 return CHECK_CU(dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context));
Hendrik Leppkes6fcbf392017-11-11 15:13:24349}
350
351static int nvenc_pop_context(AVCodecContext *avctx)
352{
353 NvencContext *ctx = avctx->priv_data;
354 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Hendrik Leppkes6fcbf392017-11-11 15:13:24355 CUcontext dummy;
356
Hendrik Leppkesbff6d982017-11-11 15:51:58357 if (ctx->d3d11_device)
358 return 0;
359
Philip Langdale19d3d0c2018-11-11 06:47:28360 return CHECK_CU(dl_fn->cuda_dl->cuCtxPopCurrent(&dummy));
Hendrik Leppkes6fcbf392017-11-11 15:13:24361}
362
Andrey Turkin0d021cc2016-05-29 12:23:26363static av_cold int nvenc_open_session(AVCodecContext *avctx)
364{
365 NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = { 0 };
366 NvencContext *ctx = avctx->priv_data;
367 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
368 NVENCSTATUS ret;
Timo Rothenpieler2a428db2014-11-29 23:04:37369
Andrey Turkin0d021cc2016-05-29 12:23:26370 params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
371 params.apiVersion = NVENCAPI_VERSION;
Hendrik Leppkesbff6d982017-11-11 15:51:58372 if (ctx->d3d11_device) {
373 params.device = ctx->d3d11_device;
374 params.deviceType = NV_ENC_DEVICE_TYPE_DIRECTX;
375 } else {
376 params.device = ctx->cu_context;
377 params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
378 }
Andrey Turkin0d021cc2016-05-29 12:23:26379
380 ret = p_nvenc->nvEncOpenEncodeSessionEx(&params, &ctx->nvencoder);
381 if (ret != NV_ENC_SUCCESS) {
382 ctx->nvencoder = NULL;
383 return nvenc_print_error(avctx, ret, "OpenEncodeSessionEx failed");
384 }
Timo Rothenpieler2a428db2014-11-29 23:04:37385
386 return 0;
387}
388
Andrey Turkin0d021cc2016-05-29 12:23:26389static int nvenc_check_codec_support(AVCodecContext *avctx)
390{
Clément Bœschb7cc4eb2017-03-20 22:04:28391 NvencContext *ctx = avctx->priv_data;
Andrey Turkin0d021cc2016-05-29 12:23:26392 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
393 int i, ret, count = 0;
394 GUID *guids = NULL;
395
396 ret = p_nvenc->nvEncGetEncodeGUIDCount(ctx->nvencoder, &count);
397
398 if (ret != NV_ENC_SUCCESS || !count)
399 return AVERROR(ENOSYS);
400
401 guids = av_malloc(count * sizeof(GUID));
402 if (!guids)
403 return AVERROR(ENOMEM);
404
405 ret = p_nvenc->nvEncGetEncodeGUIDs(ctx->nvencoder, guids, count, &count);
406 if (ret != NV_ENC_SUCCESS) {
407 ret = AVERROR(ENOSYS);
408 goto fail;
409 }
410
411 ret = AVERROR(ENOSYS);
412 for (i = 0; i < count; i++) {
413 if (!memcmp(&guids[i], &ctx->init_encode_params.encodeGUID, sizeof(*guids))) {
414 ret = 0;
415 break;
416 }
417 }
418
419fail:
420 av_free(guids);
421
422 return ret;
423}
424
425static int nvenc_check_cap(AVCodecContext *avctx, NV_ENC_CAPS cap)
426{
427 NvencContext *ctx = avctx->priv_data;
428 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
429 NV_ENC_CAPS_PARAM params = { 0 };
430 int ret, val = 0;
431
432 params.version = NV_ENC_CAPS_PARAM_VER;
433 params.capsToQuery = cap;
434
435 ret = p_nvenc->nvEncGetEncodeCaps(ctx->nvencoder, ctx->init_encode_params.encodeGUID, &params, &val);
436
437 if (ret == NV_ENC_SUCCESS)
438 return val;
439 return 0;
440}
441
442static int nvenc_check_capabilities(AVCodecContext *avctx)
443{
444 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler7a8560c2023-03-10 12:09:10445 int tmp, ret;
Andrey Turkin0d021cc2016-05-29 12:23:26446
447 ret = nvenc_check_codec_support(avctx);
448 if (ret < 0) {
hydra3333ba6b20d2019-10-27 02:30:54449 av_log(avctx, AV_LOG_WARNING, "Codec not supported\n");
Andrey Turkin0d021cc2016-05-29 12:23:26450 return ret;
451 }
452
453 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE);
Oliver Collyerd1bf8a32016-08-25 15:18:03454 if (IS_YUV444(ctx->data_pix_fmt) && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54455 av_log(avctx, AV_LOG_WARNING, "YUV444P not supported\n");
Andrey Turkin0d021cc2016-05-29 12:23:26456 return AVERROR(ENOSYS);
457 }
458
459 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
Timo Rothenpieler988f2e92021-04-18 09:17:54460 if (ctx->flags & NVENC_LOSSLESS && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54461 av_log(avctx, AV_LOG_WARNING, "Lossless encoding not supported\n");
Andrey Turkin0d021cc2016-05-29 12:23:26462 return AVERROR(ENOSYS);
463 }
464
465 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_WIDTH_MAX);
466 if (ret < avctx->width) {
hydra3333ba6b20d2019-10-27 02:30:54467 av_log(avctx, AV_LOG_WARNING, "Width %d exceeds %d\n",
Andrey Turkin0d021cc2016-05-29 12:23:26468 avctx->width, ret);
469 return AVERROR(ENOSYS);
470 }
471
472 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_HEIGHT_MAX);
473 if (ret < avctx->height) {
hydra3333ba6b20d2019-10-27 02:30:54474 av_log(avctx, AV_LOG_WARNING, "Height %d exceeds %d\n",
Andrey Turkin0d021cc2016-05-29 12:23:26475 avctx->height, ret);
476 return AVERROR(ENOSYS);
477 }
478
479 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_NUM_MAX_BFRAMES);
480 if (ret < avctx->max_b_frames) {
hydra3333ba6b20d2019-10-27 02:30:54481 av_log(avctx, AV_LOG_WARNING, "Max B-frames %d exceed %d\n",
Andrey Turkin0d021cc2016-05-29 12:23:26482 avctx->max_b_frames, ret);
483
484 return AVERROR(ENOSYS);
485 }
486
Timo Rothenpieler808356c2016-06-06 19:19:29487 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_FIELD_ENCODING);
488 if (ret < 1 && avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
hydra3333ba6b20d2019-10-27 02:30:54489 av_log(avctx, AV_LOG_WARNING,
Timo Rothenpieler808356c2016-06-06 19:19:29490 "Interlaced encoding is not supported. Supported level: %d\n",
491 ret);
492 return AVERROR(ENOSYS);
493 }
494
Oliver Collyerd1bf8a32016-08-25 15:18:03495 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_10BIT_ENCODE);
496 if (IS_10BIT(ctx->data_pix_fmt) && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54497 av_log(avctx, AV_LOG_WARNING, "10 bit encode not supported\n");
Oliver Collyerd1bf8a32016-08-25 15:18:03498 return AVERROR(ENOSYS);
499 }
500
Oliver Collyera81b3982016-08-25 15:20:03501 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOOKAHEAD);
502 if (ctx->rc_lookahead > 0 && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54503 av_log(avctx, AV_LOG_WARNING, "RC lookahead not supported\n");
Oliver Collyera81b3982016-08-25 15:20:03504 return AVERROR(ENOSYS);
505 }
506
Sven C. Dackda4d0fa2016-10-14 15:02:54507 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_AQ);
508 if (ctx->temporal_aq > 0 && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54509 av_log(avctx, AV_LOG_WARNING, "Temporal AQ not supported\n");
Sven C. Dackda4d0fa2016-10-14 15:02:54510 return AVERROR(ENOSYS);
511 }
512
Sumit Agarwal01775732017-05-09 14:24:54513 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_WEIGHTED_PREDICTION);
514 if (ctx->weighted_pred > 0 && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54515 av_log (avctx, AV_LOG_WARNING, "Weighted Prediction not supported\n");
Sumit Agarwal01775732017-05-09 14:24:54516 return AVERROR(ENOSYS);
517 }
518
Timo Rothenpielera0b69e22017-08-30 19:06:25519 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_CABAC);
520 if (ctx->coder == NV_ENC_H264_ENTROPY_CODING_MODE_CABAC && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54521 av_log(avctx, AV_LOG_WARNING, "CABAC entropy coding not supported\n");
Timo Rothenpielera0b69e22017-08-30 19:06:25522 return AVERROR(ENOSYS);
523 }
524
Timo Rothenpieler86e9dba2018-04-11 12:22:20525#ifdef NVENC_HAVE_BFRAME_REF_MODE
Timo Rothenpieler7a8560c2023-03-10 12:09:10526 tmp = (ctx->b_ref_mode >= 0) ? ctx->b_ref_mode : NV_ENC_BFRAME_REF_MODE_DISABLED;
Timo Rothenpieler86e9dba2018-04-11 12:22:20527 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE);
Timo Rothenpieler7a8560c2023-03-10 12:09:10528 if (tmp == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1 && ret != 3) {
hydra3333ba6b20d2019-10-27 02:30:54529 av_log(avctx, AV_LOG_WARNING, "Each B frame as reference is not supported\n");
Timo Rothenpieler86e9dba2018-04-11 12:22:20530 return AVERROR(ENOSYS);
Timo Rothenpieler7a8560c2023-03-10 12:09:10531 } else if (tmp != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) {
hydra3333ba6b20d2019-10-27 02:30:54532 av_log(avctx, AV_LOG_WARNING, "B frames as references are not supported\n");
Timo Rothenpieler86e9dba2018-04-11 12:22:20533 return AVERROR(ENOSYS);
534 }
535#else
Timo Rothenpieler7a8560c2023-03-10 12:09:10536 tmp = (ctx->b_ref_mode >= 0) ? ctx->b_ref_mode : 0;
537 if (tmp > 0) {
hydra3333ba6b20d2019-10-27 02:30:54538 av_log(avctx, AV_LOG_WARNING, "B frames as references need SDK 8.1 at build time\n");
Timo Rothenpieler86e9dba2018-04-11 12:22:20539 return AVERROR(ENOSYS);
540 }
541#endif
542
Roman Arzumanyan567b5e32019-09-27 15:56:11543#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES
544 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_MULTIPLE_REF_FRAMES);
545 if(avctx->refs != NV_ENC_NUM_REF_FRAMES_AUTOSELECT && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54546 av_log(avctx, AV_LOG_WARNING, "Multiple reference frames are not supported by the device\n");
Roman Arzumanyan567b5e32019-09-27 15:56:11547 return AVERROR(ENOSYS);
548 }
549#else
550 if(avctx->refs != 0) {
hydra3333ba6b20d2019-10-27 02:30:54551 av_log(avctx, AV_LOG_WARNING, "Multiple reference frames need SDK 9.1 at build time\n");
Roman Arzumanyan567b5e32019-09-27 15:56:11552 return AVERROR(ENOSYS);
553 }
554#endif
555
Limin Wang37565252021-09-02 10:38:57556#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH
557 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SINGLE_SLICE_INTRA_REFRESH);
558 if(ctx->single_slice_intra_refresh && ret <= 0) {
559 av_log(avctx, AV_LOG_WARNING, "Single slice intra refresh not supported by the device\n");
560 return AVERROR(ENOSYS);
561 }
562#else
563 if(ctx->single_slice_intra_refresh) {
564 av_log(avctx, AV_LOG_WARNING, "Single slice intra refresh needs SDK 11.1 at build time\n");
565 return AVERROR(ENOSYS);
566 }
567#endif
568
Limin Wange6bd5172021-09-06 02:01:58569 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_INTRA_REFRESH);
Limin Wang37565252021-09-02 10:38:57570 if((ctx->intra_refresh || ctx->single_slice_intra_refresh) && ret <= 0) {
Limin Wange6bd5172021-09-06 02:01:58571 av_log(avctx, AV_LOG_WARNING, "Intra refresh not supported by the device\n");
572 return AVERROR(ENOSYS);
573 }
574
Limin Wang75001ae2021-09-02 10:38:58575#ifndef NVENC_HAVE_HEVC_CONSTRAINED_ENCODING
576 if (ctx->constrained_encoding && avctx->codec->id == AV_CODEC_ID_HEVC) {
577 av_log(avctx, AV_LOG_WARNING, "HEVC constrained encoding needs SDK 10.0 at build time\n");
578 return AVERROR(ENOSYS);
579 }
580#endif
581
582 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_CONSTRAINED_ENCODING);
583 if(ctx->constrained_encoding && ret <= 0) {
584 av_log(avctx, AV_LOG_WARNING, "Constrained encoding not supported by the device\n");
585 return AVERROR(ENOSYS);
586 }
587
pkviet15537512018-05-03 00:15:52588 ctx->support_dyn_bitrate = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE);
589
Andrey Turkin0d021cc2016-05-29 12:23:26590 return 0;
591}
592
593static av_cold int nvenc_check_device(AVCodecContext *avctx, int idx)
594{
595 NvencContext *ctx = avctx->priv_data;
596 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
597 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
598 char name[128] = { 0};
599 int major, minor, ret;
Andrey Turkin0d021cc2016-05-29 12:23:26600 CUdevice cu_device;
Andrey Turkin0d021cc2016-05-29 12:23:26601 int loglevel = AV_LOG_VERBOSE;
602
603 if (ctx->device == LIST_DEVICES)
604 loglevel = AV_LOG_INFO;
605
Philip Langdale19d3d0c2018-11-11 06:47:28606 ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceGet(&cu_device, idx));
607 if (ret < 0)
608 return ret;
Andrey Turkin0d021cc2016-05-29 12:23:26609
Philip Langdale19d3d0c2018-11-11 06:47:28610 ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceGetName(name, sizeof(name), cu_device));
611 if (ret < 0)
612 return ret;
Andrey Turkin0d021cc2016-05-29 12:23:26613
Philip Langdale19d3d0c2018-11-11 06:47:28614 ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceComputeCapability(&major, &minor, cu_device));
615 if (ret < 0)
616 return ret;
Andrey Turkin0d021cc2016-05-29 12:23:26617
618 av_log(avctx, loglevel, "[ GPU #%d - < %s > has Compute SM %d.%d ]\n", idx, name, major, minor);
619 if (((major << 4) | minor) < NVENC_CAP) {
620 av_log(avctx, loglevel, "does not support NVENC\n");
621 goto fail;
622 }
623
Timo Rothenpieler5403d902017-01-18 22:01:28624 if (ctx->device != idx && ctx->device != ANY_DEVICE)
625 return -1;
626
Philip Langdale19d3d0c2018-11-11 06:47:28627 ret = CHECK_CU(dl_fn->cuda_dl->cuCtxCreate(&ctx->cu_context_internal, 0, cu_device));
628 if (ret < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26629 goto fail;
Andrey Turkin0d021cc2016-05-29 12:23:26630
631 ctx->cu_context = ctx->cu_context_internal;
Timo Rothenpieler51a23342019-09-27 16:30:10632 ctx->cu_stream = NULL;
Andrey Turkin0d021cc2016-05-29 12:23:26633
Hendrik Leppkes6fcbf392017-11-11 15:13:24634 if ((ret = nvenc_pop_context(avctx)) < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26635 goto fail2;
Andrey Turkin0d021cc2016-05-29 12:23:26636
637 if ((ret = nvenc_open_session(avctx)) < 0)
638 goto fail2;
639
640 if ((ret = nvenc_check_capabilities(avctx)) < 0)
641 goto fail3;
642
643 av_log(avctx, loglevel, "supports NVENC\n");
644
645 dl_fn->nvenc_device_count++;
646
Timo Rothenpieler5403d902017-01-18 22:01:28647 if (ctx->device == idx || ctx->device == ANY_DEVICE)
Andrey Turkin0d021cc2016-05-29 12:23:26648 return 0;
649
650fail3:
Hendrik Leppkes6fcbf392017-11-11 15:13:24651 if ((ret = nvenc_push_context(avctx)) < 0)
652 return ret;
Ganapathy Kasi43c417a2017-05-31 02:03:14653
Andrey Turkin0d021cc2016-05-29 12:23:26654 p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
655 ctx->nvencoder = NULL;
656
Hendrik Leppkes6fcbf392017-11-11 15:13:24657 if ((ret = nvenc_pop_context(avctx)) < 0)
658 return ret;
Ganapathy Kasi43c417a2017-05-31 02:03:14659
Andrey Turkin0d021cc2016-05-29 12:23:26660fail2:
Philip Langdale19d3d0c2018-11-11 06:47:28661 CHECK_CU(dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal));
Andrey Turkin0d021cc2016-05-29 12:23:26662 ctx->cu_context_internal = NULL;
663
664fail:
665 return AVERROR(ENOSYS);
666}
667
Andrey Turkin82d705e2016-05-20 14:49:24668static av_cold int nvenc_setup_device(AVCodecContext *avctx)
Timo Rothenpieler2a428db2014-11-29 23:04:37669{
Clément Bœschb7cc4eb2017-03-20 22:04:28670 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler2a428db2014-11-29 23:04:37671 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Timo Rothenpieler2a428db2014-11-29 23:04:37672
Andrey Turkinfaffff82016-05-25 14:05:50673 switch (avctx->codec->id) {
674 case AV_CODEC_ID_H264:
675 ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_H264_GUID;
676 break;
677 case AV_CODEC_ID_HEVC:
678 ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_HEVC_GUID;
679 break;
Timo Rothenpieler5c288a42022-11-05 20:17:37680#if CONFIG_AV1_NVENC_ENCODER
681 case AV_CODEC_ID_AV1:
682 ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_AV1_GUID;
683 break;
684#endif
Andrey Turkinfaffff82016-05-25 14:05:50685 default:
686 return AVERROR_BUG;
687 }
688
Timo Rothenpieler988f2e92021-04-18 09:17:54689 nvenc_map_preset(ctx);
690
691 if (ctx->flags & NVENC_DEPRECATED_PRESET)
692 av_log(avctx, AV_LOG_WARNING, "The selected preset is deprecated. Use p1 to p7 + -tune or fast/medium/slow.\n");
693
Hendrik Leppkesbff6d982017-11-11 15:51:58694 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11 || avctx->hw_frames_ctx || avctx->hw_device_ctx) {
Andrey Turkin0d021cc2016-05-29 12:23:26695 AVHWFramesContext *frames_ctx;
Timo Rothenpielerdad6f442017-05-07 11:35:25696 AVHWDeviceContext *hwdev_ctx;
Hendrik Leppkesbff6d982017-11-11 15:51:58697 AVCUDADeviceContext *cuda_device_hwctx = NULL;
698#if CONFIG_D3D11VA
699 AVD3D11VADeviceContext *d3d11_device_hwctx = NULL;
700#endif
Andrey Turkin0d021cc2016-05-29 12:23:26701 int ret;
Andrey Turkina8cf25d2016-05-20 22:08:06702
Timo Rothenpielerdad6f442017-05-07 11:35:25703 if (avctx->hw_frames_ctx) {
704 frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
Hendrik Leppkesbff6d982017-11-11 15:51:58705 if (frames_ctx->format == AV_PIX_FMT_CUDA)
706 cuda_device_hwctx = frames_ctx->device_ctx->hwctx;
707#if CONFIG_D3D11VA
708 else if (frames_ctx->format == AV_PIX_FMT_D3D11)
709 d3d11_device_hwctx = frames_ctx->device_ctx->hwctx;
710#endif
711 else
712 return AVERROR(EINVAL);
Timo Rothenpielerdad6f442017-05-07 11:35:25713 } else if (avctx->hw_device_ctx) {
714 hwdev_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data;
Hendrik Leppkesbff6d982017-11-11 15:51:58715 if (hwdev_ctx->type == AV_HWDEVICE_TYPE_CUDA)
716 cuda_device_hwctx = hwdev_ctx->hwctx;
717#if CONFIG_D3D11VA
718 else if (hwdev_ctx->type == AV_HWDEVICE_TYPE_D3D11VA)
719 d3d11_device_hwctx = hwdev_ctx->hwctx;
720#endif
721 else
722 return AVERROR(EINVAL);
Timo Rothenpielerdad6f442017-05-07 11:35:25723 } else {
Andrey Turkina8cf25d2016-05-20 22:08:06724 return AVERROR(EINVAL);
Timo Rothenpielerdad6f442017-05-07 11:35:25725 }
Andrey Turkin0d021cc2016-05-29 12:23:26726
Hendrik Leppkesbff6d982017-11-11 15:51:58727 if (cuda_device_hwctx) {
728 ctx->cu_context = cuda_device_hwctx->cuda_ctx;
Timo Rothenpieler51a23342019-09-27 16:30:10729 ctx->cu_stream = cuda_device_hwctx->stream;
Hendrik Leppkesbff6d982017-11-11 15:51:58730 }
731#if CONFIG_D3D11VA
732 else if (d3d11_device_hwctx) {
733 ctx->d3d11_device = d3d11_device_hwctx->device;
734 ID3D11Device_AddRef(ctx->d3d11_device);
735 }
736#endif
Andrey Turkin0d021cc2016-05-29 12:23:26737
738 ret = nvenc_open_session(avctx);
739 if (ret < 0)
740 return ret;
741
742 ret = nvenc_check_capabilities(avctx);
743 if (ret < 0) {
744 av_log(avctx, AV_LOG_FATAL, "Provided device doesn't support required NVENC features\n");
745 return ret;
746 }
Andrey Turkin0d021cc2016-05-29 12:23:26747 } else {
748 int i, nb_devices = 0;
749
Philip Langdale19d3d0c2018-11-11 06:47:28750 if (CHECK_CU(dl_fn->cuda_dl->cuInit(0)) < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26751 return AVERROR_UNKNOWN;
Andrey Turkina8cf25d2016-05-20 22:08:06752
Philip Langdale19d3d0c2018-11-11 06:47:28753 if (CHECK_CU(dl_fn->cuda_dl->cuDeviceGetCount(&nb_devices)) < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26754 return AVERROR_UNKNOWN;
Andrey Turkina8cf25d2016-05-20 22:08:06755
Andrey Turkin0d021cc2016-05-29 12:23:26756 if (!nb_devices) {
757 av_log(avctx, AV_LOG_FATAL, "No CUDA capable devices found\n");
758 return AVERROR_EXTERNAL;
759 }
760
761 av_log(avctx, AV_LOG_VERBOSE, "%d CUDA capable devices found\n", nb_devices);
762
763 dl_fn->nvenc_device_count = 0;
764 for (i = 0; i < nb_devices; ++i) {
765 if ((nvenc_check_device(avctx, i)) >= 0 && ctx->device != LIST_DEVICES)
766 return 0;
767 }
768
769 if (ctx->device == LIST_DEVICES)
770 return AVERROR_EXIT;
771
772 if (!dl_fn->nvenc_device_count) {
hydra3333ba6b20d2019-10-27 02:30:54773 av_log(avctx, AV_LOG_FATAL, "No capable devices found\n");
Andrey Turkin0d021cc2016-05-29 12:23:26774 return AVERROR_EXTERNAL;
775 }
776
Timo Rothenpieler5403d902017-01-18 22:01:28777 av_log(avctx, AV_LOG_FATAL, "Requested GPU %d, but only %d GPUs are available!\n", ctx->device, nb_devices);
Andrey Turkin82d705e2016-05-20 14:49:24778 return AVERROR(EINVAL);
Timo Rothenpieler2a428db2014-11-29 23:04:37779 }
780
Andrey Turkin82d705e2016-05-20 14:49:24781 return 0;
782}
783
Andrey Turkin82d705e2016-05-20 14:49:24784static av_cold void set_constqp(AVCodecContext *avctx)
785{
786 NvencContext *ctx = avctx->priv_data;
Andrey Turkinf84dfbc2016-05-25 16:39:54787 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
Timo Rothenpieler5c288a42022-11-05 20:17:37788#if CONFIG_AV1_NVENC_ENCODER
789 int qmax = avctx->codec->id == AV_CODEC_ID_AV1 ? 255 : 51;
790#else
791 int qmax = 51;
792#endif
Andrey Turkin82d705e2016-05-20 14:49:24793
Andrey Turkinf84dfbc2016-05-25 16:39:54794 rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
Konda Raju2db5ab72017-03-17 04:12:25795
796 if (ctx->init_qp_p >= 0) {
797 rc->constQP.qpInterP = ctx->init_qp_p;
798 if (ctx->init_qp_i >= 0 && ctx->init_qp_b >= 0) {
799 rc->constQP.qpIntra = ctx->init_qp_i;
800 rc->constQP.qpInterB = ctx->init_qp_b;
801 } else if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
802 rc->constQP.qpIntra = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37803 rc->constQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
Konda Raju2db5ab72017-03-17 04:12:25804 rc->constQP.qpInterB = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37805 rc->constQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
Konda Raju2db5ab72017-03-17 04:12:25806 } else {
807 rc->constQP.qpIntra = rc->constQP.qpInterP;
808 rc->constQP.qpInterB = rc->constQP.qpInterP;
809 }
Timo Rothenpieler7fb2a7a2017-03-23 16:01:40810 } else if (ctx->cqp >= 0) {
Timo Rothenpielerd84c2292017-03-23 16:10:25811 rc->constQP.qpInterP = rc->constQP.qpInterB = rc->constQP.qpIntra = ctx->cqp;
812 if (avctx->b_quant_factor != 0.0)
Timo Rothenpieler5c288a42022-11-05 20:17:37813 rc->constQP.qpInterB = av_clip(ctx->cqp * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
Timo Rothenpielerd84c2292017-03-23 16:10:25814 if (avctx->i_quant_factor != 0.0)
Timo Rothenpieler5c288a42022-11-05 20:17:37815 rc->constQP.qpIntra = av_clip(ctx->cqp * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
Konda Raju2db5ab72017-03-17 04:12:25816 }
Andrey Turkinf84dfbc2016-05-25 16:39:54817
818 avctx->qmin = -1;
819 avctx->qmax = -1;
Andrey Turkin82d705e2016-05-20 14:49:24820}
821
822static av_cold void set_vbr(AVCodecContext *avctx)
823{
824 NvencContext *ctx = avctx->priv_data;
Andrey Turkinf84dfbc2016-05-25 16:39:54825 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
826 int qp_inter_p;
Timo Rothenpieler5c288a42022-11-05 20:17:37827#if CONFIG_AV1_NVENC_ENCODER
828 int qmax = avctx->codec->id == AV_CODEC_ID_AV1 ? 255 : 51;
829#else
830 int qmax = 51;
831#endif
Andrey Turkin82d705e2016-05-20 14:49:24832
Andrey Turkinf84dfbc2016-05-25 16:39:54833 if (avctx->qmin >= 0 && avctx->qmax >= 0) {
834 rc->enableMinQP = 1;
835 rc->enableMaxQP = 1;
Andrey Turkin82d705e2016-05-20 14:49:24836
Andrey Turkinf84dfbc2016-05-25 16:39:54837 rc->minQP.qpInterB = avctx->qmin;
838 rc->minQP.qpInterP = avctx->qmin;
Clément Bœschb7cc4eb2017-03-20 22:04:28839 rc->minQP.qpIntra = avctx->qmin;
Andrey Turkin82d705e2016-05-20 14:49:24840
Andrey Turkinf84dfbc2016-05-25 16:39:54841 rc->maxQP.qpInterB = avctx->qmax;
842 rc->maxQP.qpInterP = avctx->qmax;
843 rc->maxQP.qpIntra = avctx->qmax;
844
845 qp_inter_p = (avctx->qmax + 3 * avctx->qmin) / 4; // biased towards Qmin
Timo Rothenpieler971351b2016-05-31 15:00:07846 } else if (avctx->qmin >= 0) {
847 rc->enableMinQP = 1;
848
849 rc->minQP.qpInterB = avctx->qmin;
850 rc->minQP.qpInterP = avctx->qmin;
851 rc->minQP.qpIntra = avctx->qmin;
852
853 qp_inter_p = avctx->qmin;
Andrey Turkinf84dfbc2016-05-25 16:39:54854 } else {
855 qp_inter_p = 26; // default to 26
856 }
857
858 rc->enableInitialRCQP = 1;
Andrey Turkinf84dfbc2016-05-25 16:39:54859
Konda Raju5f44a4a2017-02-28 05:39:12860 if (ctx->init_qp_p < 0) {
861 rc->initialRCQP.qpInterP = qp_inter_p;
Andrey Turkinf84dfbc2016-05-25 16:39:54862 } else {
Konda Raju5f44a4a2017-02-28 05:39:12863 rc->initialRCQP.qpInterP = ctx->init_qp_p;
864 }
865
866 if (ctx->init_qp_i < 0) {
867 if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
868 rc->initialRCQP.qpIntra = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37869 rc->initialRCQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
Konda Raju5f44a4a2017-02-28 05:39:12870 } else {
871 rc->initialRCQP.qpIntra = rc->initialRCQP.qpInterP;
872 }
873 } else {
874 rc->initialRCQP.qpIntra = ctx->init_qp_i;
875 }
876
877 if (ctx->init_qp_b < 0) {
878 if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
879 rc->initialRCQP.qpInterB = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37880 rc->initialRCQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
Konda Raju5f44a4a2017-02-28 05:39:12881 } else {
882 rc->initialRCQP.qpInterB = rc->initialRCQP.qpInterP;
883 }
884 } else {
885 rc->initialRCQP.qpInterB = ctx->init_qp_b;
Andrey Turkinf84dfbc2016-05-25 16:39:54886 }
Andrey Turkin82d705e2016-05-20 14:49:24887}
888
889static av_cold void set_lossless(AVCodecContext *avctx)
890{
891 NvencContext *ctx = avctx->priv_data;
Andrey Turkinf84dfbc2016-05-25 16:39:54892 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
Andrey Turkin82d705e2016-05-20 14:49:24893
Andrey Turkinf84dfbc2016-05-25 16:39:54894 rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
895 rc->constQP.qpInterB = 0;
896 rc->constQP.qpInterP = 0;
Clément Bœschb7cc4eb2017-03-20 22:04:28897 rc->constQP.qpIntra = 0;
Andrey Turkinf84dfbc2016-05-25 16:39:54898
899 avctx->qmin = -1;
900 avctx->qmax = -1;
901}
902
903static void nvenc_override_rate_control(AVCodecContext *avctx)
904{
905 NvencContext *ctx = avctx->priv_data;
906 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
907
908 switch (ctx->rc) {
909 case NV_ENC_PARAMS_RC_CONSTQP:
Andrey Turkinf84dfbc2016-05-25 16:39:54910 set_constqp(avctx);
911 return;
Timo Rothenpielerd2b46c12023-06-01 21:46:46912#ifndef NVENC_NO_DEPRECATED_RC
Andrey Turkinf84dfbc2016-05-25 16:39:54913 case NV_ENC_PARAMS_RC_VBR_MINQP:
914 if (avctx->qmin < 0) {
915 av_log(avctx, AV_LOG_WARNING,
916 "The variable bitrate rate-control requires "
917 "the 'qmin' option set.\n");
918 set_vbr(avctx);
919 return;
920 }
Ganapathy Raman Kasia5492432017-02-24 01:42:27921 /* fall through */
Timo Rothenpielercfbebe92017-05-09 11:57:39922 case NV_ENC_PARAMS_RC_VBR_HQ:
Timo Rothenpielerd2b46c12023-06-01 21:46:46923#endif
Ganapathy Raman Kasia5492432017-02-24 01:42:27924 case NV_ENC_PARAMS_RC_VBR:
Andrey Turkinf84dfbc2016-05-25 16:39:54925 set_vbr(avctx);
926 break;
927 case NV_ENC_PARAMS_RC_CBR:
Timo Rothenpielerd2b46c12023-06-01 21:46:46928#ifndef NVENC_NO_DEPRECATED_RC
Timo Rothenpielercfbebe92017-05-09 11:57:39929 case NV_ENC_PARAMS_RC_CBR_HQ:
930 case NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ:
Timo Rothenpielerd2b46c12023-06-01 21:46:46931#endif
Timo Rothenpielereae4eba2016-05-31 14:55:24932 break;
Andrey Turkinf84dfbc2016-05-25 16:39:54933 }
934
935 rc->rateControlMode = ctx->rc;
Andrey Turkin82d705e2016-05-20 14:49:24936}
937
Miroslav Slugeňde2faec2016-11-21 11:17:43938static av_cold int nvenc_recalc_surfaces(AVCodecContext *avctx)
939{
940 NvencContext *ctx = avctx->priv_data;
Ben Chang8de34582017-04-25 21:57:56941 // default minimum of 4 surfaces
942 // multiply by 2 for number of NVENCs on gpu (hardcode to 2)
943 // another multiply by 2 to avoid blocking next PBB group
944 int nb_surfaces = FFMAX(4, ctx->encode_config.frameIntervalP * 2 * 2);
Miroslav Slugeňde2faec2016-11-21 11:17:43945
Ben Chang8de34582017-04-25 21:57:56946 // lookahead enabled
Miroslav Slugeňde2faec2016-11-21 11:17:43947 if (ctx->rc_lookahead > 0) {
Ben Chang8de34582017-04-25 21:57:56948 // +1 is to account for lkd_bound calculation later
949 // +4 is to allow sufficient pipelining with lookahead
950 nb_surfaces = FFMAX(1, FFMAX(nb_surfaces, ctx->rc_lookahead + ctx->encode_config.frameIntervalP + 1 + 4));
951 if (nb_surfaces > ctx->nb_surfaces && ctx->nb_surfaces > 0)
952 {
Miroslav Slugeňde2faec2016-11-21 11:17:43953 av_log(avctx, AV_LOG_WARNING,
954 "Defined rc_lookahead requires more surfaces, "
955 "increasing used surfaces %d -> %d\n", ctx->nb_surfaces, nb_surfaces);
Miroslav Slugeňde2faec2016-11-21 11:17:43956 }
Ben Chang8de34582017-04-25 21:57:56957 ctx->nb_surfaces = FFMAX(nb_surfaces, ctx->nb_surfaces);
958 } else {
959 if (ctx->encode_config.frameIntervalP > 1 && ctx->nb_surfaces < nb_surfaces && ctx->nb_surfaces > 0)
960 {
961 av_log(avctx, AV_LOG_WARNING,
962 "Defined b-frame requires more surfaces, "
963 "increasing used surfaces %d -> %d\n", ctx->nb_surfaces, nb_surfaces);
964 ctx->nb_surfaces = FFMAX(ctx->nb_surfaces, nb_surfaces);
965 }
966 else if (ctx->nb_surfaces <= 0)
967 ctx->nb_surfaces = nb_surfaces;
968 // otherwise use user specified value
Miroslav Slugeňde2faec2016-11-21 11:17:43969 }
970
971 ctx->nb_surfaces = FFMAX(1, FFMIN(MAX_REGISTERED_FRAMES, ctx->nb_surfaces));
972 ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1);
973
Timo Rothenpieler16fdb482023-06-16 19:35:45974 // Output in the worst case will only start when the surface buffer is completely full.
975 // Hence we need to keep at least the max amount of surfaces plus the max reorder delay around.
976 ctx->frame_data_array_nb = ctx->nb_surfaces + ctx->encode_config.frameIntervalP - 1;
977
Miroslav Slugeňde2faec2016-11-21 11:17:43978 return 0;
979}
980
Andrey Turkinfaffff82016-05-25 14:05:50981static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:24982{
983 NvencContext *ctx = avctx->priv_data;
984
Timo Rothenpieler7fb2a7a2017-03-23 16:01:40985 if (avctx->global_quality > 0)
986 av_log(avctx, AV_LOG_WARNING, "Using global_quality with nvenc is deprecated. Use qp instead.\n");
987
988 if (ctx->cqp < 0 && avctx->global_quality > 0)
989 ctx->cqp = avctx->global_quality;
990
Andrey Turkin82d705e2016-05-20 14:49:24991 if (avctx->bit_rate > 0) {
992 ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate;
993 } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
994 ctx->encode_config.rcParams.maxBitRate = ctx->encode_config.rcParams.averageBitRate;
995 }
996
997 if (avctx->rc_max_rate > 0)
998 ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
999
Roman Arzumanyan9115d772020-03-19 08:35:291000#ifdef NVENC_HAVE_MULTIPASS
1001 ctx->encode_config.rcParams.multiPass = ctx->multipass;
Roman Arzumanyan9115d772020-03-19 08:35:291002
Timo Rothenpielere0c8e512020-10-21 16:45:521003 if (ctx->flags & NVENC_ONE_PASS)
1004 ctx->encode_config.rcParams.multiPass = NV_ENC_MULTI_PASS_DISABLED;
Timo Rothenpieler91b8e002020-10-30 16:26:321005 if (ctx->flags & NVENC_TWO_PASSES || ctx->twopass > 0)
Timo Rothenpielere0c8e512020-10-21 16:45:521006 ctx->encode_config.rcParams.multiPass = NV_ENC_TWO_PASS_FULL_RESOLUTION;
1007
1008 if (ctx->rc < 0) {
1009 if (ctx->cbr) {
1010 ctx->rc = NV_ENC_PARAMS_RC_CBR;
1011 } else if (ctx->cqp >= 0) {
1012 ctx->rc = NV_ENC_PARAMS_RC_CONSTQP;
Timo Rothenpielerd5b0a8e2020-10-30 16:21:131013 } else if (ctx->quality >= 0.0f) {
Timo Rothenpielere0c8e512020-10-21 16:45:521014 ctx->rc = NV_ENC_PARAMS_RC_VBR;
1015 }
1016 }
1017#else
Andrey Turkinf84dfbc2016-05-25 16:39:541018 if (ctx->rc < 0) {
1019 if (ctx->flags & NVENC_ONE_PASS)
1020 ctx->twopass = 0;
1021 if (ctx->flags & NVENC_TWO_PASSES)
1022 ctx->twopass = 1;
1023
1024 if (ctx->twopass < 0)
1025 ctx->twopass = (ctx->flags & NVENC_LOWLATENCY) != 0;
1026
1027 if (ctx->cbr) {
1028 if (ctx->twopass) {
Timo Rothenpielercfbebe92017-05-09 11:57:391029 ctx->rc = NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ;
Andrey Turkinf84dfbc2016-05-25 16:39:541030 } else {
1031 ctx->rc = NV_ENC_PARAMS_RC_CBR;
1032 }
Timo Rothenpieler7fb2a7a2017-03-23 16:01:401033 } else if (ctx->cqp >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541034 ctx->rc = NV_ENC_PARAMS_RC_CONSTQP;
1035 } else if (ctx->twopass) {
Timo Rothenpielercfbebe92017-05-09 11:57:391036 ctx->rc = NV_ENC_PARAMS_RC_VBR_HQ;
Andrey Turkinf84dfbc2016-05-25 16:39:541037 } else if (avctx->qmin >= 0 && avctx->qmax >= 0) {
1038 ctx->rc = NV_ENC_PARAMS_RC_VBR_MINQP;
1039 }
1040 }
Timo Rothenpielere0c8e512020-10-21 16:45:521041#endif
Andrey Turkinf84dfbc2016-05-25 16:39:541042
Timo Rothenpielercfbebe92017-05-09 11:57:391043 if (ctx->rc >= 0 && ctx->rc & RC_MODE_DEPRECATED) {
1044 av_log(avctx, AV_LOG_WARNING, "Specified rc mode is deprecated.\n");
Timo Rothenpielercde3c082020-10-21 16:17:081045 av_log(avctx, AV_LOG_WARNING, "Use -rc constqp/cbr/vbr, -tune and -multipass instead.\n");
Timo Rothenpielercfbebe92017-05-09 11:57:391046
1047 ctx->rc &= ~RC_MODE_DEPRECATED;
1048 }
1049
Timo Rothenpieler00b57982021-08-09 13:16:581050#ifdef NVENC_HAVE_QP_CHROMA_OFFSETS
1051 ctx->encode_config.rcParams.cbQPIndexOffset = ctx->qp_cb_offset;
1052 ctx->encode_config.rcParams.crQPIndexOffset = ctx->qp_cr_offset;
1053#else
1054 if (ctx->qp_cb_offset || ctx->qp_cr_offset)
1055 av_log(avctx, AV_LOG_WARNING, "Failed setting QP CB/CR offsets, SDK 11.1 or greater required at compile time.\n");
1056#endif
1057
Roman Arzumanyan9115d772020-03-19 08:35:291058#ifdef NVENC_HAVE_LDKFS
1059 if (ctx->ldkfs)
1060 ctx->encode_config.rcParams.lowDelayKeyFrameScale = ctx->ldkfs;
1061#endif
1062
Andrey Turkinfaffff82016-05-25 14:05:501063 if (ctx->flags & NVENC_LOSSLESS) {
Andrey Turkin82d705e2016-05-20 14:49:241064 set_lossless(avctx);
Timo Rothenpieler1330a0f2016-05-31 14:53:381065 } else if (ctx->rc >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541066 nvenc_override_rate_control(avctx);
Andrey Turkin82d705e2016-05-20 14:49:241067 } else {
Andrey Turkinf84dfbc2016-05-25 16:39:541068 ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
1069 set_vbr(avctx);
Andrey Turkin82d705e2016-05-20 14:49:241070 }
1071
1072 if (avctx->rc_buffer_size > 0) {
1073 ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size;
1074 } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
pkviet15537512018-05-03 00:15:521075 avctx->rc_buffer_size = ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate;
Andrey Turkin82d705e2016-05-20 14:49:241076 }
Oliver Collyera81b3982016-08-25 15:20:031077
Yogender Guptafacc19e2016-09-24 15:55:001078 if (ctx->aq) {
1079 ctx->encode_config.rcParams.enableAQ = 1;
1080 ctx->encode_config.rcParams.aqStrength = ctx->aq_strength;
1081 av_log(avctx, AV_LOG_VERBOSE, "AQ enabled.\n");
Oliver Collyera81b3982016-08-25 15:20:031082 }
Yogender Guptafacc19e2016-09-24 15:55:001083
1084 if (ctx->temporal_aq) {
1085 ctx->encode_config.rcParams.enableTemporalAQ = 1;
1086 av_log(avctx, AV_LOG_VERBOSE, "Temporal AQ enabled.\n");
1087 }
1088
Ruta Gadkari67db4ff2016-12-26 07:49:161089 if (ctx->rc_lookahead > 0) {
Yogender Guptafacc19e2016-09-24 15:55:001090 int lkd_bound = FFMIN(ctx->nb_surfaces, ctx->async_depth) -
1091 ctx->encode_config.frameIntervalP - 4;
1092
1093 if (lkd_bound < 0) {
Timo Rothenpielerac0f42d2022-12-05 20:10:361094 ctx->encode_config.rcParams.enableLookahead = 0;
Yogender Guptafacc19e2016-09-24 15:55:001095 av_log(avctx, AV_LOG_WARNING,
1096 "Lookahead not enabled. Increase buffer delay (-delay).\n");
1097 } else {
1098 ctx->encode_config.rcParams.enableLookahead = 1;
1099 ctx->encode_config.rcParams.lookaheadDepth = av_clip(ctx->rc_lookahead, 0, lkd_bound);
1100 ctx->encode_config.rcParams.disableIadapt = ctx->no_scenecut;
1101 ctx->encode_config.rcParams.disableBadapt = !ctx->b_adapt;
1102 av_log(avctx, AV_LOG_VERBOSE,
1103 "Lookahead enabled: depth %d, scenecut %s, B-adapt %s.\n",
1104 ctx->encode_config.rcParams.lookaheadDepth,
1105 ctx->encode_config.rcParams.disableIadapt ? "disabled" : "enabled",
1106 ctx->encode_config.rcParams.disableBadapt ? "disabled" : "enabled");
Timo Rothenpieler45216e32022-12-05 20:18:421107 if (ctx->encode_config.rcParams.lookaheadDepth < ctx->rc_lookahead)
1108 av_log(avctx, AV_LOG_WARNING, "Clipping lookahead depth to %d (from %d) due to lack of surfaces/delay",
1109 ctx->encode_config.rcParams.lookaheadDepth, ctx->rc_lookahead);
Yogender Guptafacc19e2016-09-24 15:55:001110 }
1111 }
1112
1113 if (ctx->strict_gop) {
1114 ctx->encode_config.rcParams.strictGOPTarget = 1;
1115 av_log(avctx, AV_LOG_VERBOSE, "Strict GOP target enabled.\n");
1116 }
1117
1118 if (ctx->nonref_p)
1119 ctx->encode_config.rcParams.enableNonRefP = 1;
1120
1121 if (ctx->zerolatency)
1122 ctx->encode_config.rcParams.zeroReorderDelay = 1;
1123
Roman Arzumanyan0842fd22020-04-20 10:53:361124 if (ctx->quality) {
Ben Chang18a659d2017-05-10 06:41:171125 //convert from float to fixed point 8.8
1126 int tmp_quality = (int)(ctx->quality * 256.0f);
1127 ctx->encode_config.rcParams.targetQuality = (uint8_t)(tmp_quality >> 8);
1128 ctx->encode_config.rcParams.targetQualityLSB = (uint8_t)(tmp_quality & 0xff);
Roman Arzumanyan0842fd22020-04-20 10:53:361129
1130 av_log(avctx, AV_LOG_VERBOSE, "CQ(%d) mode enabled.\n", tmp_quality);
1131
Timo Rothenpieler9ca139b2022-12-08 11:31:001132 // CQ mode shall discard avg bitrate/vbv buffer size and honor only max bitrate
Roman Arzumanyan470bbf62020-06-03 13:12:121133 ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate = 0;
Timo Rothenpieler9ca139b2022-12-08 11:31:001134 ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size = 0;
Roman Arzumanyan470bbf62020-06-03 13:12:121135 ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
Ben Chang18a659d2017-05-10 06:41:171136 }
Andrey Turkin82d705e2016-05-20 14:49:241137}
1138
Andrey Turkinfaffff82016-05-25 14:05:501139static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:241140{
Andrey Turkinfaffff82016-05-25 14:05:501141 NvencContext *ctx = avctx->priv_data;
1142 NV_ENC_CONFIG *cc = &ctx->encode_config;
1143 NV_ENC_CONFIG_H264 *h264 = &cc->encodeCodecConfig.h264Config;
1144 NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui = &h264->h264VUIParameters;
Andrey Turkin82d705e2016-05-20 14:49:241145
Timo Rothenpielerb71069872022-08-06 18:58:481146 const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(ctx->data_pix_fmt);
1147
1148 if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) && !IS_GBRP(ctx->data_pix_fmt)) {
1149 vui->colourMatrix = AVCOL_SPC_BT470BG;
1150 vui->colourPrimaries = avctx->color_primaries;
1151 vui->transferCharacteristics = avctx->color_trc;
1152 vui->videoFullRangeFlag = 0;
1153 } else {
1154 vui->colourMatrix = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace;
1155 vui->colourPrimaries = avctx->color_primaries;
1156 vui->transferCharacteristics = avctx->color_trc;
1157 vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
1158 || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
1159 }
Andrey Turkin82d705e2016-05-20 14:49:241160
Andrey Turkinfaffff82016-05-25 14:05:501161 vui->colourDescriptionPresentFlag =
Timo Rothenpieler7555d6f2021-03-30 20:08:491162 (vui->colourMatrix != 2 || vui->colourPrimaries != 2 || vui->transferCharacteristics != 2);
Andrey Turkin82d705e2016-05-20 14:49:241163
Andrey Turkinfaffff82016-05-25 14:05:501164 vui->videoSignalTypePresentFlag =
1165 (vui->colourDescriptionPresentFlag
1166 || vui->videoFormat != 5
1167 || vui->videoFullRangeFlag != 0);
Andrey Turkin82d705e2016-05-20 14:49:241168
Aleksoid7eb0d9e2023-07-27 02:26:231169 if (ctx->max_slice_size > 0) {
1170 h264->sliceMode = 1;
1171 h264->sliceModeData = ctx->max_slice_size;
1172 } else {
1173 h264->sliceMode = 3;
1174 h264->sliceModeData = avctx->slices > 0 ? avctx->slices : 1;
1175 }
Andrey Turkin82d705e2016-05-20 14:49:241176
Limin Wange6bd5172021-09-06 02:01:581177 if (ctx->intra_refresh) {
1178 h264->enableIntraRefresh = 1;
Ricardo Monteiro99dfdb42023-06-22 10:18:191179 h264->intraRefreshPeriod = cc->gopLength;
1180 h264->intraRefreshCnt = cc->gopLength - 1;
Zhao Zhili0d0c3982023-07-06 12:00:481181 cc->gopLength = NVENC_INFINITE_GOPLENGTH;
Limin Wang37565252021-09-02 10:38:571182#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH
1183 h264->singleSliceIntraRefresh = ctx->single_slice_intra_refresh;
1184#endif
Limin Wange6bd5172021-09-06 02:01:581185 }
1186
Limin Wang75001ae2021-09-02 10:38:581187 if (ctx->constrained_encoding)
1188 h264->enableConstrainedEncoding = 1;
1189
Andrey Turkinfaffff82016-05-25 14:05:501190 h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
Andrey Turkinf84dfbc2016-05-25 16:39:541191 h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
Miroslav Slugen1841eda2016-12-30 21:02:421192 h264->outputAUD = ctx->aud;
Andrey Turkin82d705e2016-05-20 14:49:241193
Timo Rothenpielere929b2f2019-09-27 15:55:231194 if (ctx->dpb_size >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541195 /* 0 means "let the hardware decide" */
Timo Rothenpielere929b2f2019-09-27 15:55:231196 h264->maxNumRefFrames = ctx->dpb_size;
Andrey Turkinf84dfbc2016-05-25 16:39:541197 }
Limin Wange6bd5172021-09-06 02:01:581198
Zhao Zhili7eeef722023-07-06 19:57:381199 h264->idrPeriod = cc->gopLength;
Andrey Turkinf84dfbc2016-05-25 16:39:541200
1201 if (IS_CBR(cc->rcParams.rateControlMode)) {
1202 h264->outputBufferingPeriodSEI = 1;
Andrey Turkinf84dfbc2016-05-25 16:39:541203 }
1204
Timo Rothenpieler4e6638a2017-09-02 13:39:241205 h264->outputPictureTimingSEI = 1;
1206
Timo Rothenpielerd2b46c12023-06-01 21:46:461207#ifndef NVENC_NO_DEPRECATED_RC
Timo Rothenpielercfbebe92017-05-09 11:57:391208 if (cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ ||
1209 cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_CBR_HQ ||
1210 cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_VBR_HQ) {
Andrey Turkinf84dfbc2016-05-25 16:39:541211 h264->adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE;
1212 h264->fmoMode = NV_ENC_H264_FMO_DISABLE;
1213 }
Timo Rothenpielerd2b46c12023-06-01 21:46:461214#endif
Andrey Turkin82d705e2016-05-20 14:49:241215
Andrey Turkin98243212016-05-25 14:26:251216 if (ctx->flags & NVENC_LOSSLESS) {
1217 h264->qpPrimeYZeroTransformBypassFlag = 1;
1218 } else {
1219 switch(ctx->profile) {
1220 case NV_ENC_H264_PROFILE_BASELINE:
Andrey Turkinfaffff82016-05-25 14:05:501221 cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411222 avctx->profile = AV_PROFILE_H264_BASELINE;
Andrey Turkin98243212016-05-25 14:26:251223 break;
1224 case NV_ENC_H264_PROFILE_MAIN:
1225 cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411226 avctx->profile = AV_PROFILE_H264_MAIN;
Andrey Turkin98243212016-05-25 14:26:251227 break;
1228 case NV_ENC_H264_PROFILE_HIGH:
1229 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411230 avctx->profile = AV_PROFILE_H264_HIGH;
Andrey Turkin98243212016-05-25 14:26:251231 break;
1232 case NV_ENC_H264_PROFILE_HIGH_444P:
Andrey Turkinfaffff82016-05-25 14:05:501233 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411234 avctx->profile = AV_PROFILE_H264_HIGH_444_PREDICTIVE;
Andrey Turkin98243212016-05-25 14:26:251235 break;
Andrey Turkin82d705e2016-05-20 14:49:241236 }
1237 }
1238
1239 // force setting profile as high444p if input is AV_PIX_FMT_YUV444P
Timo Rothenpieler7555d6f2021-03-30 20:08:491240 if (IS_YUV444(ctx->data_pix_fmt)) {
Andrey Turkinfaffff82016-05-25 14:05:501241 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411242 avctx->profile = AV_PROFILE_H264_HIGH_444_PREDICTIVE;
Andrey Turkin82d705e2016-05-20 14:49:241243 }
1244
Andreas Rheinhardt8238bc02023-09-02 12:57:411245 h264->chromaFormatIDC = avctx->profile == AV_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;
Andrey Turkin82d705e2016-05-20 14:49:241246
Andrey Turkinb0172872016-05-25 15:00:521247 h264->level = ctx->level;
Andrey Turkin82d705e2016-05-20 14:49:241248
Timo Rothenpielera0b69e22017-08-30 19:06:251249 if (ctx->coder >= 0)
1250 h264->entropyCodingMode = ctx->coder;
1251
Timo Rothenpieler86e9dba2018-04-11 12:22:201252#ifdef NVENC_HAVE_BFRAME_REF_MODE
Timo Rothenpieler28680e22022-11-02 18:02:561253 if (ctx->b_ref_mode >= 0)
1254 h264->useBFramesAsRef = ctx->b_ref_mode;
Timo Rothenpieler86e9dba2018-04-11 12:22:201255#endif
1256
Roman Arzumanyan567b5e32019-09-27 15:56:111257#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES
1258 h264->numRefL0 = avctx->refs;
1259 h264->numRefL1 = avctx->refs;
1260#endif
1261
Andrey Turkin82d705e2016-05-20 14:49:241262 return 0;
1263}
1264
1265static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
1266{
Andrey Turkinfaffff82016-05-25 14:05:501267 NvencContext *ctx = avctx->priv_data;
1268 NV_ENC_CONFIG *cc = &ctx->encode_config;
1269 NV_ENC_CONFIG_HEVC *hevc = &cc->encodeCodecConfig.hevcConfig;
1270 NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui = &hevc->hevcVUIParameters;
Andrey Turkin82d705e2016-05-20 14:49:241271
Timo Rothenpielerb71069872022-08-06 18:58:481272 const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(ctx->data_pix_fmt);
1273
1274 if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) && !IS_GBRP(ctx->data_pix_fmt)) {
1275 vui->colourMatrix = AVCOL_SPC_BT470BG;
1276 vui->colourPrimaries = avctx->color_primaries;
1277 vui->transferCharacteristics = avctx->color_trc;
1278 vui->videoFullRangeFlag = 0;
1279 } else {
1280 vui->colourMatrix = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace;
1281 vui->colourPrimaries = avctx->color_primaries;
1282 vui->transferCharacteristics = avctx->color_trc;
1283 vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
1284 || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
1285 }
Andrey Turkin82d705e2016-05-20 14:49:241286
Andrey Turkinfaffff82016-05-25 14:05:501287 vui->colourDescriptionPresentFlag =
Timo Rothenpieler7555d6f2021-03-30 20:08:491288 (vui->colourMatrix != 2 || vui->colourPrimaries != 2 || vui->transferCharacteristics != 2);
Andrey Turkin82d705e2016-05-20 14:49:241289
Andrey Turkinfaffff82016-05-25 14:05:501290 vui->videoSignalTypePresentFlag =
1291 (vui->colourDescriptionPresentFlag
1292 || vui->videoFormat != 5
1293 || vui->videoFullRangeFlag != 0);
Andrey Turkin82d705e2016-05-20 14:49:241294
Aleksoid7eb0d9e2023-07-27 02:26:231295 if (ctx->max_slice_size > 0) {
1296 hevc->sliceMode = 1;
1297 hevc->sliceModeData = ctx->max_slice_size;
1298 } else {
1299 hevc->sliceMode = 3;
1300 hevc->sliceModeData = avctx->slices > 0 ? avctx->slices : 1;
1301 }
Andrey Turkin82d705e2016-05-20 14:49:241302
Limin Wange6bd5172021-09-06 02:01:581303 if (ctx->intra_refresh) {
1304 hevc->enableIntraRefresh = 1;
Ricardo Monteiro99dfdb42023-06-22 10:18:191305 hevc->intraRefreshPeriod = cc->gopLength;
1306 hevc->intraRefreshCnt = cc->gopLength - 1;
Zhao Zhili0d0c3982023-07-06 12:00:481307 cc->gopLength = NVENC_INFINITE_GOPLENGTH;
Limin Wang37565252021-09-02 10:38:571308#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH
1309 hevc->singleSliceIntraRefresh = ctx->single_slice_intra_refresh;
1310#endif
Limin Wange6bd5172021-09-06 02:01:581311 }
1312
Limin Wang75001ae2021-09-02 10:38:581313#ifdef NVENC_HAVE_HEVC_CONSTRAINED_ENCODING
1314 if (ctx->constrained_encoding)
1315 hevc->enableConstrainedEncoding = 1;
1316#endif
1317
Andrey Turkinfaffff82016-05-25 14:05:501318 hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
Andrey Turkinf84dfbc2016-05-25 16:39:541319 hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
Miroslav Slugen1841eda2016-12-30 21:02:421320 hevc->outputAUD = ctx->aud;
Andrey Turkin82d705e2016-05-20 14:49:241321
Timo Rothenpielere929b2f2019-09-27 15:55:231322 if (ctx->dpb_size >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541323 /* 0 means "let the hardware decide" */
Timo Rothenpielere929b2f2019-09-27 15:55:231324 hevc->maxNumRefFramesInDPB = ctx->dpb_size;
Andrey Turkinf84dfbc2016-05-25 16:39:541325 }
Limin Wange6bd5172021-09-06 02:01:581326
Zhao Zhili7eeef722023-07-06 19:57:381327 hevc->idrPeriod = cc->gopLength;
Andrey Turkinf84dfbc2016-05-25 16:39:541328
1329 if (IS_CBR(cc->rcParams.rateControlMode)) {
1330 hevc->outputBufferingPeriodSEI = 1;
Andrey Turkinf84dfbc2016-05-25 16:39:541331 }
Andrey Turkin82d705e2016-05-20 14:49:241332
Timo Rothenpieler4e6638a2017-09-02 13:39:241333 hevc->outputPictureTimingSEI = 1;
1334
Clément Bœschb7cc4eb2017-03-20 22:04:281335 switch (ctx->profile) {
Oliver Collyerd1bf8a32016-08-25 15:18:031336 case NV_ENC_HEVC_PROFILE_MAIN:
1337 cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411338 avctx->profile = AV_PROFILE_HEVC_MAIN;
Oliver Collyerd1bf8a32016-08-25 15:18:031339 break;
1340 case NV_ENC_HEVC_PROFILE_MAIN_10:
1341 cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411342 avctx->profile = AV_PROFILE_HEVC_MAIN_10;
Oliver Collyerd1bf8a32016-08-25 15:18:031343 break;
Timo Rothenpieler033f98c2016-09-28 12:21:031344 case NV_ENC_HEVC_PROFILE_REXT:
1345 cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411346 avctx->profile = AV_PROFILE_HEVC_REXT;
Timo Rothenpieler033f98c2016-09-28 12:21:031347 break;
Oliver Collyerd1bf8a32016-08-25 15:18:031348 }
1349
1350 // force setting profile as main10 if input is 10 bit
1351 if (IS_10BIT(ctx->data_pix_fmt)) {
1352 cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411353 avctx->profile = AV_PROFILE_HEVC_MAIN_10;
Oliver Collyerd1bf8a32016-08-25 15:18:031354 }
1355
Timo Rothenpieler033f98c2016-09-28 12:21:031356 // force setting profile as rext if input is yuv444
1357 if (IS_YUV444(ctx->data_pix_fmt)) {
1358 cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411359 avctx->profile = AV_PROFILE_HEVC_REXT;
Timo Rothenpieler033f98c2016-09-28 12:21:031360 }
1361
Oliver Collyerd1bf8a32016-08-25 15:18:031362 hevc->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1;
1363
1364 hevc->pixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
Andrey Turkin82d705e2016-05-20 14:49:241365
Andrey Turkinb0172872016-05-25 15:00:521366 hevc->level = ctx->level;
Andrey Turkin82d705e2016-05-20 14:49:241367
Andrey Turkin40df4682016-05-25 15:06:021368 hevc->tier = ctx->tier;
Andrey Turkin82d705e2016-05-20 14:49:241369
Roman Arzumanyanf1f66df2019-02-14 12:20:251370#ifdef NVENC_HAVE_HEVC_BFRAME_REF_MODE
Timo Rothenpieler28680e22022-11-02 18:02:561371 if (ctx->b_ref_mode >= 0)
1372 hevc->useBFramesAsRef = ctx->b_ref_mode;
Roman Arzumanyanf1f66df2019-02-14 12:20:251373#endif
1374
Roman Arzumanyan567b5e32019-09-27 15:56:111375#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES
1376 hevc->numRefL0 = avctx->refs;
1377 hevc->numRefL1 = avctx->refs;
1378#endif
1379
Andrey Turkin82d705e2016-05-20 14:49:241380 return 0;
1381}
1382
Timo Rothenpieler5c288a42022-11-05 20:17:371383#if CONFIG_AV1_NVENC_ENCODER
1384static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx)
1385{
1386 NvencContext *ctx = avctx->priv_data;
1387 NV_ENC_CONFIG *cc = &ctx->encode_config;
1388 NV_ENC_CONFIG_AV1 *av1 = &cc->encodeCodecConfig.av1Config;
1389
1390 const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(ctx->data_pix_fmt);
1391
1392 if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) && !IS_GBRP(ctx->data_pix_fmt)) {
1393 av1->matrixCoefficients = AVCOL_SPC_BT470BG;
1394 av1->colorPrimaries = avctx->color_primaries;
1395 av1->transferCharacteristics = avctx->color_trc;
1396 av1->colorRange = 0;
1397 } else {
1398 av1->matrixCoefficients = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace;
1399 av1->colorPrimaries = avctx->color_primaries;
1400 av1->transferCharacteristics = avctx->color_trc;
1401 av1->colorRange = (avctx->color_range == AVCOL_RANGE_JPEG
1402 || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
1403 }
1404
1405 if (IS_YUV444(ctx->data_pix_fmt)) {
Timo Rothenpieler939273d2022-11-10 14:26:431406 av_log(avctx, AV_LOG_ERROR, "AV1 High Profile not supported, required for 4:4:4 encoding\n");
1407 return AVERROR(ENOTSUP);
Timo Rothenpieler5c288a42022-11-05 20:17:371408 } else {
1409 cc->profileGUID = NV_ENC_AV1_PROFILE_MAIN_GUID;
Andreas Rheinhardt8238bc02023-09-02 12:57:411410 avctx->profile = AV_PROFILE_AV1_MAIN;
Timo Rothenpieler5c288a42022-11-05 20:17:371411 }
1412
1413 if (ctx->dpb_size >= 0) {
1414 /* 0 means "let the hardware decide" */
1415 av1->maxNumRefFramesInDPB = ctx->dpb_size;
1416 }
1417
1418 if (ctx->intra_refresh) {
1419 av1->enableIntraRefresh = 1;
Ricardo Monteiro99dfdb42023-06-22 10:18:191420 av1->intraRefreshPeriod = cc->gopLength;
1421 av1->intraRefreshCnt = cc->gopLength - 1;
Zhao Zhili0d0c3982023-07-06 12:00:481422 cc->gopLength = NVENC_INFINITE_GOPLENGTH;
Timo Rothenpieler5c288a42022-11-05 20:17:371423 }
1424
Zhao Zhili7eeef722023-07-06 19:57:381425 av1->idrPeriod = cc->gopLength;
1426
Timo Rothenpieler5c288a42022-11-05 20:17:371427 if (IS_CBR(cc->rcParams.rateControlMode)) {
1428 av1->enableBitstreamPadding = 1;
1429 }
1430
1431 if (ctx->tile_cols >= 0)
1432 av1->numTileColumns = ctx->tile_cols;
1433 if (ctx->tile_rows >= 0)
1434 av1->numTileRows = ctx->tile_rows;
1435
1436 av1->outputAnnexBFormat = 0;
1437
1438 av1->level = ctx->level;
1439 av1->tier = ctx->tier;
1440
1441 av1->enableTimingInfo = ctx->timing_info;
1442
1443 /* mp4 encapsulation requires sequence headers to be present on all keyframes for AV1 */
1444 av1->disableSeqHdr = 0;
1445 av1->repeatSeqHdr = 1;
1446
1447 av1->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1;
1448
1449 av1->inputPixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
1450 av1->pixelBitDepthMinus8 = (IS_10BIT(ctx->data_pix_fmt) || ctx->highbitdepth) ? 2 : 0;
1451
1452 if (ctx->b_ref_mode >= 0)
1453 av1->useBFramesAsRef = ctx->b_ref_mode;
1454
1455 av1->numFwdRefs = avctx->refs;
1456 av1->numBwdRefs = avctx->refs;
1457
1458 return 0;
1459}
1460#endif
1461
Andrey Turkinfaffff82016-05-25 14:05:501462static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:241463{
1464 switch (avctx->codec->id) {
1465 case AV_CODEC_ID_H264:
Andrey Turkinfaffff82016-05-25 14:05:501466 return nvenc_setup_h264_config(avctx);
1467 case AV_CODEC_ID_HEVC:
Andrey Turkin82d705e2016-05-20 14:49:241468 return nvenc_setup_hevc_config(avctx);
Timo Rothenpieler5c288a42022-11-05 20:17:371469#if CONFIG_AV1_NVENC_ENCODER
1470 case AV_CODEC_ID_AV1:
1471 return nvenc_setup_av1_config(avctx);
1472#endif
Andrey Turkin82d705e2016-05-20 14:49:241473 /* Earlier switch/case will return if unknown codec is passed. */
1474 }
1475
1476 return 0;
1477}
1478
Miroslav Slugeň952421c2017-02-12 18:53:581479static void compute_dar(AVCodecContext *avctx, int *dw, int *dh) {
1480 int sw, sh;
1481
1482 sw = avctx->width;
1483 sh = avctx->height;
1484
Timo Rothenpielere7fbdda2022-11-10 12:05:591485#if CONFIG_AV1_NVENC_ENCODER
1486 if (avctx->codec->id == AV_CODEC_ID_AV1) {
1487 /* For AV1 we actually need to calculate the render width/height, not the dar */
1488 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0
1489 && avctx->sample_aspect_ratio.num != avctx->sample_aspect_ratio.den)
1490 {
1491 if (avctx->sample_aspect_ratio.num > avctx->sample_aspect_ratio.den) {
1492 sw = av_rescale(sw, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
1493 } else {
1494 sh = av_rescale(sh, avctx->sample_aspect_ratio.den, avctx->sample_aspect_ratio.num);
1495 }
1496 }
1497
1498 *dw = sw;
1499 *dh = sh;
1500 return;
1501 }
1502#endif
1503
Miroslav Slugeň952421c2017-02-12 18:53:581504 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) {
1505 sw *= avctx->sample_aspect_ratio.num;
1506 sh *= avctx->sample_aspect_ratio.den;
1507 }
1508
1509 av_reduce(dw, dh, sw, sh, 1024 * 1024);
1510}
1511
Andrey Turkin82d705e2016-05-20 14:49:241512static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
1513{
1514 NvencContext *ctx = avctx->priv_data;
1515 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1516 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
1517
1518 NV_ENC_PRESET_CONFIG preset_config = { 0 };
Andrey Turkin82d705e2016-05-20 14:49:241519 NVENCSTATUS nv_status = NV_ENC_SUCCESS;
1520 AVCPBProperties *cpb_props;
Andrey Turkin82d705e2016-05-20 14:49:241521 int res = 0;
1522 int dw, dh;
1523
Andrey Turkin82d705e2016-05-20 14:49:241524 ctx->encode_config.version = NV_ENC_CONFIG_VER;
1525 ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
Andrey Turkinfaffff82016-05-25 14:05:501526
1527 ctx->init_encode_params.encodeHeight = avctx->height;
1528 ctx->init_encode_params.encodeWidth = avctx->width;
1529
1530 ctx->init_encode_params.encodeConfig = &ctx->encode_config;
1531
Andrey Turkin82d705e2016-05-20 14:49:241532 preset_config.version = NV_ENC_PRESET_CONFIG_VER;
1533 preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
1534
Roman Arzumanyan9115d772020-03-19 08:35:291535#ifdef NVENC_HAVE_NEW_PRESETS
Timo Rothenpielerbb6edf62020-10-29 20:59:371536 ctx->init_encode_params.tuningInfo = ctx->tuning_info;
Roman Arzumanyan9115d772020-03-19 08:35:291537
Timo Rothenpieler988f2e92021-04-18 09:17:541538 if (ctx->flags & NVENC_LOSSLESS)
1539 ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOSSLESS;
1540 else if (ctx->flags & NVENC_LOWLATENCY)
Timo Rothenpielerbb6edf62020-10-29 20:59:371541 ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOW_LATENCY;
Timo Rothenpielere0c8e512020-10-21 16:45:521542
Timo Rothenpielerbb6edf62020-10-29 20:59:371543 nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder,
1544 ctx->init_encode_params.encodeGUID,
1545 ctx->init_encode_params.presetGUID,
1546 ctx->init_encode_params.tuningInfo,
1547 &preset_config);
1548#else
Timo Rothenpielerbb6edf62020-10-29 20:59:371549 nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
1550 ctx->init_encode_params.encodeGUID,
1551 ctx->init_encode_params.presetGUID,
1552 &preset_config);
Roman Arzumanyan9115d772020-03-19 08:35:291553#endif
Andrey Turkinfaffff82016-05-25 14:05:501554 if (nv_status != NV_ENC_SUCCESS)
1555 return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration");
Timo Rothenpieler2a428db2014-11-29 23:04:371556
Andrey Turkinfaffff82016-05-25 14:05:501557 memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
Agatha Hu49046582015-09-11 09:07:101558
Andrey Turkinfaffff82016-05-25 14:05:501559 ctx->encode_config.version = NV_ENC_CONFIG_VER;
Timo Rothenpielerfb34c582015-01-26 12:28:221560
Miroslav Slugeň952421c2017-02-12 18:53:581561 compute_dar(avctx, &dw, &dh);
Miroslav Slugeňf2dd6ae2016-11-27 00:46:061562 ctx->init_encode_params.darHeight = dh;
1563 ctx->init_encode_params.darWidth = dw;
Timo Rothenpielerfb34c582015-01-26 12:28:221564
Zachariah Brownb18fd2b2020-05-14 18:15:331565 if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
1566 ctx->init_encode_params.frameRateNum = avctx->framerate.num;
1567 ctx->init_encode_params.frameRateDen = avctx->framerate.den;
1568 } else {
1569 ctx->init_encode_params.frameRateNum = avctx->time_base.den;
Anton Khirnov7d1d61c2023-05-04 09:50:481570FF_DISABLE_DEPRECATION_WARNINGS
1571 ctx->init_encode_params.frameRateDen = avctx->time_base.num
1572#if FF_API_TICKS_PER_FRAME
1573 * avctx->ticks_per_frame
1574#endif
1575 ;
1576FF_ENABLE_DEPRECATION_WARNINGS
Zachariah Brownb18fd2b2020-05-14 18:15:331577 }
Timo Rothenpieler2a428db2014-11-29 23:04:371578
Timo Rothenpieler2a428db2014-11-29 23:04:371579 ctx->init_encode_params.enableEncodeAsync = 0;
1580 ctx->init_encode_params.enablePTD = 1;
1581
Roman Arzumanyan9115d772020-03-19 08:35:291582#ifdef NVENC_HAVE_NEW_PRESETS
1583 /* If lookahead isn't set from CLI, use value from preset.
1584 * P6 & P7 presets may enable lookahead for better quality.
1585 * */
1586 if (ctx->rc_lookahead == 0 && ctx->encode_config.rcParams.enableLookahead)
1587 ctx->rc_lookahead = ctx->encode_config.rcParams.lookaheadDepth;
Roman Arzumanyan9115d772020-03-19 08:35:291588#endif
1589
Sumit Agarwal01775732017-05-09 14:24:541590 if (ctx->weighted_pred == 1)
1591 ctx->init_encode_params.enableWeightedPrediction = 1;
1592
Miroslav Slugen9b425bd2016-12-30 21:04:311593 if (ctx->bluray_compat) {
1594 ctx->aud = 1;
Timo Rothenpielere929b2f2019-09-27 15:55:231595 ctx->dpb_size = FFMIN(FFMAX(avctx->refs, 0), 6);
Miroslav Slugen9b425bd2016-12-30 21:04:311596 avctx->max_b_frames = FFMIN(avctx->max_b_frames, 3);
1597 switch (avctx->codec->id) {
1598 case AV_CODEC_ID_H264:
1599 /* maximum level depends on used resolution */
1600 break;
1601 case AV_CODEC_ID_HEVC:
1602 ctx->level = NV_ENC_LEVEL_HEVC_51;
1603 ctx->tier = NV_ENC_TIER_HEVC_HIGH;
1604 break;
1605 }
1606 }
1607
Timo Rothenpieler914fd422015-01-26 12:28:211608 if (avctx->gop_size > 0) {
Ricardo Monteiro99dfdb42023-06-22 10:18:191609 // only overwrite preset if a GOP size was selected as input
Timo Rothenpieler2a428db2014-11-29 23:04:371610 ctx->encode_config.gopLength = avctx->gop_size;
Timo Rothenpieler914fd422015-01-26 12:28:211611 } else if (avctx->gop_size == 0) {
1612 ctx->encode_config.frameIntervalP = 0;
1613 ctx->encode_config.gopLength = 1;
Timo Rothenpieler2a428db2014-11-29 23:04:371614 }
1615
Ricardo Monteiro99dfdb42023-06-22 10:18:191616 if (avctx->max_b_frames >= 0 && ctx->encode_config.gopLength > 1) {
1617 /* 0 is intra-only, 1 is I/P only, 2 is one B-Frame, 3 two B-frames, and so on. */
1618 ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1;
1619 }
1620
Limin Wang37565252021-09-02 10:38:571621 /* force to enable intra refresh */
1622 if(ctx->single_slice_intra_refresh)
1623 ctx->intra_refresh = 1;
1624
Miroslav Slugeňde2faec2016-11-21 11:17:431625 nvenc_recalc_surfaces(avctx);
1626
Andrey Turkinfaffff82016-05-25 14:05:501627 nvenc_setup_rate_control(avctx);
Timo Rothenpieler2a428db2014-11-29 23:04:371628
Vittorio Giovara7c6eb0a2015-06-29 19:59:371629 if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
Timo Rothenpieler2a428db2014-11-29 23:04:371630 ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
1631 } else {
1632 ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
1633 }
1634
Andrey Turkinfaffff82016-05-25 14:05:501635 res = nvenc_setup_codec_config(avctx);
Andrey Turkin82d705e2016-05-20 14:49:241636 if (res)
1637 return res;
Timo Rothenpieler2a428db2014-11-29 23:04:371638
Hendrik Leppkes6fcbf392017-11-11 15:13:241639 res = nvenc_push_context(avctx);
1640 if (res < 0)
1641 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141642
Timo Rothenpieler2a428db2014-11-29 23:04:371643 nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params);
Timo Rothenpieler51a23342019-09-27 16:30:101644 if (nv_status != NV_ENC_SUCCESS) {
1645 nvenc_pop_context(avctx);
1646 return nvenc_print_error(avctx, nv_status, "InitializeEncoder failed");
1647 }
1648
1649#ifdef NVENC_HAVE_CUSTREAM_PTR
1650 if (ctx->cu_context) {
1651 nv_status = p_nvenc->nvEncSetIOCudaStreams(ctx->nvencoder, &ctx->cu_stream, &ctx->cu_stream);
1652 if (nv_status != NV_ENC_SUCCESS) {
1653 nvenc_pop_context(avctx);
1654 return nvenc_print_error(avctx, nv_status, "SetIOCudaStreams failed");
1655 }
1656 }
1657#endif
Ganapathy Kasi43c417a2017-05-31 02:03:141658
Hendrik Leppkes6fcbf392017-11-11 15:13:241659 res = nvenc_pop_context(avctx);
1660 if (res < 0)
1661 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141662
Timo Rothenpieler2a428db2014-11-29 23:04:371663 if (ctx->encode_config.frameIntervalP > 1)
1664 avctx->has_b_frames = 2;
1665
1666 if (ctx->encode_config.rcParams.averageBitRate > 0)
1667 avctx->bit_rate = ctx->encode_config.rcParams.averageBitRate;
1668
James Almer0231df52023-09-04 12:39:071669 cpb_props = ff_encode_add_cpb_side_data(avctx);
Anton Khirnov1520c6f2015-10-03 13:19:101670 if (!cpb_props)
1671 return AVERROR(ENOMEM);
Hendrik Leppkes5fc17ed2015-12-17 12:41:291672 cpb_props->max_bitrate = ctx->encode_config.rcParams.maxBitRate;
Anton Khirnov1520c6f2015-10-03 13:19:101673 cpb_props->avg_bitrate = avctx->bit_rate;
Hendrik Leppkes5fc17ed2015-12-17 12:41:291674 cpb_props->buffer_size = ctx->encode_config.rcParams.vbvBufferSize;
Anton Khirnov1520c6f2015-10-03 13:19:101675
Timo Rothenpieler2a428db2014-11-29 23:04:371676 return 0;
Andrey Turkin82d705e2016-05-20 14:49:241677}
1678
Philip Langdale27038692016-11-25 19:11:451679static NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum AVPixelFormat pix_fmt)
1680{
1681 switch (pix_fmt) {
1682 case AV_PIX_FMT_YUV420P:
1683 return NV_ENC_BUFFER_FORMAT_YV12_PL;
1684 case AV_PIX_FMT_NV12:
1685 return NV_ENC_BUFFER_FORMAT_NV12_PL;
1686 case AV_PIX_FMT_P010:
Philip Langdale6a89cdc2018-02-25 17:08:061687 case AV_PIX_FMT_P016:
Philip Langdale27038692016-11-25 19:11:451688 return NV_ENC_BUFFER_FORMAT_YUV420_10BIT;
Timo Rothenpieler7555d6f2021-03-30 20:08:491689 case AV_PIX_FMT_GBRP:
Philip Langdale27038692016-11-25 19:11:451690 case AV_PIX_FMT_YUV444P:
1691 return NV_ENC_BUFFER_FORMAT_YUV444_PL;
Timo Rothenpieler7555d6f2021-03-30 20:08:491692 case AV_PIX_FMT_GBRP16:
Philip Langdale27038692016-11-25 19:11:451693 case AV_PIX_FMT_YUV444P16:
1694 return NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
1695 case AV_PIX_FMT_0RGB32:
Timo Rothenpieler85bc6b52022-07-04 23:58:101696 case AV_PIX_FMT_RGB32:
Philip Langdale27038692016-11-25 19:11:451697 return NV_ENC_BUFFER_FORMAT_ARGB;
1698 case AV_PIX_FMT_0BGR32:
Timo Rothenpieler85bc6b52022-07-04 23:58:101699 case AV_PIX_FMT_BGR32:
Philip Langdale27038692016-11-25 19:11:451700 return NV_ENC_BUFFER_FORMAT_ABGR;
Timo Rothenpieler85bc6b52022-07-04 23:58:101701 case AV_PIX_FMT_X2RGB10:
1702 return NV_ENC_BUFFER_FORMAT_ARGB10;
1703 case AV_PIX_FMT_X2BGR10:
1704 return NV_ENC_BUFFER_FORMAT_ABGR10;
Philip Langdale27038692016-11-25 19:11:451705 default:
1706 return NV_ENC_BUFFER_FORMAT_UNDEFINED;
1707 }
1708}
1709
Andrey Turkin82d705e2016-05-20 14:49:241710static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
1711{
1712 NvencContext *ctx = avctx->priv_data;
1713 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1714 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
Ben Chang8de34582017-04-25 21:57:561715 NvencSurface* tmp_surface = &ctx->surfaces[idx];
Andrey Turkin82d705e2016-05-20 14:49:241716
1717 NVENCSTATUS nv_status;
Andrey Turkin82d705e2016-05-20 14:49:241718 NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 };
Andrey Turkin82d705e2016-05-20 14:49:241719 allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
1720
Hendrik Leppkesbff6d982017-11-11 15:51:581721 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Andrey Turkina8cf25d2016-05-20 22:08:061722 ctx->surfaces[idx].in_ref = av_frame_alloc();
1723 if (!ctx->surfaces[idx].in_ref)
1724 return AVERROR(ENOMEM);
1725 } else {
1726 NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 };
Philip Langdale27038692016-11-25 19:11:451727
1728 ctx->surfaces[idx].format = nvenc_map_buffer_format(ctx->data_pix_fmt);
1729 if (ctx->surfaces[idx].format == NV_ENC_BUFFER_FORMAT_UNDEFINED) {
1730 av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n",
1731 av_get_pix_fmt_name(ctx->data_pix_fmt));
1732 return AVERROR(EINVAL);
1733 }
1734
Andrey Turkina8cf25d2016-05-20 22:08:061735 allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
Timo Rothenpielera1652ac2017-05-23 09:24:401736 allocSurf.width = avctx->width;
1737 allocSurf.height = avctx->height;
Andrey Turkina8cf25d2016-05-20 22:08:061738 allocSurf.bufferFmt = ctx->surfaces[idx].format;
1739
1740 nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf);
1741 if (nv_status != NV_ENC_SUCCESS) {
1742 return nvenc_print_error(avctx, nv_status, "CreateInputBuffer failed");
1743 }
1744
1745 ctx->surfaces[idx].input_surface = allocSurf.inputBuffer;
1746 ctx->surfaces[idx].width = allocSurf.width;
1747 ctx->surfaces[idx].height = allocSurf.height;
Andrey Turkin82d705e2016-05-20 14:49:241748 }
1749
Andrey Turkin82d705e2016-05-20 14:49:241750 nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut);
1751 if (nv_status != NV_ENC_SUCCESS) {
Andrey Turkine1691c42016-05-20 15:37:001752 int err = nvenc_print_error(avctx, nv_status, "CreateBitstreamBuffer failed");
Hendrik Leppkesbff6d982017-11-11 15:51:581753 if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11)
Andrey Turkina8cf25d2016-05-20 22:08:061754 p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[idx].input_surface);
1755 av_frame_free(&ctx->surfaces[idx].in_ref);
Andrey Turkine1691c42016-05-20 15:37:001756 return err;
Andrey Turkin82d705e2016-05-20 14:49:241757 }
1758
Andrey Turkine1691c42016-05-20 15:37:001759 ctx->surfaces[idx].output_surface = allocOut.bitstreamBuffer;
Andrey Turkin82d705e2016-05-20 14:49:241760
Anton Khirnov587545c2022-01-06 15:59:491761 av_fifo_write(ctx->unused_surface_queue, &tmp_surface, 1);
Ben Chang8de34582017-04-25 21:57:561762
Andrey Turkin82d705e2016-05-20 14:49:241763 return 0;
1764}
1765
Andrey Turkinb6933532016-05-25 16:57:111766static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:241767{
Andrey Turkin82d705e2016-05-20 14:49:241768 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler4e93f002017-11-15 17:33:311769 int i, res = 0, res2;
Andrey Turkin82d705e2016-05-20 14:49:241770
Andreas Rheinhardt1ea36502021-09-14 19:31:531771 ctx->surfaces = av_calloc(ctx->nb_surfaces, sizeof(*ctx->surfaces));
Andrey Turkinf052ef32016-05-29 10:07:341772 if (!ctx->surfaces)
Andrey Turkin82d705e2016-05-20 14:49:241773 return AVERROR(ENOMEM);
Andrey Turkin82d705e2016-05-20 14:49:241774
Timo Rothenpieler16fdb482023-06-16 19:35:451775 ctx->frame_data_array = av_calloc(ctx->frame_data_array_nb, sizeof(*ctx->frame_data_array));
1776 if (!ctx->frame_data_array)
1777 return AVERROR(ENOMEM);
1778
Timo Rothenpieler6c418ae2023-06-16 18:23:261779 ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0);
1780 if (!ctx->timestamp_list)
Andrey Turkincfb49fc2016-05-20 16:13:201781 return AVERROR(ENOMEM);
Ben Chang8de34582017-04-25 21:57:561782
Anton Khirnov587545c2022-01-06 15:59:491783 ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
Ben Chang8de34582017-04-25 21:57:561784 if (!ctx->unused_surface_queue)
1785 return AVERROR(ENOMEM);
1786
Anton Khirnov587545c2022-01-06 15:59:491787 ctx->output_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
Andrey Turkincfb49fc2016-05-20 16:13:201788 if (!ctx->output_surface_queue)
1789 return AVERROR(ENOMEM);
Anton Khirnov587545c2022-01-06 15:59:491790 ctx->output_surface_ready_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
Andrey Turkincfb49fc2016-05-20 16:13:201791 if (!ctx->output_surface_ready_queue)
1792 return AVERROR(ENOMEM);
1793
Hendrik Leppkes6fcbf392017-11-11 15:13:241794 res = nvenc_push_context(avctx);
1795 if (res < 0)
1796 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141797
Andrey Turkinf052ef32016-05-29 10:07:341798 for (i = 0; i < ctx->nb_surfaces; i++) {
Andrey Turkinb6933532016-05-25 16:57:111799 if ((res = nvenc_alloc_surface(avctx, i)) < 0)
Timo Rothenpieler4e93f002017-11-15 17:33:311800 goto fail;
Ganapathy Kasi43c417a2017-05-31 02:03:141801 }
1802
Timo Rothenpieler4e93f002017-11-15 17:33:311803fail:
1804 res2 = nvenc_pop_context(avctx);
1805 if (res2 < 0)
1806 return res2;
Andrey Turkin82d705e2016-05-20 14:49:241807
Timo Rothenpieler4e93f002017-11-15 17:33:311808 return res;
Andrey Turkin82d705e2016-05-20 14:49:241809}
1810
1811static av_cold int nvenc_setup_extradata(AVCodecContext *avctx)
1812{
1813 NvencContext *ctx = avctx->priv_data;
1814 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1815 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
1816
1817 NVENCSTATUS nv_status;
1818 uint32_t outSize = 0;
Timo Rothenpielereb1e3592022-11-15 00:32:561819 char tmpHeader[NV_MAX_SEQ_HDR_LEN];
1820
Andrey Turkin82d705e2016-05-20 14:49:241821 NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 };
1822 payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;
1823
1824 payload.spsppsBuffer = tmpHeader;
1825 payload.inBufferSize = sizeof(tmpHeader);
1826 payload.outSPSPPSPayloadSize = &outSize;
1827
1828 nv_status = p_nvenc->nvEncGetSequenceParams(ctx->nvencoder, &payload);
1829 if (nv_status != NV_ENC_SUCCESS) {
Andrey Turkine1691c42016-05-20 15:37:001830 return nvenc_print_error(avctx, nv_status, "GetSequenceParams failed");
Andrey Turkin82d705e2016-05-20 14:49:241831 }
1832
1833 avctx->extradata_size = outSize;
1834 avctx->extradata = av_mallocz(outSize + AV_INPUT_BUFFER_PADDING_SIZE);
1835
1836 if (!avctx->extradata) {
1837 return AVERROR(ENOMEM);
1838 }
1839
1840 memcpy(avctx->extradata, tmpHeader, outSize);
1841
1842 return 0;
1843}
1844
Andrey Turkin7aa16d52016-05-25 13:04:281845av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
Timo Rothenpieler2a428db2014-11-29 23:04:371846{
Andrey Turkinb6933532016-05-25 16:57:111847 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler2a428db2014-11-29 23:04:371848 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1849 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
Hendrik Leppkes6fcbf392017-11-11 15:13:241850 int i, res;
Timo Rothenpieler2a428db2014-11-29 23:04:371851
Andrey Turkinb6933532016-05-25 16:57:111852 /* the encoder has to be flushed before it can be closed */
1853 if (ctx->nvencoder) {
1854 NV_ENC_PIC_PARAMS params = { .version = NV_ENC_PIC_PARAMS_VER,
1855 .encodePicFlags = NV_ENC_PIC_FLAG_EOS };
1856
Hendrik Leppkes6fcbf392017-11-11 15:13:241857 res = nvenc_push_context(avctx);
1858 if (res < 0)
1859 return res;
Timo Rothenpieler0e995ea2017-08-30 19:12:231860
Andrey Turkinb6933532016-05-25 16:57:111861 p_nvenc->nvEncEncodePicture(ctx->nvencoder, &params);
1862 }
1863
Timo Rothenpieler6c418ae2023-06-16 18:23:261864 av_fifo_freep2(&ctx->timestamp_list);
Anton Khirnov587545c2022-01-06 15:59:491865 av_fifo_freep2(&ctx->output_surface_ready_queue);
1866 av_fifo_freep2(&ctx->output_surface_queue);
1867 av_fifo_freep2(&ctx->unused_surface_queue);
Timo Rothenpieler2a428db2014-11-29 23:04:371868
Timo Rothenpieler16fdb482023-06-16 19:35:451869 if (ctx->frame_data_array) {
1870 for (i = 0; i < ctx->nb_surfaces; i++)
1871 av_buffer_unref(&ctx->frame_data_array[i].frame_opaque_ref);
1872 av_freep(&ctx->frame_data_array);
1873 }
1874
Hendrik Leppkesbff6d982017-11-11 15:51:581875 if (ctx->surfaces && (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11)) {
Andrey Turkina8cf25d2016-05-20 22:08:061876 for (i = 0; i < ctx->nb_registered_frames; i++) {
Timo Rothenpielerbbe1b212018-01-26 19:16:531877 if (ctx->registered_frames[i].mapped)
1878 p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[i].in_map.mappedResource);
Andrey Turkina8cf25d2016-05-20 22:08:061879 if (ctx->registered_frames[i].regptr)
1880 p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr);
1881 }
1882 ctx->nb_registered_frames = 0;
1883 }
1884
Andrey Turkinb6933532016-05-25 16:57:111885 if (ctx->surfaces) {
Andrey Turkinf052ef32016-05-29 10:07:341886 for (i = 0; i < ctx->nb_surfaces; ++i) {
Hendrik Leppkesbff6d982017-11-11 15:51:581887 if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11)
Andrey Turkinb6933532016-05-25 16:57:111888 p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[i].input_surface);
1889 av_frame_free(&ctx->surfaces[i].in_ref);
1890 p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->surfaces[i].output_surface);
1891 }
Timo Rothenpieler2a428db2014-11-29 23:04:371892 }
Andrey Turkincfb49fc2016-05-20 16:13:201893 av_freep(&ctx->surfaces);
Andrey Turkinf052ef32016-05-29 10:07:341894 ctx->nb_surfaces = 0;
Timo Rothenpieler2a428db2014-11-29 23:04:371895
James Almer827d6fe2020-06-09 21:31:321896 av_frame_free(&ctx->frame);
1897
Brad Hards63948a62021-05-25 10:11:571898 av_freep(&ctx->sei_data);
1899
Timo Rothenpieler0e995ea2017-08-30 19:12:231900 if (ctx->nvencoder) {
Andrey Turkinb6933532016-05-25 16:57:111901 p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
Timo Rothenpieler2a428db2014-11-29 23:04:371902
Hendrik Leppkes6fcbf392017-11-11 15:13:241903 res = nvenc_pop_context(avctx);
1904 if (res < 0)
1905 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141906 }
Timo Rothenpieler0e995ea2017-08-30 19:12:231907 ctx->nvencoder = NULL;
Ganapathy Kasi43c417a2017-05-31 02:03:141908
Andrey Turkina8cf25d2016-05-20 22:08:061909 if (ctx->cu_context_internal)
Philip Langdale19d3d0c2018-11-11 06:47:281910 CHECK_CU(dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal));
Andrey Turkina8cf25d2016-05-20 22:08:061911 ctx->cu_context = ctx->cu_context_internal = NULL;
Timo Rothenpieler2a428db2014-11-29 23:04:371912
Hendrik Leppkesbff6d982017-11-11 15:51:581913#if CONFIG_D3D11VA
1914 if (ctx->d3d11_device) {
1915 ID3D11Device_Release(ctx->d3d11_device);
1916 ctx->d3d11_device = NULL;
1917 }
1918#endif
1919
Timo Rothenpielera66835b2016-10-10 10:55:591920 nvenc_free_functions(&dl_fn->nvenc_dl);
1921 cuda_free_functions(&dl_fn->cuda_dl);
Andrey Turkinb6933532016-05-25 16:57:111922
1923 dl_fn->nvenc_device_count = 0;
1924
Andrey Turkinb6933532016-05-25 16:57:111925 av_log(avctx, AV_LOG_VERBOSE, "Nvenc unloaded\n");
1926
1927 return 0;
1928}
1929
1930av_cold int ff_nvenc_encode_init(AVCodecContext *avctx)
1931{
Andrey Turkin0d021cc2016-05-29 12:23:261932 NvencContext *ctx = avctx->priv_data;
1933 int ret;
Andrey Turkinb6933532016-05-25 16:57:111934
Hendrik Leppkesbff6d982017-11-11 15:51:581935 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Timo Rothenpieler2e700b02018-05-07 20:39:201936 AVHWFramesContext *frames_ctx;
1937 if (!avctx->hw_frames_ctx) {
Andrey Turkin0d021cc2016-05-29 12:23:261938 av_log(avctx, AV_LOG_ERROR,
Timo Rothenpieler2e700b02018-05-07 20:39:201939 "hw_frames_ctx must be set when using GPU frames as input\n");
Andrey Turkin0d021cc2016-05-29 12:23:261940 return AVERROR(EINVAL);
1941 }
Timo Rothenpieler2e700b02018-05-07 20:39:201942 frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
1943 if (frames_ctx->format != avctx->pix_fmt) {
1944 av_log(avctx, AV_LOG_ERROR,
1945 "hw_frames_ctx must match the GPU frame type\n");
1946 return AVERROR(EINVAL);
1947 }
1948 ctx->data_pix_fmt = frames_ctx->sw_format;
Andrey Turkin0d021cc2016-05-29 12:23:261949 } else {
1950 ctx->data_pix_fmt = avctx->pix_fmt;
1951 }
Andrey Turkinb6933532016-05-25 16:57:111952
James Almer827d6fe2020-06-09 21:31:321953 ctx->frame = av_frame_alloc();
1954 if (!ctx->frame)
1955 return AVERROR(ENOMEM);
1956
Andrey Turkin0d021cc2016-05-29 12:23:261957 if ((ret = nvenc_load_libraries(avctx)) < 0)
1958 return ret;
Andrey Turkinb6933532016-05-25 16:57:111959
Andrey Turkin0d021cc2016-05-29 12:23:261960 if ((ret = nvenc_setup_device(avctx)) < 0)
1961 return ret;
Andrey Turkinb6933532016-05-25 16:57:111962
Andrey Turkin0d021cc2016-05-29 12:23:261963 if ((ret = nvenc_setup_encoder(avctx)) < 0)
1964 return ret;
Andrey Turkinb6933532016-05-25 16:57:111965
Andrey Turkin0d021cc2016-05-29 12:23:261966 if ((ret = nvenc_setup_surfaces(avctx)) < 0)
1967 return ret;
Andrey Turkinb6933532016-05-25 16:57:111968
1969 if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
Andrey Turkin0d021cc2016-05-29 12:23:261970 if ((ret = nvenc_setup_extradata(avctx)) < 0)
1971 return ret;
Andrey Turkinb6933532016-05-25 16:57:111972 }
Timo Rothenpieler2a428db2014-11-29 23:04:371973
Timo Rothenpieler2a428db2014-11-29 23:04:371974 return 0;
1975}
1976
Andrey Turkine1691c42016-05-20 15:37:001977static NvencSurface *get_free_frame(NvencContext *ctx)
Andrey Turkin82d705e2016-05-20 14:49:241978{
Ben Chang8de34582017-04-25 21:57:561979 NvencSurface *tmp_surf;
Andrey Turkin82d705e2016-05-20 14:49:241980
Anton Khirnov587545c2022-01-06 15:59:491981 if (av_fifo_read(ctx->unused_surface_queue, &tmp_surf, 1) < 0)
Ben Chang8de34582017-04-25 21:57:561982 // queue empty
1983 return NULL;
Andrey Turkin82d705e2016-05-20 14:49:241984
Ben Chang8de34582017-04-25 21:57:561985 return tmp_surf;
Andrey Turkin82d705e2016-05-20 14:49:241986}
1987
Timo Rothenpieler96cba1c2016-09-07 13:49:281988static int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *nv_surface,
1989 NV_ENC_LOCK_INPUT_BUFFER *lock_buffer_params, const AVFrame *frame)
Andrey Turkin82d705e2016-05-20 14:49:241990{
Timo Rothenpieler96cba1c2016-09-07 13:49:281991 int dst_linesize[4] = {
1992 lock_buffer_params->pitch,
1993 lock_buffer_params->pitch,
1994 lock_buffer_params->pitch,
1995 lock_buffer_params->pitch
1996 };
1997 uint8_t *dst_data[4];
1998 int ret;
Andrey Turkin82d705e2016-05-20 14:49:241999
Timo Rothenpieler96cba1c2016-09-07 13:49:282000 if (frame->format == AV_PIX_FMT_YUV420P)
2001 dst_linesize[1] = dst_linesize[2] >>= 1;
Andrey Turkin82d705e2016-05-20 14:49:242002
Timo Rothenpieler96cba1c2016-09-07 13:49:282003 ret = av_image_fill_pointers(dst_data, frame->format, nv_surface->height,
2004 lock_buffer_params->bufferDataPtr, dst_linesize);
2005 if (ret < 0)
2006 return ret;
Andrey Turkin82d705e2016-05-20 14:49:242007
Timo Rothenpieler96cba1c2016-09-07 13:49:282008 if (frame->format == AV_PIX_FMT_YUV420P)
2009 FFSWAP(uint8_t*, dst_data[1], dst_data[2]);
Andrey Turkin82d705e2016-05-20 14:49:242010
Timo Rothenpieler96cba1c2016-09-07 13:49:282011 av_image_copy(dst_data, dst_linesize,
2012 (const uint8_t**)frame->data, frame->linesize, frame->format,
Timo Rothenpieler8ebe1dd2016-09-08 17:08:312013 avctx->width, avctx->height);
Andrey Turkin82d705e2016-05-20 14:49:242014
2015 return 0;
2016}
2017
Andrey Turkina8cf25d2016-05-20 22:08:062018static int nvenc_find_free_reg_resource(AVCodecContext *avctx)
2019{
2020 NvencContext *ctx = avctx->priv_data;
2021 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2022 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
Timo Rothenpieler48e52e42018-01-28 11:51:202023 NVENCSTATUS nv_status;
Andrey Turkina8cf25d2016-05-20 22:08:062024
Timo Rothenpieler23ed1472019-04-24 17:00:252025 int i, first_round;
Andrey Turkina8cf25d2016-05-20 22:08:062026
2027 if (ctx->nb_registered_frames == FF_ARRAY_ELEMS(ctx->registered_frames)) {
Timo Rothenpieler23ed1472019-04-24 17:00:252028 for (first_round = 1; first_round >= 0; first_round--) {
Timo Rothenpieler2e254bb2019-04-24 20:47:242029 for (i = 0; i < ctx->nb_registered_frames; i++) {
2030 if (!ctx->registered_frames[i].mapped) {
2031 if (ctx->registered_frames[i].regptr) {
2032 if (first_round)
2033 continue;
2034 nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr);
2035 if (nv_status != NV_ENC_SUCCESS)
2036 return nvenc_print_error(avctx, nv_status, "Failed unregistering unused input resource");
2037 ctx->registered_frames[i].ptr = NULL;
2038 ctx->registered_frames[i].regptr = NULL;
2039 }
2040 return i;
Andrey Turkina8cf25d2016-05-20 22:08:062041 }
Andrey Turkina8cf25d2016-05-20 22:08:062042 }
2043 }
2044 } else {
2045 return ctx->nb_registered_frames++;
2046 }
2047
2048 av_log(avctx, AV_LOG_ERROR, "Too many registered CUDA frames\n");
2049 return AVERROR(ENOMEM);
2050}
2051
2052static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame)
2053{
2054 NvencContext *ctx = avctx->priv_data;
2055 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2056 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2057
Timo Rothenpieler2e700b02018-05-07 20:39:202058 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frame->hw_frames_ctx->data;
Timo Rothenpieler0b13c342022-01-10 14:41:502059 NV_ENC_REGISTER_RESOURCE reg = { 0 };
Andrey Turkina8cf25d2016-05-20 22:08:062060 int i, idx, ret;
2061
2062 for (i = 0; i < ctx->nb_registered_frames; i++) {
Hendrik Leppkesbff6d982017-11-11 15:51:582063 if (avctx->pix_fmt == AV_PIX_FMT_CUDA && ctx->registered_frames[i].ptr == frame->data[0])
2064 return i;
2065 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])
Andrey Turkina8cf25d2016-05-20 22:08:062066 return i;
2067 }
2068
2069 idx = nvenc_find_free_reg_resource(avctx);
2070 if (idx < 0)
2071 return idx;
2072
2073 reg.version = NV_ENC_REGISTER_RESOURCE_VER;
Timo Rothenpieler2e700b02018-05-07 20:39:202074 reg.width = frames_ctx->width;
2075 reg.height = frames_ctx->height;
Andrey Turkina8cf25d2016-05-20 22:08:062076 reg.pitch = frame->linesize[0];
2077 reg.resourceToRegister = frame->data[0];
2078
Hendrik Leppkesbff6d982017-11-11 15:51:582079 if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
2080 reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR;
2081 }
2082 else if (avctx->pix_fmt == AV_PIX_FMT_D3D11) {
2083 reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX;
2084 reg.subResourceIndex = (intptr_t)frame->data[1];
2085 }
2086
Timo Rothenpieler2e700b02018-05-07 20:39:202087 reg.bufferFormat = nvenc_map_buffer_format(frames_ctx->sw_format);
Philip Langdale27038692016-11-25 19:11:452088 if (reg.bufferFormat == NV_ENC_BUFFER_FORMAT_UNDEFINED) {
2089 av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n",
Timo Rothenpieler2e700b02018-05-07 20:39:202090 av_get_pix_fmt_name(frames_ctx->sw_format));
Philip Langdale27038692016-11-25 19:11:452091 return AVERROR(EINVAL);
2092 }
2093
Andrey Turkina8cf25d2016-05-20 22:08:062094 ret = p_nvenc->nvEncRegisterResource(ctx->nvencoder, &reg);
2095 if (ret != NV_ENC_SUCCESS) {
2096 nvenc_print_error(avctx, ret, "Error registering an input resource");
2097 return AVERROR_UNKNOWN;
2098 }
2099
Hendrik Leppkesbff6d982017-11-11 15:51:582100 ctx->registered_frames[idx].ptr = frame->data[0];
2101 ctx->registered_frames[idx].ptr_index = reg.subResourceIndex;
2102 ctx->registered_frames[idx].regptr = reg.registeredResource;
Andrey Turkina8cf25d2016-05-20 22:08:062103 return idx;
2104}
2105
Andrey Turkin82d705e2016-05-20 14:49:242106static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame,
Andrey Turkine1691c42016-05-20 15:37:002107 NvencSurface *nvenc_frame)
Andrey Turkin82d705e2016-05-20 14:49:242108{
2109 NvencContext *ctx = avctx->priv_data;
2110 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2111 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2112
2113 int res;
2114 NVENCSTATUS nv_status;
Andrey Turkin82d705e2016-05-20 14:49:242115
Hendrik Leppkesbff6d982017-11-11 15:51:582116 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Andrey Turkina8cf25d2016-05-20 22:08:062117 int reg_idx = nvenc_register_frame(avctx, frame);
2118 if (reg_idx < 0) {
Hendrik Leppkesbff6d982017-11-11 15:51:582119 av_log(avctx, AV_LOG_ERROR, "Could not register an input HW frame\n");
Andrey Turkina8cf25d2016-05-20 22:08:062120 return reg_idx;
2121 }
Andrey Turkin82d705e2016-05-20 14:49:242122
Andrey Turkina8cf25d2016-05-20 22:08:062123 res = av_frame_ref(nvenc_frame->in_ref, frame);
2124 if (res < 0)
2125 return res;
2126
Timo Rothenpielerbbe1b212018-01-26 19:16:532127 if (!ctx->registered_frames[reg_idx].mapped) {
2128 ctx->registered_frames[reg_idx].in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER;
2129 ctx->registered_frames[reg_idx].in_map.registeredResource = ctx->registered_frames[reg_idx].regptr;
2130 nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &ctx->registered_frames[reg_idx].in_map);
2131 if (nv_status != NV_ENC_SUCCESS) {
2132 av_frame_unref(nvenc_frame->in_ref);
2133 return nvenc_print_error(avctx, nv_status, "Error mapping an input resource");
2134 }
Andrey Turkina8cf25d2016-05-20 22:08:062135 }
2136
Timo Rothenpielerbbe1b212018-01-26 19:16:532137 ctx->registered_frames[reg_idx].mapped += 1;
2138
Andrey Turkina8cf25d2016-05-20 22:08:062139 nvenc_frame->reg_idx = reg_idx;
Timo Rothenpielerbbe1b212018-01-26 19:16:532140 nvenc_frame->input_surface = ctx->registered_frames[reg_idx].in_map.mappedResource;
2141 nvenc_frame->format = ctx->registered_frames[reg_idx].in_map.mappedBufferFmt;
Timo Rothenpielerfa3ecad2016-09-07 16:15:222142 nvenc_frame->pitch = frame->linesize[0];
Timo Rothenpielerbbe1b212018-01-26 19:16:532143
Andrey Turkina8cf25d2016-05-20 22:08:062144 return 0;
2145 } else {
2146 NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 };
2147
2148 lockBufferParams.version = NV_ENC_LOCK_INPUT_BUFFER_VER;
2149 lockBufferParams.inputBuffer = nvenc_frame->input_surface;
2150
2151 nv_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams);
2152 if (nv_status != NV_ENC_SUCCESS) {
2153 return nvenc_print_error(avctx, nv_status, "Failed locking nvenc input buffer");
2154 }
2155
Timo Rothenpielerfa3ecad2016-09-07 16:15:222156 nvenc_frame->pitch = lockBufferParams.pitch;
Andrey Turkina8cf25d2016-05-20 22:08:062157 res = nvenc_copy_frame(avctx, nvenc_frame, &lockBufferParams, frame);
2158
2159 nv_status = p_nvenc->nvEncUnlockInputBuffer(ctx->nvencoder, nvenc_frame->input_surface);
2160 if (nv_status != NV_ENC_SUCCESS) {
2161 return nvenc_print_error(avctx, nv_status, "Failed unlocking input buffer!");
2162 }
2163
2164 return res;
Andrey Turkin82d705e2016-05-20 14:49:242165 }
Andrey Turkin82d705e2016-05-20 14:49:242166}
2167
2168static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
Roman Arzumanyan5a88e8c2018-03-22 09:30:062169 NV_ENC_PIC_PARAMS *params,
Limin Wang4ef766e2020-06-15 14:08:402170 NV_ENC_SEI_PAYLOAD *sei_data,
2171 int sei_count)
Andrey Turkin82d705e2016-05-20 14:49:242172{
2173 NvencContext *ctx = avctx->priv_data;
2174
2175 switch (avctx->codec->id) {
2176 case AV_CODEC_ID_H264:
Andrey Turkin2f53b5b2016-05-29 12:50:062177 params->codecPicParams.h264PicParams.sliceMode =
2178 ctx->encode_config.encodeCodecConfig.h264Config.sliceMode;
2179 params->codecPicParams.h264PicParams.sliceModeData =
2180 ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData;
Limin Wang4ef766e2020-06-15 14:08:402181 if (sei_count > 0) {
Roman Arzumanyan5a88e8c2018-03-22 09:30:062182 params->codecPicParams.h264PicParams.seiPayloadArray = sei_data;
Limin Wang4ef766e2020-06-15 14:08:402183 params->codecPicParams.h264PicParams.seiPayloadArrayCnt = sei_count;
Roman Arzumanyan5a88e8c2018-03-22 09:30:062184 }
2185
Andrey Turkin82d705e2016-05-20 14:49:242186 break;
Andrey Turkin2f53b5b2016-05-29 12:50:062187 case AV_CODEC_ID_HEVC:
2188 params->codecPicParams.hevcPicParams.sliceMode =
2189 ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode;
2190 params->codecPicParams.hevcPicParams.sliceModeData =
2191 ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData;
Limin Wang4ef766e2020-06-15 14:08:402192 if (sei_count > 0) {
Roman Arzumanyan5a88e8c2018-03-22 09:30:062193 params->codecPicParams.hevcPicParams.seiPayloadArray = sei_data;
Limin Wang4ef766e2020-06-15 14:08:402194 params->codecPicParams.hevcPicParams.seiPayloadArrayCnt = sei_count;
Roman Arzumanyan5a88e8c2018-03-22 09:30:062195 }
2196
Andrey Turkin2f53b5b2016-05-29 12:50:062197 break;
Timo Rothenpieler5c288a42022-11-05 20:17:372198#if CONFIG_AV1_NVENC_ENCODER
2199 case AV_CODEC_ID_AV1:
2200 params->codecPicParams.av1PicParams.numTileColumns =
2201 ctx->encode_config.encodeCodecConfig.av1Config.numTileColumns;
2202 params->codecPicParams.av1PicParams.numTileRows =
2203 ctx->encode_config.encodeCodecConfig.av1Config.numTileRows;
2204 if (sei_count > 0) {
2205 params->codecPicParams.av1PicParams.obuPayloadArray = sei_data;
2206 params->codecPicParams.av1PicParams.obuPayloadArrayCnt = sei_count;
2207 }
2208
2209 break;
2210#endif
Andrey Turkin82d705e2016-05-20 14:49:242211 }
2212}
2213
Timo Rothenpieler6c418ae2023-06-16 18:23:262214static inline void timestamp_queue_enqueue(AVFifo *queue, int64_t timestamp)
Andrey Turkin2f53b5b2016-05-29 12:50:062215{
Timo Rothenpieler6c418ae2023-06-16 18:23:262216 av_fifo_write(queue, &timestamp, 1);
Andrey Turkin2f53b5b2016-05-29 12:50:062217}
2218
Timo Rothenpieler6c418ae2023-06-16 18:23:262219static inline int64_t timestamp_queue_dequeue(AVFifo *queue)
Andrey Turkin2f53b5b2016-05-29 12:50:062220{
Timo Rothenpieler6c418ae2023-06-16 18:23:262221 int64_t timestamp = AV_NOPTS_VALUE;
Anton Khirnov35538092022-07-12 09:25:092222 // The following call might fail if the queue is empty.
Timo Rothenpieler6c418ae2023-06-16 18:23:262223 av_fifo_read(queue, &timestamp, 1);
Anton Khirnov35538092022-07-12 09:25:092224
Timo Rothenpieler6c418ae2023-06-16 18:23:262225 return timestamp;
Andrey Turkin2f53b5b2016-05-29 12:50:062226}
2227
Andrey Turkind3463912016-05-29 12:34:382228static int nvenc_set_timestamp(AVCodecContext *avctx,
2229 NV_ENC_LOCK_BITSTREAM *params,
2230 AVPacket *pkt)
2231{
2232 NvencContext *ctx = avctx->priv_data;
2233
2234 pkt->pts = params->outputTimeStamp;
Timo Rothenpielere5babcc2016-05-31 16:59:352235
Timo Rothenpieleraa3d9822022-11-05 20:20:062236 if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) {
Anton Khirnov7d1d61c2023-05-04 09:50:482237FF_DISABLE_DEPRECATION_WARNINGS
Timo Rothenpieler6c418ae2023-06-16 18:23:262238 pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list) -
Anton Khirnov7d1d61c2023-05-04 09:50:482239#if FF_API_TICKS_PER_FRAME
Timo Rothenpielerac7c2652023-06-14 22:45:442240 FFMAX(avctx->ticks_per_frame, 1) *
Anton Khirnov7d1d61c2023-05-04 09:50:482241#endif
Timo Rothenpielerac7c2652023-06-14 22:45:442242 FFMAX(ctx->encode_config.frameIntervalP - 1, 0);
Anton Khirnov7d1d61c2023-05-04 09:50:482243FF_ENABLE_DEPRECATION_WARNINGS
Timo Rothenpieleraa3d9822022-11-05 20:20:062244 } else {
2245 pkt->dts = pkt->pts;
2246 }
Andrey Turkind3463912016-05-29 12:34:382247
Andrey Turkind3463912016-05-29 12:34:382248 return 0;
2249}
2250
Timo Rothenpieler16fdb482023-06-16 19:35:452251static int nvenc_store_frame_data(AVCodecContext *avctx, NV_ENC_PIC_PARAMS *pic_params, const AVFrame *frame)
2252{
2253 NvencContext *ctx = avctx->priv_data;
2254 int res = 0;
2255
2256 int idx = ctx->frame_data_array_pos;
2257 NvencFrameData *frame_data = &ctx->frame_data_array[idx];
2258
2259 // in case the encoder got reconfigured, there might be leftovers
2260 av_buffer_unref(&frame_data->frame_opaque_ref);
2261
Andreas Rheinhardt2d7c1472023-07-31 09:50:212262 if (frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
Timo Rothenpieler16fdb482023-06-16 19:35:452263 frame_data->frame_opaque_ref = av_buffer_ref(frame->opaque_ref);
2264 if (!frame_data->frame_opaque_ref)
2265 return AVERROR(ENOMEM);
2266 }
2267
2268 frame_data->duration = frame->duration;
2269 frame_data->frame_opaque = frame->opaque;
2270
2271#if FF_API_REORDERED_OPAQUE
2272FF_DISABLE_DEPRECATION_WARNINGS
2273 frame_data->reordered_opaque = frame->reordered_opaque;
2274FF_ENABLE_DEPRECATION_WARNINGS
2275#endif
2276
2277 ctx->frame_data_array_pos = (ctx->frame_data_array_pos + 1) % ctx->frame_data_array_nb;
2278 pic_params->inputDuration = idx;
2279
2280 return res;
2281}
2282
2283static int nvenc_retrieve_frame_data(AVCodecContext *avctx, NV_ENC_LOCK_BITSTREAM *lock_params, AVPacket *pkt)
2284{
2285 NvencContext *ctx = avctx->priv_data;
2286 int res = 0;
2287
2288 int idx = lock_params->outputDuration;
2289 NvencFrameData *frame_data = &ctx->frame_data_array[idx];
2290
2291 pkt->duration = frame_data->duration;
2292
2293#if FF_API_REORDERED_OPAQUE
2294FF_DISABLE_DEPRECATION_WARNINGS
2295 avctx->reordered_opaque = frame_data->reordered_opaque;
2296FF_ENABLE_DEPRECATION_WARNINGS
2297#endif
2298
2299 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
2300 pkt->opaque = frame_data->frame_opaque;
2301 pkt->opaque_ref = frame_data->frame_opaque_ref;
2302 frame_data->frame_opaque_ref = NULL;
2303 }
2304
2305 av_buffer_unref(&frame_data->frame_opaque_ref);
2306
2307 return res;
2308}
2309
Andrey Turkine1691c42016-05-20 15:37:002310static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSurface *tmpoutsurf)
Timo Rothenpieler2a428db2014-11-29 23:04:372311{
2312 NvencContext *ctx = avctx->priv_data;
2313 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2314 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2315
Timo Rothenpieler2a428db2014-11-29 23:04:372316 NV_ENC_LOCK_BITSTREAM lock_params = { 0 };
2317 NVENCSTATUS nv_status;
2318 int res = 0;
2319
Lucas Cooperfd554702016-03-07 23:47:562320 enum AVPictureType pict_type;
2321
Timo Rothenpieler2a428db2014-11-29 23:04:372322 lock_params.version = NV_ENC_LOCK_BITSTREAM_VER;
2323
2324 lock_params.doNotWait = 0;
2325 lock_params.outputBitstream = tmpoutsurf->output_surface;
Timo Rothenpieler2a428db2014-11-29 23:04:372326
2327 nv_status = p_nvenc->nvEncLockBitstream(ctx->nvencoder, &lock_params);
2328 if (nv_status != NV_ENC_SUCCESS) {
Andrey Turkine1691c42016-05-20 15:37:002329 res = nvenc_print_error(avctx, nv_status, "Failed locking bitstream buffer");
Timo Rothenpieler2a428db2014-11-29 23:04:372330 goto error;
2331 }
2332
James Almer238e08b2021-03-12 23:50:012333 res = ff_get_encode_buffer(avctx, pkt, lock_params.bitstreamSizeInBytes, 0);
Timo Rothenpieler4fb6ce22019-11-17 00:27:442334
2335 if (res < 0) {
Timo Rothenpieler2a428db2014-11-29 23:04:372336 p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
2337 goto error;
2338 }
2339
2340 memcpy(pkt->data, lock_params.bitstreamBufferPtr, lock_params.bitstreamSizeInBytes);
2341
2342 nv_status = p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
Timo Rothenpieler48e52e42018-01-28 11:51:202343 if (nv_status != NV_ENC_SUCCESS) {
2344 res = nvenc_print_error(avctx, nv_status, "Failed unlocking bitstream buffer, expect the gates of mordor to open");
2345 goto error;
2346 }
Timo Rothenpieler2a428db2014-11-29 23:04:372347
Andrey Turkina8cf25d2016-05-20 22:08:062348
Hendrik Leppkesbff6d982017-11-11 15:51:582349 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Timo Rothenpielerbbe1b212018-01-26 19:16:532350 ctx->registered_frames[tmpoutsurf->reg_idx].mapped -= 1;
2351 if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped == 0) {
Timo Rothenpieler48e52e42018-01-28 11:51:202352 nv_status = p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].in_map.mappedResource);
2353 if (nv_status != NV_ENC_SUCCESS) {
2354 res = nvenc_print_error(avctx, nv_status, "Failed unmapping input resource");
2355 goto error;
2356 }
Timo Rothenpielerbbe1b212018-01-26 19:16:532357 } else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) {
2358 res = AVERROR_BUG;
2359 goto error;
2360 }
2361
Andrey Turkina8cf25d2016-05-20 22:08:062362 av_frame_unref(tmpoutsurf->in_ref);
Andrey Turkina8cf25d2016-05-20 22:08:062363
2364 tmpoutsurf->input_surface = NULL;
2365 }
2366
Timo Rothenpieler2a428db2014-11-29 23:04:372367 switch (lock_params.pictureType) {
2368 case NV_ENC_PIC_TYPE_IDR:
2369 pkt->flags |= AV_PKT_FLAG_KEY;
2370 case NV_ENC_PIC_TYPE_I:
Lucas Cooperfd554702016-03-07 23:47:562371 pict_type = AV_PICTURE_TYPE_I;
Timo Rothenpieler2a428db2014-11-29 23:04:372372 break;
2373 case NV_ENC_PIC_TYPE_P:
Lucas Cooperfd554702016-03-07 23:47:562374 pict_type = AV_PICTURE_TYPE_P;
Timo Rothenpieler2a428db2014-11-29 23:04:372375 break;
2376 case NV_ENC_PIC_TYPE_B:
Lucas Cooperfd554702016-03-07 23:47:562377 pict_type = AV_PICTURE_TYPE_B;
Timo Rothenpieler2a428db2014-11-29 23:04:372378 break;
2379 case NV_ENC_PIC_TYPE_BI:
Lucas Cooperfd554702016-03-07 23:47:562380 pict_type = AV_PICTURE_TYPE_BI;
Timo Rothenpieler2a428db2014-11-29 23:04:372381 break;
2382 default:
2383 av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered, expect the output to be broken.\n");
2384 av_log(avctx, AV_LOG_ERROR, "Please report this error and include as much information on how to reproduce it as possible.\n");
2385 res = AVERROR_EXTERNAL;
2386 goto error;
Lucas Cooperfd554702016-03-07 23:47:562387 }
2388
Lucas Cooperfd554702016-03-07 23:47:562389 ff_side_data_set_encoder_stats(pkt,
2390 (lock_params.frameAvgQP - 1) * FF_QP2LAMBDA, NULL, 0, pict_type);
Timo Rothenpieler2a428db2014-11-29 23:04:372391
Andrey Turkind3463912016-05-29 12:34:382392 res = nvenc_set_timestamp(avctx, &lock_params, pkt);
2393 if (res < 0)
2394 goto error2;
Timo Rothenpieler2a428db2014-11-29 23:04:372395
Timo Rothenpieler16fdb482023-06-16 19:35:452396 res = nvenc_retrieve_frame_data(avctx, &lock_params, pkt);
2397 if (res < 0)
2398 goto error2;
2399
Timo Rothenpieler2a428db2014-11-29 23:04:372400 return 0;
2401
2402error:
Timo Rothenpieler6c418ae2023-06-16 18:23:262403 timestamp_queue_dequeue(ctx->timestamp_list);
Timo Rothenpieler2a428db2014-11-29 23:04:372404
Andrey Turkind3463912016-05-29 12:34:382405error2:
Timo Rothenpieler2a428db2014-11-29 23:04:372406 return res;
2407}
2408
Andrey Turkin2f53b5b2016-05-29 12:50:062409static int output_ready(AVCodecContext *avctx, int flush)
Andrey Turkincfb49fc2016-05-20 16:13:202410{
Andrey Turkin2f53b5b2016-05-29 12:50:062411 NvencContext *ctx = avctx->priv_data;
Andrey Turkincfb49fc2016-05-20 16:13:202412 int nb_ready, nb_pending;
2413
Anton Khirnov587545c2022-01-06 15:59:492414 nb_ready = av_fifo_can_read(ctx->output_surface_ready_queue);
2415 nb_pending = av_fifo_can_read(ctx->output_surface_queue);
Andrey Turkin2f53b5b2016-05-29 12:50:062416 if (flush)
2417 return nb_ready > 0;
2418 return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth);
Andrey Turkincfb49fc2016-05-20 16:13:202419}
2420
Timo Rothenpieler57de8062021-06-04 16:40:172421static int prepare_sei_data_array(AVCodecContext *avctx, const AVFrame *frame)
2422{
2423 NvencContext *ctx = avctx->priv_data;
2424 int sei_count = 0;
2425 int i, res;
2426
2427 if (ctx->a53_cc && av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC)) {
2428 void *a53_data = NULL;
2429 size_t a53_size = 0;
2430
2431 if (ff_alloc_a53_sei(frame, 0, &a53_data, &a53_size) < 0) {
2432 av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
2433 }
2434
2435 if (a53_data) {
2436 void *tmp = av_fast_realloc(ctx->sei_data,
2437 &ctx->sei_data_size,
2438 (sei_count + 1) * sizeof(*ctx->sei_data));
2439 if (!tmp) {
2440 av_free(a53_data);
2441 res = AVERROR(ENOMEM);
2442 goto error;
2443 } else {
2444 ctx->sei_data = tmp;
2445 ctx->sei_data[sei_count].payloadSize = (uint32_t)a53_size;
Timo Rothenpieler57de8062021-06-04 16:40:172446 ctx->sei_data[sei_count].payload = (uint8_t*)a53_data;
Timo Rothenpieler6362b8c2022-11-05 20:18:362447
2448#if CONFIG_AV1_NVENC_ENCODER
2449 if (avctx->codec->id == AV_CODEC_ID_AV1)
2450 ctx->sei_data[sei_count].payloadType = AV1_METADATA_TYPE_ITUT_T35;
2451 else
2452#endif
2453 ctx->sei_data[sei_count].payloadType = SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35;
2454
Timo Rothenpieler57de8062021-06-04 16:40:172455 sei_count++;
2456 }
2457 }
2458 }
2459
2460 if (ctx->s12m_tc && av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE)) {
2461 void *tc_data = NULL;
2462 size_t tc_size = 0;
2463
2464 if (ff_alloc_timecode_sei(frame, avctx->framerate, 0, &tc_data, &tc_size) < 0) {
2465 av_log(ctx, AV_LOG_ERROR, "Not enough memory for timecode sei, skipping\n");
2466 }
2467
2468 if (tc_data) {
2469 void *tmp = av_fast_realloc(ctx->sei_data,
2470 &ctx->sei_data_size,
2471 (sei_count + 1) * sizeof(*ctx->sei_data));
2472 if (!tmp) {
2473 av_free(tc_data);
2474 res = AVERROR(ENOMEM);
2475 goto error;
2476 } else {
2477 ctx->sei_data = tmp;
2478 ctx->sei_data[sei_count].payloadSize = (uint32_t)tc_size;
Timo Rothenpieler57de8062021-06-04 16:40:172479 ctx->sei_data[sei_count].payload = (uint8_t*)tc_data;
Timo Rothenpieler6362b8c2022-11-05 20:18:362480
2481#if CONFIG_AV1_NVENC_ENCODER
2482 if (avctx->codec->id == AV_CODEC_ID_AV1)
2483 ctx->sei_data[sei_count].payloadType = AV1_METADATA_TYPE_TIMECODE;
2484 else
2485#endif
2486 ctx->sei_data[sei_count].payloadType = SEI_TYPE_TIME_CODE;
2487
Timo Rothenpieler57de8062021-06-04 16:40:172488 sei_count++;
2489 }
2490 }
2491 }
2492
Limin Wang0c8741f2021-12-24 04:32:472493 if (!ctx->udu_sei)
2494 return sei_count;
2495
Timo Rothenpieler57de8062021-06-04 16:40:172496 for (i = 0; i < frame->nb_side_data; i++) {
2497 AVFrameSideData *side_data = frame->side_data[i];
2498 void *tmp;
2499
2500 if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED)
2501 continue;
2502
2503 tmp = av_fast_realloc(ctx->sei_data,
2504 &ctx->sei_data_size,
2505 (sei_count + 1) * sizeof(*ctx->sei_data));
2506 if (!tmp) {
2507 res = AVERROR(ENOMEM);
2508 goto error;
2509 } else {
2510 ctx->sei_data = tmp;
2511 ctx->sei_data[sei_count].payloadSize = side_data->size;
2512 ctx->sei_data[sei_count].payloadType = SEI_TYPE_USER_DATA_UNREGISTERED;
2513 ctx->sei_data[sei_count].payload = av_memdup(side_data->data, side_data->size);
2514
2515 if (!ctx->sei_data[sei_count].payload) {
2516 res = AVERROR(ENOMEM);
2517 goto error;
2518 }
2519
2520 sei_count++;
2521 }
2522 }
2523
2524 return sei_count;
2525
2526error:
2527 for (i = 0; i < sei_count; i++)
2528 av_freep(&(ctx->sei_data[i].payload));
2529
2530 return res;
2531}
2532
Timo Rothenpielerfdbb4b92018-05-03 16:57:402533static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
Miroslav Slugeň952421c2017-02-12 18:53:582534{
2535 NvencContext *ctx = avctx->priv_data;
2536 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
2537 NVENCSTATUS ret;
2538
2539 NV_ENC_RECONFIGURE_PARAMS params = { 0 };
2540 int needs_reconfig = 0;
2541 int needs_encode_config = 0;
pkviet15537512018-05-03 00:15:522542 int reconfig_bitrate = 0, reconfig_dar = 0;
Miroslav Slugeň952421c2017-02-12 18:53:582543 int dw, dh;
2544
2545 params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
2546 params.reInitEncodeParams = ctx->init_encode_params;
2547
2548 compute_dar(avctx, &dw, &dh);
2549 if (dw != ctx->init_encode_params.darWidth || dh != ctx->init_encode_params.darHeight) {
2550 av_log(avctx, AV_LOG_VERBOSE,
2551 "aspect ratio change (DAR): %d:%d -> %d:%d\n",
2552 ctx->init_encode_params.darWidth,
2553 ctx->init_encode_params.darHeight, dw, dh);
2554
2555 params.reInitEncodeParams.darHeight = dh;
2556 params.reInitEncodeParams.darWidth = dw;
2557
2558 needs_reconfig = 1;
pkviet15537512018-05-03 00:15:522559 reconfig_dar = 1;
2560 }
2561
2562 if (ctx->rc != NV_ENC_PARAMS_RC_CONSTQP && ctx->support_dyn_bitrate) {
2563 if (avctx->bit_rate > 0 && params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate != avctx->bit_rate) {
2564 av_log(avctx, AV_LOG_VERBOSE,
2565 "avg bitrate change: %d -> %d\n",
2566 params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate,
2567 (uint32_t)avctx->bit_rate);
2568
2569 params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate = avctx->bit_rate;
2570 reconfig_bitrate = 1;
2571 }
2572
2573 if (avctx->rc_max_rate > 0 && ctx->encode_config.rcParams.maxBitRate != avctx->rc_max_rate) {
2574 av_log(avctx, AV_LOG_VERBOSE,
2575 "max bitrate change: %d -> %d\n",
2576 params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate,
2577 (uint32_t)avctx->rc_max_rate);
2578
2579 params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate = avctx->rc_max_rate;
2580 reconfig_bitrate = 1;
2581 }
2582
2583 if (avctx->rc_buffer_size > 0 && ctx->encode_config.rcParams.vbvBufferSize != avctx->rc_buffer_size) {
2584 av_log(avctx, AV_LOG_VERBOSE,
2585 "vbv buffer size change: %d -> %d\n",
2586 params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize,
2587 avctx->rc_buffer_size);
2588
2589 params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize = avctx->rc_buffer_size;
2590 reconfig_bitrate = 1;
2591 }
2592
2593 if (reconfig_bitrate) {
2594 params.resetEncoder = 1;
2595 params.forceIDR = 1;
2596
2597 needs_encode_config = 1;
2598 needs_reconfig = 1;
2599 }
Miroslav Slugeň952421c2017-02-12 18:53:582600 }
2601
2602 if (!needs_encode_config)
2603 params.reInitEncodeParams.encodeConfig = NULL;
2604
2605 if (needs_reconfig) {
2606 ret = p_nvenc->nvEncReconfigureEncoder(ctx->nvencoder, &params);
2607 if (ret != NV_ENC_SUCCESS) {
2608 nvenc_print_error(avctx, ret, "failed to reconfigure nvenc");
2609 } else {
pkviet15537512018-05-03 00:15:522610 if (reconfig_dar) {
2611 ctx->init_encode_params.darHeight = dh;
2612 ctx->init_encode_params.darWidth = dw;
2613 }
2614
2615 if (reconfig_bitrate) {
2616 ctx->encode_config.rcParams.averageBitRate = params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate;
2617 ctx->encode_config.rcParams.maxBitRate = params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate;
2618 ctx->encode_config.rcParams.vbvBufferSize = params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize;
2619 }
2620
Miroslav Slugeň952421c2017-02-12 18:53:582621 }
2622 }
Miroslav Slugeň952421c2017-02-12 18:53:582623}
2624
James Almer827d6fe2020-06-09 21:31:322625static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Timo Rothenpieler2a428db2014-11-29 23:04:372626{
2627 NVENCSTATUS nv_status;
Timo Rothenpielerd0961d32017-09-02 17:42:132628 NvencSurface *tmp_out_surf, *in_surf;
Hendrik Leppkes6fcbf392017-11-11 15:13:242629 int res, res2;
Limin Wang4ef766e2020-06-15 14:08:402630 int sei_count = 0;
2631 int i;
Timo Rothenpieler2a428db2014-11-29 23:04:372632
2633 NvencContext *ctx = avctx->priv_data;
2634 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2635 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2636
2637 NV_ENC_PIC_PARAMS pic_params = { 0 };
2638 pic_params.version = NV_ENC_PIC_PARAMS_VER;
2639
Hendrik Leppkesbff6d982017-11-11 15:51:582640 if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
Timo Rothenpielera56d0492017-09-02 17:30:212641 return AVERROR(EINVAL);
2642
James Almer827d6fe2020-06-09 21:31:322643 if (frame && frame->buf[0]) {
Timo Rothenpielerd0961d32017-09-02 17:42:132644 in_surf = get_free_frame(ctx);
2645 if (!in_surf)
Timo Rothenpielera56d0492017-09-02 17:30:212646 return AVERROR(EAGAIN);
Timo Rothenpieler2a428db2014-11-29 23:04:372647
Hendrik Leppkes6fcbf392017-11-11 15:13:242648 res = nvenc_push_context(avctx);
2649 if (res < 0)
2650 return res;
Timo Rothenpielerbe74ba62017-02-13 21:59:462651
Timo Rothenpielerfdbb4b92018-05-03 16:57:402652 reconfig_encoder(avctx, frame);
2653
Timo Rothenpielerd0961d32017-09-02 17:42:132654 res = nvenc_upload_frame(avctx, frame, in_surf);
Timo Rothenpielerbe74ba62017-02-13 21:59:462655
Hendrik Leppkes6fcbf392017-11-11 15:13:242656 res2 = nvenc_pop_context(avctx);
2657 if (res2 < 0)
2658 return res2;
Timo Rothenpielerbe74ba62017-02-13 21:59:462659
Timo Rothenpielera56d0492017-09-02 17:30:212660 if (res)
Andrey Turkin82d705e2016-05-20 14:49:242661 return res;
Timo Rothenpieler2a428db2014-11-29 23:04:372662
Timo Rothenpielerd0961d32017-09-02 17:42:132663 pic_params.inputBuffer = in_surf->input_surface;
2664 pic_params.bufferFmt = in_surf->format;
2665 pic_params.inputWidth = in_surf->width;
2666 pic_params.inputHeight = in_surf->height;
2667 pic_params.inputPitch = in_surf->pitch;
2668 pic_params.outputBitstream = in_surf->output_surface;
Timo Rothenpieler2a428db2014-11-29 23:04:372669
Michael Niedermayer94d68a42015-07-27 19:14:312670 if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
James Almer2f561ba2023-04-11 18:02:142671 if (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)
Timo Rothenpieler2a428db2014-11-29 23:04:372672 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM;
Andrey Turkin2f53b5b2016-05-29 12:50:062673 else
Timo Rothenpieler2a428db2014-11-29 23:04:372674 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP;
Timo Rothenpieler2a428db2014-11-29 23:04:372675 } else {
2676 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
2677 }
2678
Timo Rothenpieler30c55872016-10-12 18:51:432679 if (ctx->forced_idr >= 0 && frame->pict_type == AV_PICTURE_TYPE_I) {
2680 pic_params.encodePicFlags =
2681 ctx->forced_idr ? NV_ENC_PIC_FLAG_FORCEIDR : NV_ENC_PIC_FLAG_FORCEINTRA;
2682 } else {
2683 pic_params.encodePicFlags = 0;
2684 }
2685
Timo Rothenpieler2a428db2014-11-29 23:04:372686 pic_params.inputTimeStamp = frame->pts;
Andrey Turkin82d705e2016-05-20 14:49:242687
Timo Rothenpieler8bcce562021-06-06 19:53:532688 if (ctx->extra_sei) {
2689 res = prepare_sei_data_array(avctx, frame);
2690 if (res < 0)
2691 return res;
2692 sei_count = res;
2693 }
Brad Hardscee9f962021-06-04 14:06:382694
Timo Rothenpieler16fdb482023-06-16 19:35:452695 res = nvenc_store_frame_data(avctx, &pic_params, frame);
2696 if (res < 0)
2697 return res;
2698
Brad Hards63948a62021-05-25 10:11:572699 nvenc_codec_specific_pic_params(avctx, &pic_params, ctx->sei_data, sei_count);
Timo Rothenpieler2a428db2014-11-29 23:04:372700 } else {
2701 pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
Timo Rothenpieler2a428db2014-11-29 23:04:372702 }
2703
Hendrik Leppkes6fcbf392017-11-11 15:13:242704 res = nvenc_push_context(avctx);
2705 if (res < 0)
Timo Rothenpieler6c418ae2023-06-16 18:23:262706 return res;
Timo Rothenpielerbe74ba62017-02-13 21:59:462707
Timo Rothenpieler2a428db2014-11-29 23:04:372708 nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
Limin Wang4ef766e2020-06-15 14:08:402709
Brad Hards63948a62021-05-25 10:11:572710 for (i = 0; i < sei_count; i++)
2711 av_freep(&(ctx->sei_data[i].payload));
Timo Rothenpielerbe74ba62017-02-13 21:59:462712
Hendrik Leppkes6fcbf392017-11-11 15:13:242713 res = nvenc_pop_context(avctx);
2714 if (res < 0)
Timo Rothenpieler6c418ae2023-06-16 18:23:262715 return res;
Timo Rothenpielerbe74ba62017-02-13 21:59:462716
Andrey Turkin2f53b5b2016-05-29 12:50:062717 if (nv_status != NV_ENC_SUCCESS &&
Timo Rothenpieler6c418ae2023-06-16 18:23:262718 nv_status != NV_ENC_ERR_NEED_MORE_INPUT)
2719 return nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
Timo Rothenpieler2a428db2014-11-29 23:04:372720
James Almer827d6fe2020-06-09 21:31:322721 if (frame && frame->buf[0]) {
Anton Khirnov587545c2022-01-06 15:59:492722 av_fifo_write(ctx->output_surface_queue, &in_surf, 1);
Timo Rothenpieler6c418ae2023-06-16 18:23:262723
2724 if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER)
2725 timestamp_queue_enqueue(ctx->timestamp_list, frame->pts);
Andrey Turkin58c6dcb2016-05-29 12:51:362726 }
Timo Rothenpieler2a428db2014-11-29 23:04:372727
Andrey Turkin2f53b5b2016-05-29 12:50:062728 /* all the pending buffers are now ready for output */
2729 if (nv_status == NV_ENC_SUCCESS) {
Anton Khirnov587545c2022-01-06 15:59:492730 while (av_fifo_read(ctx->output_surface_queue, &tmp_out_surf, 1) >= 0)
2731 av_fifo_write(ctx->output_surface_ready_queue, &tmp_out_surf, 1);
Timo Rothenpieler2a428db2014-11-29 23:04:372732 }
2733
Timo Rothenpielera56d0492017-09-02 17:30:212734 return 0;
2735}
2736
2737int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
2738{
Timo Rothenpielerd0961d32017-09-02 17:42:132739 NvencSurface *tmp_out_surf;
Hendrik Leppkes6fcbf392017-11-11 15:13:242740 int res, res2;
Timo Rothenpielera56d0492017-09-02 17:30:212741
2742 NvencContext *ctx = avctx->priv_data;
Timo Rothenpielera56d0492017-09-02 17:30:212743
James Almer827d6fe2020-06-09 21:31:322744 AVFrame *frame = ctx->frame;
2745
Hendrik Leppkesbff6d982017-11-11 15:51:582746 if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
Timo Rothenpielera56d0492017-09-02 17:30:212747 return AVERROR(EINVAL);
2748
James Almer827d6fe2020-06-09 21:31:322749 if (!frame->buf[0]) {
2750 res = ff_encode_get_frame(avctx, frame);
2751 if (res < 0 && res != AVERROR_EOF)
2752 return res;
2753 }
2754
2755 res = nvenc_send_frame(avctx, frame);
2756 if (res < 0) {
2757 if (res != AVERROR(EAGAIN))
2758 return res;
2759 } else
2760 av_frame_unref(frame);
2761
2762 if (output_ready(avctx, avctx->internal->draining)) {
Anton Khirnov587545c2022-01-06 15:59:492763 av_fifo_read(ctx->output_surface_ready_queue, &tmp_out_surf, 1);
Timo Rothenpieler2a428db2014-11-29 23:04:372764
Hendrik Leppkes6fcbf392017-11-11 15:13:242765 res = nvenc_push_context(avctx);
2766 if (res < 0)
2767 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:142768
Timo Rothenpielerd0961d32017-09-02 17:42:132769 res = process_output_surface(avctx, pkt, tmp_out_surf);
Timo Rothenpieler2a428db2014-11-29 23:04:372770
Hendrik Leppkes6fcbf392017-11-11 15:13:242771 res2 = nvenc_pop_context(avctx);
2772 if (res2 < 0)
2773 return res2;
Ganapathy Kasi43c417a2017-05-31 02:03:142774
Timo Rothenpieler2a428db2014-11-29 23:04:372775 if (res)
2776 return res;
2777
Anton Khirnov587545c2022-01-06 15:59:492778 av_fifo_write(ctx->unused_surface_queue, &tmp_out_surf, 1);
James Almer827d6fe2020-06-09 21:31:322779 } else if (avctx->internal->draining) {
Timo Rothenpielera56d0492017-09-02 17:30:212780 return AVERROR_EOF;
Timo Rothenpieler2a428db2014-11-29 23:04:372781 } else {
Timo Rothenpielera56d0492017-09-02 17:30:212782 return AVERROR(EAGAIN);
2783 }
2784
2785 return 0;
2786}
2787
Philip Langdale3ea70572019-12-20 23:34:332788av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx)
2789{
James Almer827d6fe2020-06-09 21:31:322790 NvencContext *ctx = avctx->priv_data;
2791
2792 nvenc_send_frame(avctx, NULL);
Timo Rothenpieler6c418ae2023-06-16 18:23:262793 av_fifo_reset2(ctx->timestamp_list);
Philip Langdale3ea70572019-12-20 23:34:332794}