blob: ab42dc9690f47c05a8f793134311bc33e191e48e [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
Anton Khirnov35538092022-07-12 09:25:0931#include "libavutil/buffer.h"
Timo Rothenpielera66835b2016-10-10 10:55:5932#include "libavutil/hwcontext_cuda.h"
Andrey Turkin0d021cc2016-05-29 12:23:2633#include "libavutil/hwcontext.h"
Philip Langdale19d3d0c2018-11-11 06:47:2834#include "libavutil/cuda_check.h"
Timo Rothenpieler2a428db2014-11-29 23:04:3735#include "libavutil/imgutils.h"
Timo Rothenpieler2a428db2014-11-29 23:04:3736#include "libavutil/mem.h"
Philip Langdale27038692016-11-25 19:11:4537#include "libavutil/pixdesc.h"
Timo Rothenpielere7fbdda2022-11-10 12:05:5938#include "libavutil/mathematics.h"
James Almer0de01da2020-08-09 17:01:1639#include "atsc_a53.h"
James Almer827d6fe2020-06-09 21:31:3240#include "encode.h"
Timo Rothenpieler2a428db2014-11-29 23:04:3741#include "internal.h"
James Almer6e190392020-06-02 21:38:3342#include "packet_internal.h"
Andrey Turkina8cf25d2016-05-20 22:08:0643
Philip Langdale19d3d0c2018-11-11 06:47:2844#define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x)
45
Andrey Turkin0d021cc2016-05-29 12:23:2646#define NVENC_CAP 0x30
Timo Rothenpielercfbebe92017-05-09 11:57:3947#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR || \
48 rc == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || \
49 rc == NV_ENC_PARAMS_RC_CBR_HQ)
Andrey Turkinf84dfbc2016-05-25 16:39:5450
Andrey Turkin7aa16d52016-05-25 13:04:2851const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
52 AV_PIX_FMT_YUV420P,
53 AV_PIX_FMT_NV12,
Oliver Collyerd1bf8a32016-08-25 15:18:0354 AV_PIX_FMT_P010,
Andrey Turkin7aa16d52016-05-25 13:04:2855 AV_PIX_FMT_YUV444P,
Philip Langdale6a89cdc2018-02-25 17:08:0656 AV_PIX_FMT_P016, // Truncated to 10bits
57 AV_PIX_FMT_YUV444P16, // Truncated to 10bits
Sven C. Dack4aeb7a82016-09-07 13:35:1458 AV_PIX_FMT_0RGB32,
Timo Rothenpieler85bc6b52022-07-04 23:58:1059 AV_PIX_FMT_RGB32,
Sven C. Dack4aeb7a82016-09-07 13:35:1460 AV_PIX_FMT_0BGR32,
Timo Rothenpieler85bc6b52022-07-04 23:58:1061 AV_PIX_FMT_BGR32,
62 AV_PIX_FMT_X2RGB10,
63 AV_PIX_FMT_X2BGR10,
Timo Rothenpieler7555d6f2021-03-30 20:08:4964 AV_PIX_FMT_GBRP,
65 AV_PIX_FMT_GBRP16, // Truncated to 10bits
Andrey Turkin7aa16d52016-05-25 13:04:2866 AV_PIX_FMT_CUDA,
Hendrik Leppkesbff6d982017-11-11 15:51:5867#if CONFIG_D3D11VA
68 AV_PIX_FMT_D3D11,
69#endif
Andrey Turkin7aa16d52016-05-25 13:04:2870 AV_PIX_FMT_NONE
71};
Timo Rothenpieler2a428db2014-11-29 23:04:3772
Mark Thompsoncd322792020-11-08 18:51:1573const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = {
Mark Thompson1dff97b2020-04-13 15:33:1874 HW_CONFIG_ENCODER_FRAMES(CUDA, CUDA),
75 HW_CONFIG_ENCODER_DEVICE(NONE, CUDA),
76#if CONFIG_D3D11VA
77 HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA),
78 HW_CONFIG_ENCODER_DEVICE(NONE, D3D11VA),
79#endif
80 NULL,
81};
82
Timo Rothenpieler7555d6f2021-03-30 20:08:4983#define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \
84 pix_fmt == AV_PIX_FMT_P016 || \
85 pix_fmt == AV_PIX_FMT_YUV444P16 || \
Timo Rothenpielerc7a60122022-11-14 22:10:2086 pix_fmt == AV_PIX_FMT_X2RGB10 || \
87 pix_fmt == AV_PIX_FMT_X2BGR10 || \
Timo Rothenpieler7555d6f2021-03-30 20:08:4988 pix_fmt == AV_PIX_FMT_GBRP16)
Oliver Collyerd1bf8a32016-08-25 15:18:0389
Timo Rothenpieler7555d6f2021-03-30 20:08:4990#define IS_YUV444(pix_fmt) (pix_fmt == AV_PIX_FMT_YUV444P || \
91 pix_fmt == AV_PIX_FMT_YUV444P16 || \
92 pix_fmt == AV_PIX_FMT_GBRP || \
93 pix_fmt == AV_PIX_FMT_GBRP16)
94
95#define IS_GBRP(pix_fmt) (pix_fmt == AV_PIX_FMT_GBRP || \
96 pix_fmt == AV_PIX_FMT_GBRP16)
Oliver Collyerd1bf8a32016-08-25 15:18:0397
Andrey Turkine1691c42016-05-20 15:37:0098static const struct {
99 NVENCSTATUS nverr;
100 int averr;
101 const char *desc;
102} nvenc_errors[] = {
103 { NV_ENC_SUCCESS, 0, "success" },
104 { NV_ENC_ERR_NO_ENCODE_DEVICE, AVERROR(ENOENT), "no encode device" },
105 { NV_ENC_ERR_UNSUPPORTED_DEVICE, AVERROR(ENOSYS), "unsupported device" },
106 { NV_ENC_ERR_INVALID_ENCODERDEVICE, AVERROR(EINVAL), "invalid encoder device" },
107 { NV_ENC_ERR_INVALID_DEVICE, AVERROR(EINVAL), "invalid device" },
108 { NV_ENC_ERR_DEVICE_NOT_EXIST, AVERROR(EIO), "device does not exist" },
109 { NV_ENC_ERR_INVALID_PTR, AVERROR(EFAULT), "invalid ptr" },
110 { NV_ENC_ERR_INVALID_EVENT, AVERROR(EINVAL), "invalid event" },
111 { NV_ENC_ERR_INVALID_PARAM, AVERROR(EINVAL), "invalid param" },
112 { NV_ENC_ERR_INVALID_CALL, AVERROR(EINVAL), "invalid call" },
113 { NV_ENC_ERR_OUT_OF_MEMORY, AVERROR(ENOMEM), "out of memory" },
114 { NV_ENC_ERR_ENCODER_NOT_INITIALIZED, AVERROR(EINVAL), "encoder not initialized" },
115 { NV_ENC_ERR_UNSUPPORTED_PARAM, AVERROR(ENOSYS), "unsupported param" },
116 { NV_ENC_ERR_LOCK_BUSY, AVERROR(EAGAIN), "lock busy" },
James Almerdc482482016-09-24 18:31:00117 { NV_ENC_ERR_NOT_ENOUGH_BUFFER, AVERROR_BUFFER_TOO_SMALL, "not enough buffer"},
Andrey Turkine1691c42016-05-20 15:37:00118 { NV_ENC_ERR_INVALID_VERSION, AVERROR(EINVAL), "invalid version" },
119 { NV_ENC_ERR_MAP_FAILED, AVERROR(EIO), "map failed" },
120 { NV_ENC_ERR_NEED_MORE_INPUT, AVERROR(EAGAIN), "need more input" },
121 { NV_ENC_ERR_ENCODER_BUSY, AVERROR(EAGAIN), "encoder busy" },
122 { NV_ENC_ERR_EVENT_NOT_REGISTERD, AVERROR(EBADF), "event not registered" },
123 { NV_ENC_ERR_GENERIC, AVERROR_UNKNOWN, "generic error" },
124 { NV_ENC_ERR_INCOMPATIBLE_CLIENT_KEY, AVERROR(EINVAL), "incompatible client key" },
125 { NV_ENC_ERR_UNIMPLEMENTED, AVERROR(ENOSYS), "unimplemented" },
126 { NV_ENC_ERR_RESOURCE_REGISTER_FAILED, AVERROR(EIO), "resource register failed" },
127 { NV_ENC_ERR_RESOURCE_NOT_REGISTERED, AVERROR(EBADF), "resource not registered" },
128 { NV_ENC_ERR_RESOURCE_NOT_MAPPED, AVERROR(EBADF), "resource not mapped" },
129};
130
131static int nvenc_map_error(NVENCSTATUS err, const char **desc)
132{
133 int i;
134 for (i = 0; i < FF_ARRAY_ELEMS(nvenc_errors); i++) {
135 if (nvenc_errors[i].nverr == err) {
136 if (desc)
137 *desc = nvenc_errors[i].desc;
138 return nvenc_errors[i].averr;
139 }
140 }
141 if (desc)
142 *desc = "unknown error";
143 return AVERROR_UNKNOWN;
144}
145
Timo Rothenpielerab0ef1a2019-09-27 17:09:11146static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err,
Clément Bœschb7cc4eb2017-03-20 22:04:28147 const char *error_string)
Andrey Turkine1691c42016-05-20 15:37:00148{
149 const char *desc;
Timo Rothenpielerab0ef1a2019-09-27 17:09:11150 const char *details = "(no details)";
151 int ret = nvenc_map_error(err, &desc);
152
153#ifdef NVENC_HAVE_GETLASTERRORSTRING
154 NvencContext *ctx = avctx->priv_data;
155 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
156
157 if (p_nvenc && ctx->nvencoder)
158 details = p_nvenc->nvEncGetLastErrorString(ctx->nvencoder);
159#endif
160
161 av_log(avctx, AV_LOG_ERROR, "%s: %s (%d): %s\n", error_string, desc, err, details);
162
Andrey Turkine1691c42016-05-20 15:37:00163 return ret;
164}
165
Anton Khirnov35538092022-07-12 09:25:09166typedef struct FrameData {
167 int64_t pts;
168 int64_t duration;
169 int64_t reordered_opaque;
170
171 void *frame_opaque;
172 AVBufferRef *frame_opaque_ref;
173} FrameData;
174
175static void reorder_queue_flush(AVFifo *queue)
176{
177 FrameData fd;
178
179 while (av_fifo_read(queue, &fd, 1) >= 0)
180 av_buffer_unref(&fd.frame_opaque_ref);
181}
182
Timo Rothenpieler988f2e92021-04-18 09:17:54183typedef struct GUIDTuple {
184 const GUID guid;
185 int flags;
186} GUIDTuple;
187
188#define PRESET_ALIAS(alias, name, ...) \
189 [PRESET_ ## alias] = { NV_ENC_PRESET_ ## name ## _GUID, __VA_ARGS__ }
190
191#define PRESET(name, ...) PRESET_ALIAS(name, name, __VA_ARGS__)
192
193static void nvenc_map_preset(NvencContext *ctx)
194{
195 GUIDTuple presets[] = {
196#ifdef NVENC_HAVE_NEW_PRESETS
197 PRESET(P1),
198 PRESET(P2),
199 PRESET(P3),
200 PRESET(P4),
201 PRESET(P5),
202 PRESET(P6),
203 PRESET(P7),
204 PRESET_ALIAS(SLOW, P7, NVENC_TWO_PASSES),
205 PRESET_ALIAS(MEDIUM, P4, NVENC_ONE_PASS),
206 PRESET_ALIAS(FAST, P1, NVENC_ONE_PASS),
207 // Compat aliases
208 PRESET_ALIAS(DEFAULT, P4, NVENC_DEPRECATED_PRESET),
209 PRESET_ALIAS(HP, P1, NVENC_DEPRECATED_PRESET),
210 PRESET_ALIAS(HQ, P7, NVENC_DEPRECATED_PRESET),
211 PRESET_ALIAS(BD, P5, NVENC_DEPRECATED_PRESET),
212 PRESET_ALIAS(LOW_LATENCY_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
213 PRESET_ALIAS(LOW_LATENCY_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
214 PRESET_ALIAS(LOW_LATENCY_HQ, P7, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
215 PRESET_ALIAS(LOSSLESS_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
216 PRESET_ALIAS(LOSSLESS_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
217#else
218 PRESET(DEFAULT),
219 PRESET(HP),
220 PRESET(HQ),
221 PRESET(BD),
222 PRESET_ALIAS(SLOW, HQ, NVENC_TWO_PASSES),
223 PRESET_ALIAS(MEDIUM, HQ, NVENC_ONE_PASS),
224 PRESET_ALIAS(FAST, HP, NVENC_ONE_PASS),
225 PRESET(LOW_LATENCY_DEFAULT, NVENC_LOWLATENCY),
226 PRESET(LOW_LATENCY_HP, NVENC_LOWLATENCY),
227 PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY),
228 PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS),
229 PRESET(LOSSLESS_HP, NVENC_LOSSLESS),
230#endif
231 };
232
233 GUIDTuple *t = &presets[ctx->preset];
234
235 ctx->init_encode_params.presetGUID = t->guid;
236 ctx->flags = t->flags;
237
238#ifdef NVENC_HAVE_NEW_PRESETS
239 if (ctx->tuning_info == NV_ENC_TUNING_INFO_LOSSLESS)
240 ctx->flags |= NVENC_LOSSLESS;
241#endif
242}
243
244#undef PRESET
245#undef PRESET_ALIAS
246
Timo Rothenpielercb3358b2017-06-01 09:55:25247static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level)
248{
Timo Rothenpieler5c288a42022-11-05 20:17:37249#if NVENCAPI_CHECK_VERSION(12, 1)
Timo Rothenpieler648f5c92019-09-23 13:47:27250 const char *minver = "(unknown)";
Timo Rothenpieler5c288a42022-11-05 20:17:37251#elif NVENCAPI_CHECK_VERSION(12, 0)
252# if defined(_WIN32) || defined(__CYGWIN__)
253 const char *minver = "522.25";
254# else
255 const char *minver = "520.56.06";
256# endif
Timo Rothenpielerac040852021-08-08 00:00:38257#elif NVENCAPI_CHECK_VERSION(11, 1)
258# if defined(_WIN32) || defined(__CYGWIN__)
259 const char *minver = "471.41";
260# else
261 const char *minver = "470.57.02";
262# endif
Timo Rothenpieler62073cf2020-10-17 21:10:42263#elif NVENCAPI_CHECK_VERSION(11, 0)
264# if defined(_WIN32) || defined(__CYGWIN__)
265 const char *minver = "456.71";
266# else
267 const char *minver = "455.28";
268# endif
Roman Arzumanyan9115d772020-03-19 08:35:29269#elif NVENCAPI_CHECK_VERSION(10, 0)
270# if defined(_WIN32) || defined(__CYGWIN__)
271 const char *minver = "450.51";
272# else
273 const char *minver = "445.87";
274# endif
Timo Rothenpieler648f5c92019-09-23 13:47:27275#elif NVENCAPI_CHECK_VERSION(9, 1)
276# if defined(_WIN32) || defined(__CYGWIN__)
Timo Rothenpieler89cbbe92019-09-24 10:00:00277 const char *minver = "436.15";
Timo Rothenpieler648f5c92019-09-23 13:47:27278# else
279 const char *minver = "435.21";
280# endif
281#elif NVENCAPI_CHECK_VERSION(9, 0)
Timo Rothenpieler1144d5c2019-03-09 23:25:31282# if defined(_WIN32) || defined(__CYGWIN__)
283 const char *minver = "418.81";
284# else
285 const char *minver = "418.30";
286# endif
287#elif NVENCAPI_CHECK_VERSION(8, 2)
288# if defined(_WIN32) || defined(__CYGWIN__)
289 const char *minver = "397.93";
290# else
291 const char *minver = "396.24";
292#endif
293#elif NVENCAPI_CHECK_VERSION(8, 1)
Timo Rothenpieler2108a672018-04-11 12:28:36294# if defined(_WIN32) || defined(__CYGWIN__)
295 const char *minver = "390.77";
296# else
297 const char *minver = "390.25";
298# endif
Timo Rothenpielercb3358b2017-06-01 09:55:25299#else
Timo Rothenpieler2108a672018-04-11 12:28:36300# if defined(_WIN32) || defined(__CYGWIN__)
301 const char *minver = "378.66";
302# else
Timo Rothenpielercb3358b2017-06-01 09:55:25303 const char *minver = "378.13";
Timo Rothenpieler2108a672018-04-11 12:28:36304# endif
Timo Rothenpielercb3358b2017-06-01 09:55:25305#endif
306 av_log(avctx, level, "The minimum required Nvidia driver for nvenc is %s or newer\n", minver);
307}
308
Andrey Turkin0d021cc2016-05-29 12:23:26309static av_cold int nvenc_load_libraries(AVCodecContext *avctx)
Timo Rothenpieler2a428db2014-11-29 23:04:37310{
Clément Bœschb7cc4eb2017-03-20 22:04:28311 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler2a428db2014-11-29 23:04:37312 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Andrey Turkin0d021cc2016-05-29 12:23:26313 NVENCSTATUS err;
Timo Rothenpielerdf615ef2016-08-28 17:46:44314 uint32_t nvenc_max_ver;
Timo Rothenpielera66835b2016-10-10 10:55:59315 int ret;
Timo Rothenpieler2a428db2014-11-29 23:04:37316
Mark Thompson1dc483a2017-11-18 17:16:14317 ret = cuda_load_functions(&dl_fn->cuda_dl, avctx);
Timo Rothenpielera66835b2016-10-10 10:55:59318 if (ret < 0)
319 return ret;
Timo Rothenpieler2a428db2014-11-29 23:04:37320
Mark Thompson1dc483a2017-11-18 17:16:14321 ret = nvenc_load_functions(&dl_fn->nvenc_dl, avctx);
Timo Rothenpielercb3358b2017-06-01 09:55:25322 if (ret < 0) {
323 nvenc_print_driver_requirement(avctx, AV_LOG_ERROR);
Timo Rothenpielera66835b2016-10-10 10:55:59324 return ret;
Timo Rothenpielercb3358b2017-06-01 09:55:25325 }
Timo Rothenpieler2a428db2014-11-29 23:04:37326
Timo Rothenpielera66835b2016-10-10 10:55:59327 err = dl_fn->nvenc_dl->NvEncodeAPIGetMaxSupportedVersion(&nvenc_max_ver);
Timo Rothenpielerdf615ef2016-08-28 17:46:44328 if (err != NV_ENC_SUCCESS)
329 return nvenc_print_error(avctx, err, "Failed to query nvenc max version");
330
331 av_log(avctx, AV_LOG_VERBOSE, "Loaded Nvenc version %d.%d\n", nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
332
333 if ((NVENCAPI_MAJOR_VERSION << 4 | NVENCAPI_MINOR_VERSION) > nvenc_max_ver) {
334 av_log(avctx, AV_LOG_ERROR, "Driver does not support the required nvenc API version. "
335 "Required: %d.%d Found: %d.%d\n",
336 NVENCAPI_MAJOR_VERSION, NVENCAPI_MINOR_VERSION,
337 nvenc_max_ver >> 4, nvenc_max_ver & 0xf);
Timo Rothenpielercb3358b2017-06-01 09:55:25338 nvenc_print_driver_requirement(avctx, AV_LOG_ERROR);
Timo Rothenpielerdf615ef2016-08-28 17:46:44339 return AVERROR(ENOSYS);
340 }
341
Timo Rothenpieler2a428db2014-11-29 23:04:37342 dl_fn->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER;
343
Timo Rothenpielera66835b2016-10-10 10:55:59344 err = dl_fn->nvenc_dl->NvEncodeAPICreateInstance(&dl_fn->nvenc_funcs);
Andrey Turkin0d021cc2016-05-29 12:23:26345 if (err != NV_ENC_SUCCESS)
346 return nvenc_print_error(avctx, err, "Failed to create nvenc instance");
Timo Rothenpieler2a428db2014-11-29 23:04:37347
348 av_log(avctx, AV_LOG_VERBOSE, "Nvenc initialized successfully\n");
349
Andrey Turkin0d021cc2016-05-29 12:23:26350 return 0;
351}
Timo Rothenpieler2a428db2014-11-29 23:04:37352
Hendrik Leppkes6fcbf392017-11-11 15:13:24353static int nvenc_push_context(AVCodecContext *avctx)
354{
355 NvencContext *ctx = avctx->priv_data;
356 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Hendrik Leppkes6fcbf392017-11-11 15:13:24357
Hendrik Leppkesbff6d982017-11-11 15:51:58358 if (ctx->d3d11_device)
359 return 0;
360
Philip Langdale19d3d0c2018-11-11 06:47:28361 return CHECK_CU(dl_fn->cuda_dl->cuCtxPushCurrent(ctx->cu_context));
Hendrik Leppkes6fcbf392017-11-11 15:13:24362}
363
364static int nvenc_pop_context(AVCodecContext *avctx)
365{
366 NvencContext *ctx = avctx->priv_data;
367 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Hendrik Leppkes6fcbf392017-11-11 15:13:24368 CUcontext dummy;
369
Hendrik Leppkesbff6d982017-11-11 15:51:58370 if (ctx->d3d11_device)
371 return 0;
372
Philip Langdale19d3d0c2018-11-11 06:47:28373 return CHECK_CU(dl_fn->cuda_dl->cuCtxPopCurrent(&dummy));
Hendrik Leppkes6fcbf392017-11-11 15:13:24374}
375
Andrey Turkin0d021cc2016-05-29 12:23:26376static av_cold int nvenc_open_session(AVCodecContext *avctx)
377{
378 NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = { 0 };
379 NvencContext *ctx = avctx->priv_data;
380 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
381 NVENCSTATUS ret;
Timo Rothenpieler2a428db2014-11-29 23:04:37382
Andrey Turkin0d021cc2016-05-29 12:23:26383 params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
384 params.apiVersion = NVENCAPI_VERSION;
Hendrik Leppkesbff6d982017-11-11 15:51:58385 if (ctx->d3d11_device) {
386 params.device = ctx->d3d11_device;
387 params.deviceType = NV_ENC_DEVICE_TYPE_DIRECTX;
388 } else {
389 params.device = ctx->cu_context;
390 params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
391 }
Andrey Turkin0d021cc2016-05-29 12:23:26392
393 ret = p_nvenc->nvEncOpenEncodeSessionEx(&params, &ctx->nvencoder);
394 if (ret != NV_ENC_SUCCESS) {
395 ctx->nvencoder = NULL;
396 return nvenc_print_error(avctx, ret, "OpenEncodeSessionEx failed");
397 }
Timo Rothenpieler2a428db2014-11-29 23:04:37398
399 return 0;
400}
401
Andrey Turkin0d021cc2016-05-29 12:23:26402static int nvenc_check_codec_support(AVCodecContext *avctx)
403{
Clément Bœschb7cc4eb2017-03-20 22:04:28404 NvencContext *ctx = avctx->priv_data;
Andrey Turkin0d021cc2016-05-29 12:23:26405 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
406 int i, ret, count = 0;
407 GUID *guids = NULL;
408
409 ret = p_nvenc->nvEncGetEncodeGUIDCount(ctx->nvencoder, &count);
410
411 if (ret != NV_ENC_SUCCESS || !count)
412 return AVERROR(ENOSYS);
413
414 guids = av_malloc(count * sizeof(GUID));
415 if (!guids)
416 return AVERROR(ENOMEM);
417
418 ret = p_nvenc->nvEncGetEncodeGUIDs(ctx->nvencoder, guids, count, &count);
419 if (ret != NV_ENC_SUCCESS) {
420 ret = AVERROR(ENOSYS);
421 goto fail;
422 }
423
424 ret = AVERROR(ENOSYS);
425 for (i = 0; i < count; i++) {
426 if (!memcmp(&guids[i], &ctx->init_encode_params.encodeGUID, sizeof(*guids))) {
427 ret = 0;
428 break;
429 }
430 }
431
432fail:
433 av_free(guids);
434
435 return ret;
436}
437
438static int nvenc_check_cap(AVCodecContext *avctx, NV_ENC_CAPS cap)
439{
440 NvencContext *ctx = avctx->priv_data;
441 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
442 NV_ENC_CAPS_PARAM params = { 0 };
443 int ret, val = 0;
444
445 params.version = NV_ENC_CAPS_PARAM_VER;
446 params.capsToQuery = cap;
447
448 ret = p_nvenc->nvEncGetEncodeCaps(ctx->nvencoder, ctx->init_encode_params.encodeGUID, &params, &val);
449
450 if (ret == NV_ENC_SUCCESS)
451 return val;
452 return 0;
453}
454
455static int nvenc_check_capabilities(AVCodecContext *avctx)
456{
457 NvencContext *ctx = avctx->priv_data;
458 int ret;
459
460 ret = nvenc_check_codec_support(avctx);
461 if (ret < 0) {
hydra3333ba6b20d2019-10-27 02:30:54462 av_log(avctx, AV_LOG_WARNING, "Codec not supported\n");
Andrey Turkin0d021cc2016-05-29 12:23:26463 return ret;
464 }
465
466 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE);
Oliver Collyerd1bf8a32016-08-25 15:18:03467 if (IS_YUV444(ctx->data_pix_fmt) && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54468 av_log(avctx, AV_LOG_WARNING, "YUV444P not supported\n");
Andrey Turkin0d021cc2016-05-29 12:23:26469 return AVERROR(ENOSYS);
470 }
471
472 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
Timo Rothenpieler988f2e92021-04-18 09:17:54473 if (ctx->flags & NVENC_LOSSLESS && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54474 av_log(avctx, AV_LOG_WARNING, "Lossless encoding not supported\n");
Andrey Turkin0d021cc2016-05-29 12:23:26475 return AVERROR(ENOSYS);
476 }
477
478 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_WIDTH_MAX);
479 if (ret < avctx->width) {
hydra3333ba6b20d2019-10-27 02:30:54480 av_log(avctx, AV_LOG_WARNING, "Width %d exceeds %d\n",
Andrey Turkin0d021cc2016-05-29 12:23:26481 avctx->width, ret);
482 return AVERROR(ENOSYS);
483 }
484
485 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_HEIGHT_MAX);
486 if (ret < avctx->height) {
hydra3333ba6b20d2019-10-27 02:30:54487 av_log(avctx, AV_LOG_WARNING, "Height %d exceeds %d\n",
Andrey Turkin0d021cc2016-05-29 12:23:26488 avctx->height, ret);
489 return AVERROR(ENOSYS);
490 }
491
492 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_NUM_MAX_BFRAMES);
493 if (ret < avctx->max_b_frames) {
hydra3333ba6b20d2019-10-27 02:30:54494 av_log(avctx, AV_LOG_WARNING, "Max B-frames %d exceed %d\n",
Andrey Turkin0d021cc2016-05-29 12:23:26495 avctx->max_b_frames, ret);
496
497 return AVERROR(ENOSYS);
498 }
499
Timo Rothenpieler808356c2016-06-06 19:19:29500 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_FIELD_ENCODING);
501 if (ret < 1 && avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
hydra3333ba6b20d2019-10-27 02:30:54502 av_log(avctx, AV_LOG_WARNING,
Timo Rothenpieler808356c2016-06-06 19:19:29503 "Interlaced encoding is not supported. Supported level: %d\n",
504 ret);
505 return AVERROR(ENOSYS);
506 }
507
Oliver Collyerd1bf8a32016-08-25 15:18:03508 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_10BIT_ENCODE);
509 if (IS_10BIT(ctx->data_pix_fmt) && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54510 av_log(avctx, AV_LOG_WARNING, "10 bit encode not supported\n");
Oliver Collyerd1bf8a32016-08-25 15:18:03511 return AVERROR(ENOSYS);
512 }
513
Oliver Collyera81b3982016-08-25 15:20:03514 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOOKAHEAD);
515 if (ctx->rc_lookahead > 0 && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54516 av_log(avctx, AV_LOG_WARNING, "RC lookahead not supported\n");
Oliver Collyera81b3982016-08-25 15:20:03517 return AVERROR(ENOSYS);
518 }
519
Sven C. Dackda4d0fa2016-10-14 15:02:54520 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_AQ);
521 if (ctx->temporal_aq > 0 && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54522 av_log(avctx, AV_LOG_WARNING, "Temporal AQ not supported\n");
Sven C. Dackda4d0fa2016-10-14 15:02:54523 return AVERROR(ENOSYS);
524 }
525
Sumit Agarwal01775732017-05-09 14:24:54526 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_WEIGHTED_PREDICTION);
527 if (ctx->weighted_pred > 0 && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54528 av_log (avctx, AV_LOG_WARNING, "Weighted Prediction not supported\n");
Sumit Agarwal01775732017-05-09 14:24:54529 return AVERROR(ENOSYS);
530 }
531
Timo Rothenpielera0b69e22017-08-30 19:06:25532 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_CABAC);
533 if (ctx->coder == NV_ENC_H264_ENTROPY_CODING_MODE_CABAC && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54534 av_log(avctx, AV_LOG_WARNING, "CABAC entropy coding not supported\n");
Timo Rothenpielera0b69e22017-08-30 19:06:25535 return AVERROR(ENOSYS);
536 }
537
Timo Rothenpieler86e9dba2018-04-11 12:22:20538#ifdef NVENC_HAVE_BFRAME_REF_MODE
539 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE);
Timo Rothenpieler466c14d2020-07-28 19:44:11540 if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1 && ret != 3) {
hydra3333ba6b20d2019-10-27 02:30:54541 av_log(avctx, AV_LOG_WARNING, "Each B frame as reference is not supported\n");
Timo Rothenpieler86e9dba2018-04-11 12:22:20542 return AVERROR(ENOSYS);
543 } else if (ctx->b_ref_mode != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) {
hydra3333ba6b20d2019-10-27 02:30:54544 av_log(avctx, AV_LOG_WARNING, "B frames as references are not supported\n");
Timo Rothenpieler86e9dba2018-04-11 12:22:20545 return AVERROR(ENOSYS);
546 }
547#else
548 if (ctx->b_ref_mode != 0) {
hydra3333ba6b20d2019-10-27 02:30:54549 av_log(avctx, AV_LOG_WARNING, "B frames as references need SDK 8.1 at build time\n");
Timo Rothenpieler86e9dba2018-04-11 12:22:20550 return AVERROR(ENOSYS);
551 }
552#endif
553
Roman Arzumanyan567b5e32019-09-27 15:56:11554#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES
555 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_MULTIPLE_REF_FRAMES);
556 if(avctx->refs != NV_ENC_NUM_REF_FRAMES_AUTOSELECT && ret <= 0) {
hydra3333ba6b20d2019-10-27 02:30:54557 av_log(avctx, AV_LOG_WARNING, "Multiple reference frames are not supported by the device\n");
Roman Arzumanyan567b5e32019-09-27 15:56:11558 return AVERROR(ENOSYS);
559 }
560#else
561 if(avctx->refs != 0) {
hydra3333ba6b20d2019-10-27 02:30:54562 av_log(avctx, AV_LOG_WARNING, "Multiple reference frames need SDK 9.1 at build time\n");
Roman Arzumanyan567b5e32019-09-27 15:56:11563 return AVERROR(ENOSYS);
564 }
565#endif
566
Limin Wang37565252021-09-02 10:38:57567#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH
568 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SINGLE_SLICE_INTRA_REFRESH);
569 if(ctx->single_slice_intra_refresh && ret <= 0) {
570 av_log(avctx, AV_LOG_WARNING, "Single slice intra refresh not supported by the device\n");
571 return AVERROR(ENOSYS);
572 }
573#else
574 if(ctx->single_slice_intra_refresh) {
575 av_log(avctx, AV_LOG_WARNING, "Single slice intra refresh needs SDK 11.1 at build time\n");
576 return AVERROR(ENOSYS);
577 }
578#endif
579
Limin Wange6bd5172021-09-06 02:01:58580 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_INTRA_REFRESH);
Limin Wang37565252021-09-02 10:38:57581 if((ctx->intra_refresh || ctx->single_slice_intra_refresh) && ret <= 0) {
Limin Wange6bd5172021-09-06 02:01:58582 av_log(avctx, AV_LOG_WARNING, "Intra refresh not supported by the device\n");
583 return AVERROR(ENOSYS);
584 }
585
Limin Wang75001ae2021-09-02 10:38:58586#ifndef NVENC_HAVE_HEVC_CONSTRAINED_ENCODING
587 if (ctx->constrained_encoding && avctx->codec->id == AV_CODEC_ID_HEVC) {
588 av_log(avctx, AV_LOG_WARNING, "HEVC constrained encoding needs SDK 10.0 at build time\n");
589 return AVERROR(ENOSYS);
590 }
591#endif
592
593 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_CONSTRAINED_ENCODING);
594 if(ctx->constrained_encoding && ret <= 0) {
595 av_log(avctx, AV_LOG_WARNING, "Constrained encoding not supported by the device\n");
596 return AVERROR(ENOSYS);
597 }
598
pkviet15537512018-05-03 00:15:52599 ctx->support_dyn_bitrate = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE);
600
Andrey Turkin0d021cc2016-05-29 12:23:26601 return 0;
602}
603
604static av_cold int nvenc_check_device(AVCodecContext *avctx, int idx)
605{
606 NvencContext *ctx = avctx->priv_data;
607 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
608 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
609 char name[128] = { 0};
610 int major, minor, ret;
Andrey Turkin0d021cc2016-05-29 12:23:26611 CUdevice cu_device;
Andrey Turkin0d021cc2016-05-29 12:23:26612 int loglevel = AV_LOG_VERBOSE;
613
614 if (ctx->device == LIST_DEVICES)
615 loglevel = AV_LOG_INFO;
616
Philip Langdale19d3d0c2018-11-11 06:47:28617 ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceGet(&cu_device, idx));
618 if (ret < 0)
619 return ret;
Andrey Turkin0d021cc2016-05-29 12:23:26620
Philip Langdale19d3d0c2018-11-11 06:47:28621 ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceGetName(name, sizeof(name), cu_device));
622 if (ret < 0)
623 return ret;
Andrey Turkin0d021cc2016-05-29 12:23:26624
Philip Langdale19d3d0c2018-11-11 06:47:28625 ret = CHECK_CU(dl_fn->cuda_dl->cuDeviceComputeCapability(&major, &minor, cu_device));
626 if (ret < 0)
627 return ret;
Andrey Turkin0d021cc2016-05-29 12:23:26628
629 av_log(avctx, loglevel, "[ GPU #%d - < %s > has Compute SM %d.%d ]\n", idx, name, major, minor);
630 if (((major << 4) | minor) < NVENC_CAP) {
631 av_log(avctx, loglevel, "does not support NVENC\n");
632 goto fail;
633 }
634
Timo Rothenpieler5403d902017-01-18 22:01:28635 if (ctx->device != idx && ctx->device != ANY_DEVICE)
636 return -1;
637
Philip Langdale19d3d0c2018-11-11 06:47:28638 ret = CHECK_CU(dl_fn->cuda_dl->cuCtxCreate(&ctx->cu_context_internal, 0, cu_device));
639 if (ret < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26640 goto fail;
Andrey Turkin0d021cc2016-05-29 12:23:26641
642 ctx->cu_context = ctx->cu_context_internal;
Timo Rothenpieler51a23342019-09-27 16:30:10643 ctx->cu_stream = NULL;
Andrey Turkin0d021cc2016-05-29 12:23:26644
Hendrik Leppkes6fcbf392017-11-11 15:13:24645 if ((ret = nvenc_pop_context(avctx)) < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26646 goto fail2;
Andrey Turkin0d021cc2016-05-29 12:23:26647
648 if ((ret = nvenc_open_session(avctx)) < 0)
649 goto fail2;
650
651 if ((ret = nvenc_check_capabilities(avctx)) < 0)
652 goto fail3;
653
654 av_log(avctx, loglevel, "supports NVENC\n");
655
656 dl_fn->nvenc_device_count++;
657
Timo Rothenpieler5403d902017-01-18 22:01:28658 if (ctx->device == idx || ctx->device == ANY_DEVICE)
Andrey Turkin0d021cc2016-05-29 12:23:26659 return 0;
660
661fail3:
Hendrik Leppkes6fcbf392017-11-11 15:13:24662 if ((ret = nvenc_push_context(avctx)) < 0)
663 return ret;
Ganapathy Kasi43c417a2017-05-31 02:03:14664
Andrey Turkin0d021cc2016-05-29 12:23:26665 p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
666 ctx->nvencoder = NULL;
667
Hendrik Leppkes6fcbf392017-11-11 15:13:24668 if ((ret = nvenc_pop_context(avctx)) < 0)
669 return ret;
Ganapathy Kasi43c417a2017-05-31 02:03:14670
Andrey Turkin0d021cc2016-05-29 12:23:26671fail2:
Philip Langdale19d3d0c2018-11-11 06:47:28672 CHECK_CU(dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal));
Andrey Turkin0d021cc2016-05-29 12:23:26673 ctx->cu_context_internal = NULL;
674
675fail:
676 return AVERROR(ENOSYS);
677}
678
Andrey Turkin82d705e2016-05-20 14:49:24679static av_cold int nvenc_setup_device(AVCodecContext *avctx)
Timo Rothenpieler2a428db2014-11-29 23:04:37680{
Clément Bœschb7cc4eb2017-03-20 22:04:28681 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler2a428db2014-11-29 23:04:37682 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
Timo Rothenpieler2a428db2014-11-29 23:04:37683
Andrey Turkinfaffff82016-05-25 14:05:50684 switch (avctx->codec->id) {
685 case AV_CODEC_ID_H264:
686 ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_H264_GUID;
687 break;
688 case AV_CODEC_ID_HEVC:
689 ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_HEVC_GUID;
690 break;
Timo Rothenpieler5c288a42022-11-05 20:17:37691#if CONFIG_AV1_NVENC_ENCODER
692 case AV_CODEC_ID_AV1:
693 ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_AV1_GUID;
694 break;
695#endif
Andrey Turkinfaffff82016-05-25 14:05:50696 default:
697 return AVERROR_BUG;
698 }
699
Timo Rothenpieler988f2e92021-04-18 09:17:54700 nvenc_map_preset(ctx);
701
702 if (ctx->flags & NVENC_DEPRECATED_PRESET)
703 av_log(avctx, AV_LOG_WARNING, "The selected preset is deprecated. Use p1 to p7 + -tune or fast/medium/slow.\n");
704
Hendrik Leppkesbff6d982017-11-11 15:51:58705 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:26706 AVHWFramesContext *frames_ctx;
Timo Rothenpielerdad6f442017-05-07 11:35:25707 AVHWDeviceContext *hwdev_ctx;
Hendrik Leppkesbff6d982017-11-11 15:51:58708 AVCUDADeviceContext *cuda_device_hwctx = NULL;
709#if CONFIG_D3D11VA
710 AVD3D11VADeviceContext *d3d11_device_hwctx = NULL;
711#endif
Andrey Turkin0d021cc2016-05-29 12:23:26712 int ret;
Andrey Turkina8cf25d2016-05-20 22:08:06713
Timo Rothenpielerdad6f442017-05-07 11:35:25714 if (avctx->hw_frames_ctx) {
715 frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
Hendrik Leppkesbff6d982017-11-11 15:51:58716 if (frames_ctx->format == AV_PIX_FMT_CUDA)
717 cuda_device_hwctx = frames_ctx->device_ctx->hwctx;
718#if CONFIG_D3D11VA
719 else if (frames_ctx->format == AV_PIX_FMT_D3D11)
720 d3d11_device_hwctx = frames_ctx->device_ctx->hwctx;
721#endif
722 else
723 return AVERROR(EINVAL);
Timo Rothenpielerdad6f442017-05-07 11:35:25724 } else if (avctx->hw_device_ctx) {
725 hwdev_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data;
Hendrik Leppkesbff6d982017-11-11 15:51:58726 if (hwdev_ctx->type == AV_HWDEVICE_TYPE_CUDA)
727 cuda_device_hwctx = hwdev_ctx->hwctx;
728#if CONFIG_D3D11VA
729 else if (hwdev_ctx->type == AV_HWDEVICE_TYPE_D3D11VA)
730 d3d11_device_hwctx = hwdev_ctx->hwctx;
731#endif
732 else
733 return AVERROR(EINVAL);
Timo Rothenpielerdad6f442017-05-07 11:35:25734 } else {
Andrey Turkina8cf25d2016-05-20 22:08:06735 return AVERROR(EINVAL);
Timo Rothenpielerdad6f442017-05-07 11:35:25736 }
Andrey Turkin0d021cc2016-05-29 12:23:26737
Hendrik Leppkesbff6d982017-11-11 15:51:58738 if (cuda_device_hwctx) {
739 ctx->cu_context = cuda_device_hwctx->cuda_ctx;
Timo Rothenpieler51a23342019-09-27 16:30:10740 ctx->cu_stream = cuda_device_hwctx->stream;
Hendrik Leppkesbff6d982017-11-11 15:51:58741 }
742#if CONFIG_D3D11VA
743 else if (d3d11_device_hwctx) {
744 ctx->d3d11_device = d3d11_device_hwctx->device;
745 ID3D11Device_AddRef(ctx->d3d11_device);
746 }
747#endif
Andrey Turkin0d021cc2016-05-29 12:23:26748
749 ret = nvenc_open_session(avctx);
750 if (ret < 0)
751 return ret;
752
753 ret = nvenc_check_capabilities(avctx);
754 if (ret < 0) {
755 av_log(avctx, AV_LOG_FATAL, "Provided device doesn't support required NVENC features\n");
756 return ret;
757 }
Andrey Turkin0d021cc2016-05-29 12:23:26758 } else {
759 int i, nb_devices = 0;
760
Philip Langdale19d3d0c2018-11-11 06:47:28761 if (CHECK_CU(dl_fn->cuda_dl->cuInit(0)) < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26762 return AVERROR_UNKNOWN;
Andrey Turkina8cf25d2016-05-20 22:08:06763
Philip Langdale19d3d0c2018-11-11 06:47:28764 if (CHECK_CU(dl_fn->cuda_dl->cuDeviceGetCount(&nb_devices)) < 0)
Andrey Turkin0d021cc2016-05-29 12:23:26765 return AVERROR_UNKNOWN;
Andrey Turkina8cf25d2016-05-20 22:08:06766
Andrey Turkin0d021cc2016-05-29 12:23:26767 if (!nb_devices) {
768 av_log(avctx, AV_LOG_FATAL, "No CUDA capable devices found\n");
769 return AVERROR_EXTERNAL;
770 }
771
772 av_log(avctx, AV_LOG_VERBOSE, "%d CUDA capable devices found\n", nb_devices);
773
774 dl_fn->nvenc_device_count = 0;
775 for (i = 0; i < nb_devices; ++i) {
776 if ((nvenc_check_device(avctx, i)) >= 0 && ctx->device != LIST_DEVICES)
777 return 0;
778 }
779
780 if (ctx->device == LIST_DEVICES)
781 return AVERROR_EXIT;
782
783 if (!dl_fn->nvenc_device_count) {
hydra3333ba6b20d2019-10-27 02:30:54784 av_log(avctx, AV_LOG_FATAL, "No capable devices found\n");
Andrey Turkin0d021cc2016-05-29 12:23:26785 return AVERROR_EXTERNAL;
786 }
787
Timo Rothenpieler5403d902017-01-18 22:01:28788 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:24789 return AVERROR(EINVAL);
Timo Rothenpieler2a428db2014-11-29 23:04:37790 }
791
Andrey Turkin82d705e2016-05-20 14:49:24792 return 0;
793}
794
Andrey Turkin82d705e2016-05-20 14:49:24795static av_cold void set_constqp(AVCodecContext *avctx)
796{
797 NvencContext *ctx = avctx->priv_data;
Andrey Turkinf84dfbc2016-05-25 16:39:54798 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
Timo Rothenpieler5c288a42022-11-05 20:17:37799#if CONFIG_AV1_NVENC_ENCODER
800 int qmax = avctx->codec->id == AV_CODEC_ID_AV1 ? 255 : 51;
801#else
802 int qmax = 51;
803#endif
Andrey Turkin82d705e2016-05-20 14:49:24804
Andrey Turkinf84dfbc2016-05-25 16:39:54805 rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
Konda Raju2db5ab72017-03-17 04:12:25806
807 if (ctx->init_qp_p >= 0) {
808 rc->constQP.qpInterP = ctx->init_qp_p;
809 if (ctx->init_qp_i >= 0 && ctx->init_qp_b >= 0) {
810 rc->constQP.qpIntra = ctx->init_qp_i;
811 rc->constQP.qpInterB = ctx->init_qp_b;
812 } else if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
813 rc->constQP.qpIntra = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37814 rc->constQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
Konda Raju2db5ab72017-03-17 04:12:25815 rc->constQP.qpInterB = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37816 rc->constQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
Konda Raju2db5ab72017-03-17 04:12:25817 } else {
818 rc->constQP.qpIntra = rc->constQP.qpInterP;
819 rc->constQP.qpInterB = rc->constQP.qpInterP;
820 }
Timo Rothenpieler7fb2a7a2017-03-23 16:01:40821 } else if (ctx->cqp >= 0) {
Timo Rothenpielerd84c2292017-03-23 16:10:25822 rc->constQP.qpInterP = rc->constQP.qpInterB = rc->constQP.qpIntra = ctx->cqp;
823 if (avctx->b_quant_factor != 0.0)
Timo Rothenpieler5c288a42022-11-05 20:17:37824 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:25825 if (avctx->i_quant_factor != 0.0)
Timo Rothenpieler5c288a42022-11-05 20:17:37826 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:25827 }
Andrey Turkinf84dfbc2016-05-25 16:39:54828
829 avctx->qmin = -1;
830 avctx->qmax = -1;
Andrey Turkin82d705e2016-05-20 14:49:24831}
832
833static av_cold void set_vbr(AVCodecContext *avctx)
834{
835 NvencContext *ctx = avctx->priv_data;
Andrey Turkinf84dfbc2016-05-25 16:39:54836 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
837 int qp_inter_p;
Timo Rothenpieler5c288a42022-11-05 20:17:37838#if CONFIG_AV1_NVENC_ENCODER
839 int qmax = avctx->codec->id == AV_CODEC_ID_AV1 ? 255 : 51;
840#else
841 int qmax = 51;
842#endif
Andrey Turkin82d705e2016-05-20 14:49:24843
Andrey Turkinf84dfbc2016-05-25 16:39:54844 if (avctx->qmin >= 0 && avctx->qmax >= 0) {
845 rc->enableMinQP = 1;
846 rc->enableMaxQP = 1;
Andrey Turkin82d705e2016-05-20 14:49:24847
Andrey Turkinf84dfbc2016-05-25 16:39:54848 rc->minQP.qpInterB = avctx->qmin;
849 rc->minQP.qpInterP = avctx->qmin;
Clément Bœschb7cc4eb2017-03-20 22:04:28850 rc->minQP.qpIntra = avctx->qmin;
Andrey Turkin82d705e2016-05-20 14:49:24851
Andrey Turkinf84dfbc2016-05-25 16:39:54852 rc->maxQP.qpInterB = avctx->qmax;
853 rc->maxQP.qpInterP = avctx->qmax;
854 rc->maxQP.qpIntra = avctx->qmax;
855
856 qp_inter_p = (avctx->qmax + 3 * avctx->qmin) / 4; // biased towards Qmin
Timo Rothenpieler971351b2016-05-31 15:00:07857 } else if (avctx->qmin >= 0) {
858 rc->enableMinQP = 1;
859
860 rc->minQP.qpInterB = avctx->qmin;
861 rc->minQP.qpInterP = avctx->qmin;
862 rc->minQP.qpIntra = avctx->qmin;
863
864 qp_inter_p = avctx->qmin;
Andrey Turkinf84dfbc2016-05-25 16:39:54865 } else {
866 qp_inter_p = 26; // default to 26
867 }
868
869 rc->enableInitialRCQP = 1;
Andrey Turkinf84dfbc2016-05-25 16:39:54870
Konda Raju5f44a4a2017-02-28 05:39:12871 if (ctx->init_qp_p < 0) {
872 rc->initialRCQP.qpInterP = qp_inter_p;
Andrey Turkinf84dfbc2016-05-25 16:39:54873 } else {
Konda Raju5f44a4a2017-02-28 05:39:12874 rc->initialRCQP.qpInterP = ctx->init_qp_p;
875 }
876
877 if (ctx->init_qp_i < 0) {
878 if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
879 rc->initialRCQP.qpIntra = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37880 rc->initialRCQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
Konda Raju5f44a4a2017-02-28 05:39:12881 } else {
882 rc->initialRCQP.qpIntra = rc->initialRCQP.qpInterP;
883 }
884 } else {
885 rc->initialRCQP.qpIntra = ctx->init_qp_i;
886 }
887
888 if (ctx->init_qp_b < 0) {
889 if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
890 rc->initialRCQP.qpInterB = av_clip(
Timo Rothenpieler5c288a42022-11-05 20:17:37891 rc->initialRCQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
Konda Raju5f44a4a2017-02-28 05:39:12892 } else {
893 rc->initialRCQP.qpInterB = rc->initialRCQP.qpInterP;
894 }
895 } else {
896 rc->initialRCQP.qpInterB = ctx->init_qp_b;
Andrey Turkinf84dfbc2016-05-25 16:39:54897 }
Andrey Turkin82d705e2016-05-20 14:49:24898}
899
900static av_cold void set_lossless(AVCodecContext *avctx)
901{
902 NvencContext *ctx = avctx->priv_data;
Andrey Turkinf84dfbc2016-05-25 16:39:54903 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
Andrey Turkin82d705e2016-05-20 14:49:24904
Andrey Turkinf84dfbc2016-05-25 16:39:54905 rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
906 rc->constQP.qpInterB = 0;
907 rc->constQP.qpInterP = 0;
Clément Bœschb7cc4eb2017-03-20 22:04:28908 rc->constQP.qpIntra = 0;
Andrey Turkinf84dfbc2016-05-25 16:39:54909
910 avctx->qmin = -1;
911 avctx->qmax = -1;
912}
913
914static void nvenc_override_rate_control(AVCodecContext *avctx)
915{
916 NvencContext *ctx = avctx->priv_data;
917 NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
918
919 switch (ctx->rc) {
920 case NV_ENC_PARAMS_RC_CONSTQP:
Andrey Turkinf84dfbc2016-05-25 16:39:54921 set_constqp(avctx);
922 return;
Andrey Turkinf84dfbc2016-05-25 16:39:54923 case NV_ENC_PARAMS_RC_VBR_MINQP:
924 if (avctx->qmin < 0) {
925 av_log(avctx, AV_LOG_WARNING,
926 "The variable bitrate rate-control requires "
927 "the 'qmin' option set.\n");
928 set_vbr(avctx);
929 return;
930 }
Ganapathy Raman Kasia5492432017-02-24 01:42:27931 /* fall through */
Timo Rothenpielercfbebe92017-05-09 11:57:39932 case NV_ENC_PARAMS_RC_VBR_HQ:
Ganapathy Raman Kasia5492432017-02-24 01:42:27933 case NV_ENC_PARAMS_RC_VBR:
Andrey Turkinf84dfbc2016-05-25 16:39:54934 set_vbr(avctx);
935 break;
936 case NV_ENC_PARAMS_RC_CBR:
Timo Rothenpielercfbebe92017-05-09 11:57:39937 case NV_ENC_PARAMS_RC_CBR_HQ:
938 case NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ:
Timo Rothenpielereae4eba2016-05-31 14:55:24939 break;
Andrey Turkinf84dfbc2016-05-25 16:39:54940 }
941
942 rc->rateControlMode = ctx->rc;
Andrey Turkin82d705e2016-05-20 14:49:24943}
944
Miroslav Slugeňde2faec2016-11-21 11:17:43945static av_cold int nvenc_recalc_surfaces(AVCodecContext *avctx)
946{
947 NvencContext *ctx = avctx->priv_data;
Ben Chang8de34582017-04-25 21:57:56948 // default minimum of 4 surfaces
949 // multiply by 2 for number of NVENCs on gpu (hardcode to 2)
950 // another multiply by 2 to avoid blocking next PBB group
951 int nb_surfaces = FFMAX(4, ctx->encode_config.frameIntervalP * 2 * 2);
Miroslav Slugeňde2faec2016-11-21 11:17:43952
Ben Chang8de34582017-04-25 21:57:56953 // lookahead enabled
Miroslav Slugeňde2faec2016-11-21 11:17:43954 if (ctx->rc_lookahead > 0) {
Ben Chang8de34582017-04-25 21:57:56955 // +1 is to account for lkd_bound calculation later
956 // +4 is to allow sufficient pipelining with lookahead
957 nb_surfaces = FFMAX(1, FFMAX(nb_surfaces, ctx->rc_lookahead + ctx->encode_config.frameIntervalP + 1 + 4));
958 if (nb_surfaces > ctx->nb_surfaces && ctx->nb_surfaces > 0)
959 {
Miroslav Slugeňde2faec2016-11-21 11:17:43960 av_log(avctx, AV_LOG_WARNING,
961 "Defined rc_lookahead requires more surfaces, "
962 "increasing used surfaces %d -> %d\n", ctx->nb_surfaces, nb_surfaces);
Miroslav Slugeňde2faec2016-11-21 11:17:43963 }
Ben Chang8de34582017-04-25 21:57:56964 ctx->nb_surfaces = FFMAX(nb_surfaces, ctx->nb_surfaces);
965 } else {
966 if (ctx->encode_config.frameIntervalP > 1 && ctx->nb_surfaces < nb_surfaces && ctx->nb_surfaces > 0)
967 {
968 av_log(avctx, AV_LOG_WARNING,
969 "Defined b-frame requires more surfaces, "
970 "increasing used surfaces %d -> %d\n", ctx->nb_surfaces, nb_surfaces);
971 ctx->nb_surfaces = FFMAX(ctx->nb_surfaces, nb_surfaces);
972 }
973 else if (ctx->nb_surfaces <= 0)
974 ctx->nb_surfaces = nb_surfaces;
975 // otherwise use user specified value
Miroslav Slugeňde2faec2016-11-21 11:17:43976 }
977
978 ctx->nb_surfaces = FFMAX(1, FFMIN(MAX_REGISTERED_FRAMES, ctx->nb_surfaces));
979 ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1);
980
981 return 0;
982}
983
Andrey Turkinfaffff82016-05-25 14:05:50984static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:24985{
986 NvencContext *ctx = avctx->priv_data;
987
Timo Rothenpieler7fb2a7a2017-03-23 16:01:40988 if (avctx->global_quality > 0)
989 av_log(avctx, AV_LOG_WARNING, "Using global_quality with nvenc is deprecated. Use qp instead.\n");
990
991 if (ctx->cqp < 0 && avctx->global_quality > 0)
992 ctx->cqp = avctx->global_quality;
993
Andrey Turkin82d705e2016-05-20 14:49:24994 if (avctx->bit_rate > 0) {
995 ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate;
996 } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
997 ctx->encode_config.rcParams.maxBitRate = ctx->encode_config.rcParams.averageBitRate;
998 }
999
1000 if (avctx->rc_max_rate > 0)
1001 ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
1002
Roman Arzumanyan9115d772020-03-19 08:35:291003#ifdef NVENC_HAVE_MULTIPASS
1004 ctx->encode_config.rcParams.multiPass = ctx->multipass;
Roman Arzumanyan9115d772020-03-19 08:35:291005
Timo Rothenpielere0c8e512020-10-21 16:45:521006 if (ctx->flags & NVENC_ONE_PASS)
1007 ctx->encode_config.rcParams.multiPass = NV_ENC_MULTI_PASS_DISABLED;
Timo Rothenpieler91b8e002020-10-30 16:26:321008 if (ctx->flags & NVENC_TWO_PASSES || ctx->twopass > 0)
Timo Rothenpielere0c8e512020-10-21 16:45:521009 ctx->encode_config.rcParams.multiPass = NV_ENC_TWO_PASS_FULL_RESOLUTION;
1010
1011 if (ctx->rc < 0) {
1012 if (ctx->cbr) {
1013 ctx->rc = NV_ENC_PARAMS_RC_CBR;
1014 } else if (ctx->cqp >= 0) {
1015 ctx->rc = NV_ENC_PARAMS_RC_CONSTQP;
Timo Rothenpielerd5b0a8e2020-10-30 16:21:131016 } else if (ctx->quality >= 0.0f) {
Timo Rothenpielere0c8e512020-10-21 16:45:521017 ctx->rc = NV_ENC_PARAMS_RC_VBR;
1018 }
1019 }
1020#else
Andrey Turkinf84dfbc2016-05-25 16:39:541021 if (ctx->rc < 0) {
1022 if (ctx->flags & NVENC_ONE_PASS)
1023 ctx->twopass = 0;
1024 if (ctx->flags & NVENC_TWO_PASSES)
1025 ctx->twopass = 1;
1026
1027 if (ctx->twopass < 0)
1028 ctx->twopass = (ctx->flags & NVENC_LOWLATENCY) != 0;
1029
1030 if (ctx->cbr) {
1031 if (ctx->twopass) {
Timo Rothenpielercfbebe92017-05-09 11:57:391032 ctx->rc = NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ;
Andrey Turkinf84dfbc2016-05-25 16:39:541033 } else {
1034 ctx->rc = NV_ENC_PARAMS_RC_CBR;
1035 }
Timo Rothenpieler7fb2a7a2017-03-23 16:01:401036 } else if (ctx->cqp >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541037 ctx->rc = NV_ENC_PARAMS_RC_CONSTQP;
1038 } else if (ctx->twopass) {
Timo Rothenpielercfbebe92017-05-09 11:57:391039 ctx->rc = NV_ENC_PARAMS_RC_VBR_HQ;
Andrey Turkinf84dfbc2016-05-25 16:39:541040 } else if (avctx->qmin >= 0 && avctx->qmax >= 0) {
1041 ctx->rc = NV_ENC_PARAMS_RC_VBR_MINQP;
1042 }
1043 }
Timo Rothenpielere0c8e512020-10-21 16:45:521044#endif
Andrey Turkinf84dfbc2016-05-25 16:39:541045
Timo Rothenpielercfbebe92017-05-09 11:57:391046 if (ctx->rc >= 0 && ctx->rc & RC_MODE_DEPRECATED) {
1047 av_log(avctx, AV_LOG_WARNING, "Specified rc mode is deprecated.\n");
Timo Rothenpielercde3c082020-10-21 16:17:081048 av_log(avctx, AV_LOG_WARNING, "Use -rc constqp/cbr/vbr, -tune and -multipass instead.\n");
Timo Rothenpielercfbebe92017-05-09 11:57:391049
1050 ctx->rc &= ~RC_MODE_DEPRECATED;
1051 }
1052
Timo Rothenpieler00b57982021-08-09 13:16:581053#ifdef NVENC_HAVE_QP_CHROMA_OFFSETS
1054 ctx->encode_config.rcParams.cbQPIndexOffset = ctx->qp_cb_offset;
1055 ctx->encode_config.rcParams.crQPIndexOffset = ctx->qp_cr_offset;
1056#else
1057 if (ctx->qp_cb_offset || ctx->qp_cr_offset)
1058 av_log(avctx, AV_LOG_WARNING, "Failed setting QP CB/CR offsets, SDK 11.1 or greater required at compile time.\n");
1059#endif
1060
Roman Arzumanyan9115d772020-03-19 08:35:291061#ifdef NVENC_HAVE_LDKFS
1062 if (ctx->ldkfs)
1063 ctx->encode_config.rcParams.lowDelayKeyFrameScale = ctx->ldkfs;
1064#endif
1065
Andrey Turkinfaffff82016-05-25 14:05:501066 if (ctx->flags & NVENC_LOSSLESS) {
Andrey Turkin82d705e2016-05-20 14:49:241067 set_lossless(avctx);
Timo Rothenpieler1330a0f2016-05-31 14:53:381068 } else if (ctx->rc >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541069 nvenc_override_rate_control(avctx);
Andrey Turkin82d705e2016-05-20 14:49:241070 } else {
Andrey Turkinf84dfbc2016-05-25 16:39:541071 ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
1072 set_vbr(avctx);
Andrey Turkin82d705e2016-05-20 14:49:241073 }
1074
1075 if (avctx->rc_buffer_size > 0) {
1076 ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size;
1077 } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
pkviet15537512018-05-03 00:15:521078 avctx->rc_buffer_size = ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate;
Andrey Turkin82d705e2016-05-20 14:49:241079 }
Oliver Collyera81b3982016-08-25 15:20:031080
Yogender Guptafacc19e2016-09-24 15:55:001081 if (ctx->aq) {
1082 ctx->encode_config.rcParams.enableAQ = 1;
1083 ctx->encode_config.rcParams.aqStrength = ctx->aq_strength;
1084 av_log(avctx, AV_LOG_VERBOSE, "AQ enabled.\n");
Oliver Collyera81b3982016-08-25 15:20:031085 }
Yogender Guptafacc19e2016-09-24 15:55:001086
1087 if (ctx->temporal_aq) {
1088 ctx->encode_config.rcParams.enableTemporalAQ = 1;
1089 av_log(avctx, AV_LOG_VERBOSE, "Temporal AQ enabled.\n");
1090 }
1091
Ruta Gadkari67db4ff2016-12-26 07:49:161092 if (ctx->rc_lookahead > 0) {
Yogender Guptafacc19e2016-09-24 15:55:001093 int lkd_bound = FFMIN(ctx->nb_surfaces, ctx->async_depth) -
1094 ctx->encode_config.frameIntervalP - 4;
1095
1096 if (lkd_bound < 0) {
Timo Rothenpielerac0f42d2022-12-05 20:10:361097 ctx->encode_config.rcParams.enableLookahead = 0;
Yogender Guptafacc19e2016-09-24 15:55:001098 av_log(avctx, AV_LOG_WARNING,
1099 "Lookahead not enabled. Increase buffer delay (-delay).\n");
1100 } else {
1101 ctx->encode_config.rcParams.enableLookahead = 1;
1102 ctx->encode_config.rcParams.lookaheadDepth = av_clip(ctx->rc_lookahead, 0, lkd_bound);
1103 ctx->encode_config.rcParams.disableIadapt = ctx->no_scenecut;
1104 ctx->encode_config.rcParams.disableBadapt = !ctx->b_adapt;
1105 av_log(avctx, AV_LOG_VERBOSE,
1106 "Lookahead enabled: depth %d, scenecut %s, B-adapt %s.\n",
1107 ctx->encode_config.rcParams.lookaheadDepth,
1108 ctx->encode_config.rcParams.disableIadapt ? "disabled" : "enabled",
1109 ctx->encode_config.rcParams.disableBadapt ? "disabled" : "enabled");
Timo Rothenpieler45216e32022-12-05 20:18:421110 if (ctx->encode_config.rcParams.lookaheadDepth < ctx->rc_lookahead)
1111 av_log(avctx, AV_LOG_WARNING, "Clipping lookahead depth to %d (from %d) due to lack of surfaces/delay",
1112 ctx->encode_config.rcParams.lookaheadDepth, ctx->rc_lookahead);
Yogender Guptafacc19e2016-09-24 15:55:001113 }
1114 }
1115
1116 if (ctx->strict_gop) {
1117 ctx->encode_config.rcParams.strictGOPTarget = 1;
1118 av_log(avctx, AV_LOG_VERBOSE, "Strict GOP target enabled.\n");
1119 }
1120
1121 if (ctx->nonref_p)
1122 ctx->encode_config.rcParams.enableNonRefP = 1;
1123
1124 if (ctx->zerolatency)
1125 ctx->encode_config.rcParams.zeroReorderDelay = 1;
1126
Roman Arzumanyan0842fd22020-04-20 10:53:361127 if (ctx->quality) {
Ben Chang18a659d2017-05-10 06:41:171128 //convert from float to fixed point 8.8
1129 int tmp_quality = (int)(ctx->quality * 256.0f);
1130 ctx->encode_config.rcParams.targetQuality = (uint8_t)(tmp_quality >> 8);
1131 ctx->encode_config.rcParams.targetQualityLSB = (uint8_t)(tmp_quality & 0xff);
Roman Arzumanyan0842fd22020-04-20 10:53:361132
1133 av_log(avctx, AV_LOG_VERBOSE, "CQ(%d) mode enabled.\n", tmp_quality);
1134
Timo Rothenpieler9ca139b2022-12-08 11:31:001135 // CQ mode shall discard avg bitrate/vbv buffer size and honor only max bitrate
Roman Arzumanyan470bbf62020-06-03 13:12:121136 ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate = 0;
Timo Rothenpieler9ca139b2022-12-08 11:31:001137 ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size = 0;
Roman Arzumanyan470bbf62020-06-03 13:12:121138 ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
Ben Chang18a659d2017-05-10 06:41:171139 }
Andrey Turkin82d705e2016-05-20 14:49:241140}
1141
Andrey Turkinfaffff82016-05-25 14:05:501142static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:241143{
Andrey Turkinfaffff82016-05-25 14:05:501144 NvencContext *ctx = avctx->priv_data;
1145 NV_ENC_CONFIG *cc = &ctx->encode_config;
1146 NV_ENC_CONFIG_H264 *h264 = &cc->encodeCodecConfig.h264Config;
1147 NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui = &h264->h264VUIParameters;
Andrey Turkin82d705e2016-05-20 14:49:241148
Timo Rothenpielerb71069872022-08-06 18:58:481149 const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(ctx->data_pix_fmt);
1150
1151 if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) && !IS_GBRP(ctx->data_pix_fmt)) {
1152 vui->colourMatrix = AVCOL_SPC_BT470BG;
1153 vui->colourPrimaries = avctx->color_primaries;
1154 vui->transferCharacteristics = avctx->color_trc;
1155 vui->videoFullRangeFlag = 0;
1156 } else {
1157 vui->colourMatrix = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace;
1158 vui->colourPrimaries = avctx->color_primaries;
1159 vui->transferCharacteristics = avctx->color_trc;
1160 vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
1161 || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
1162 }
Andrey Turkin82d705e2016-05-20 14:49:241163
Andrey Turkinfaffff82016-05-25 14:05:501164 vui->colourDescriptionPresentFlag =
Timo Rothenpieler7555d6f2021-03-30 20:08:491165 (vui->colourMatrix != 2 || vui->colourPrimaries != 2 || vui->transferCharacteristics != 2);
Andrey Turkin82d705e2016-05-20 14:49:241166
Andrey Turkinfaffff82016-05-25 14:05:501167 vui->videoSignalTypePresentFlag =
1168 (vui->colourDescriptionPresentFlag
1169 || vui->videoFormat != 5
1170 || vui->videoFullRangeFlag != 0);
Andrey Turkin82d705e2016-05-20 14:49:241171
Andrey Turkinfaffff82016-05-25 14:05:501172 h264->sliceMode = 3;
Limin Wang85489e02021-09-02 10:38:551173 h264->sliceModeData = avctx->slices > 0 ? avctx->slices : 1;
Andrey Turkin82d705e2016-05-20 14:49:241174
Limin Wange6bd5172021-09-06 02:01:581175 if (ctx->intra_refresh) {
1176 h264->enableIntraRefresh = 1;
1177 h264->intraRefreshPeriod = avctx->gop_size;
1178 h264->intraRefreshCnt = avctx->gop_size - 1;
Limin Wang37565252021-09-02 10:38:571179#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH
1180 h264->singleSliceIntraRefresh = ctx->single_slice_intra_refresh;
1181#endif
Limin Wange6bd5172021-09-06 02:01:581182 }
1183
Limin Wang75001ae2021-09-02 10:38:581184 if (ctx->constrained_encoding)
1185 h264->enableConstrainedEncoding = 1;
1186
Andrey Turkinfaffff82016-05-25 14:05:501187 h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
Andrey Turkinf84dfbc2016-05-25 16:39:541188 h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
Miroslav Slugen1841eda2016-12-30 21:02:421189 h264->outputAUD = ctx->aud;
Andrey Turkin82d705e2016-05-20 14:49:241190
Timo Rothenpielere929b2f2019-09-27 15:55:231191 if (ctx->dpb_size >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541192 /* 0 means "let the hardware decide" */
Timo Rothenpielere929b2f2019-09-27 15:55:231193 h264->maxNumRefFrames = ctx->dpb_size;
Andrey Turkinf84dfbc2016-05-25 16:39:541194 }
Limin Wange6bd5172021-09-06 02:01:581195
1196 if (ctx->intra_refresh) {
1197 h264->idrPeriod = NVENC_INFINITE_GOPLENGTH;
1198 } else if (avctx->gop_size >= 0) {
1199 h264->idrPeriod = avctx->gop_size;
Andrey Turkinf84dfbc2016-05-25 16:39:541200 }
1201
1202 if (IS_CBR(cc->rcParams.rateControlMode)) {
1203 h264->outputBufferingPeriodSEI = 1;
Andrey Turkinf84dfbc2016-05-25 16:39:541204 }
1205
Timo Rothenpieler4e6638a2017-09-02 13:39:241206 h264->outputPictureTimingSEI = 1;
1207
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 }
Andrey Turkin82d705e2016-05-20 14:49:241214
Andrey Turkin98243212016-05-25 14:26:251215 if (ctx->flags & NVENC_LOSSLESS) {
1216 h264->qpPrimeYZeroTransformBypassFlag = 1;
1217 } else {
1218 switch(ctx->profile) {
1219 case NV_ENC_H264_PROFILE_BASELINE:
Andrey Turkinfaffff82016-05-25 14:05:501220 cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
Andrey Turkin82d705e2016-05-20 14:49:241221 avctx->profile = FF_PROFILE_H264_BASELINE;
Andrey Turkin98243212016-05-25 14:26:251222 break;
1223 case NV_ENC_H264_PROFILE_MAIN:
1224 cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
1225 avctx->profile = FF_PROFILE_H264_MAIN;
1226 break;
1227 case NV_ENC_H264_PROFILE_HIGH:
1228 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
1229 avctx->profile = FF_PROFILE_H264_HIGH;
1230 break;
1231 case NV_ENC_H264_PROFILE_HIGH_444P:
Andrey Turkinfaffff82016-05-25 14:05:501232 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
Andrey Turkin82d705e2016-05-20 14:49:241233 avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
Andrey Turkin98243212016-05-25 14:26:251234 break;
Andrey Turkin82d705e2016-05-20 14:49:241235 }
1236 }
1237
1238 // force setting profile as high444p if input is AV_PIX_FMT_YUV444P
Timo Rothenpieler7555d6f2021-03-30 20:08:491239 if (IS_YUV444(ctx->data_pix_fmt)) {
Andrey Turkinfaffff82016-05-25 14:05:501240 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
Andrey Turkin82d705e2016-05-20 14:49:241241 avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
1242 }
1243
Andrey Turkinfaffff82016-05-25 14:05:501244 h264->chromaFormatIDC = avctx->profile == FF_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;
Andrey Turkin82d705e2016-05-20 14:49:241245
Andrey Turkinb0172872016-05-25 15:00:521246 h264->level = ctx->level;
Andrey Turkin82d705e2016-05-20 14:49:241247
Timo Rothenpielera0b69e22017-08-30 19:06:251248 if (ctx->coder >= 0)
1249 h264->entropyCodingMode = ctx->coder;
1250
Timo Rothenpieler86e9dba2018-04-11 12:22:201251#ifdef NVENC_HAVE_BFRAME_REF_MODE
Timo Rothenpieler28680e22022-11-02 18:02:561252 if (ctx->b_ref_mode >= 0)
1253 h264->useBFramesAsRef = ctx->b_ref_mode;
Timo Rothenpieler86e9dba2018-04-11 12:22:201254#endif
1255
Roman Arzumanyan567b5e32019-09-27 15:56:111256#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES
1257 h264->numRefL0 = avctx->refs;
1258 h264->numRefL1 = avctx->refs;
1259#endif
1260
Andrey Turkin82d705e2016-05-20 14:49:241261 return 0;
1262}
1263
1264static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
1265{
Andrey Turkinfaffff82016-05-25 14:05:501266 NvencContext *ctx = avctx->priv_data;
1267 NV_ENC_CONFIG *cc = &ctx->encode_config;
1268 NV_ENC_CONFIG_HEVC *hevc = &cc->encodeCodecConfig.hevcConfig;
1269 NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui = &hevc->hevcVUIParameters;
Andrey Turkin82d705e2016-05-20 14:49:241270
Timo Rothenpielerb71069872022-08-06 18:58:481271 const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(ctx->data_pix_fmt);
1272
1273 if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) && !IS_GBRP(ctx->data_pix_fmt)) {
1274 vui->colourMatrix = AVCOL_SPC_BT470BG;
1275 vui->colourPrimaries = avctx->color_primaries;
1276 vui->transferCharacteristics = avctx->color_trc;
1277 vui->videoFullRangeFlag = 0;
1278 } else {
1279 vui->colourMatrix = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace;
1280 vui->colourPrimaries = avctx->color_primaries;
1281 vui->transferCharacteristics = avctx->color_trc;
1282 vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
1283 || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
1284 }
Andrey Turkin82d705e2016-05-20 14:49:241285
Andrey Turkinfaffff82016-05-25 14:05:501286 vui->colourDescriptionPresentFlag =
Timo Rothenpieler7555d6f2021-03-30 20:08:491287 (vui->colourMatrix != 2 || vui->colourPrimaries != 2 || vui->transferCharacteristics != 2);
Andrey Turkin82d705e2016-05-20 14:49:241288
Andrey Turkinfaffff82016-05-25 14:05:501289 vui->videoSignalTypePresentFlag =
1290 (vui->colourDescriptionPresentFlag
1291 || vui->videoFormat != 5
1292 || vui->videoFullRangeFlag != 0);
Andrey Turkin82d705e2016-05-20 14:49:241293
Andrey Turkinfaffff82016-05-25 14:05:501294 hevc->sliceMode = 3;
Limin Wang85489e02021-09-02 10:38:551295 hevc->sliceModeData = avctx->slices > 0 ? avctx->slices : 1;
Andrey Turkin82d705e2016-05-20 14:49:241296
Limin Wange6bd5172021-09-06 02:01:581297 if (ctx->intra_refresh) {
1298 hevc->enableIntraRefresh = 1;
1299 hevc->intraRefreshPeriod = avctx->gop_size;
1300 hevc->intraRefreshCnt = avctx->gop_size - 1;
Limin Wang37565252021-09-02 10:38:571301#ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH
1302 hevc->singleSliceIntraRefresh = ctx->single_slice_intra_refresh;
1303#endif
Limin Wange6bd5172021-09-06 02:01:581304 }
1305
Limin Wang75001ae2021-09-02 10:38:581306#ifdef NVENC_HAVE_HEVC_CONSTRAINED_ENCODING
1307 if (ctx->constrained_encoding)
1308 hevc->enableConstrainedEncoding = 1;
1309#endif
1310
Andrey Turkinfaffff82016-05-25 14:05:501311 hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
Andrey Turkinf84dfbc2016-05-25 16:39:541312 hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
Miroslav Slugen1841eda2016-12-30 21:02:421313 hevc->outputAUD = ctx->aud;
Andrey Turkin82d705e2016-05-20 14:49:241314
Timo Rothenpielere929b2f2019-09-27 15:55:231315 if (ctx->dpb_size >= 0) {
Andrey Turkinf84dfbc2016-05-25 16:39:541316 /* 0 means "let the hardware decide" */
Timo Rothenpielere929b2f2019-09-27 15:55:231317 hevc->maxNumRefFramesInDPB = ctx->dpb_size;
Andrey Turkinf84dfbc2016-05-25 16:39:541318 }
Limin Wange6bd5172021-09-06 02:01:581319
1320 if (ctx->intra_refresh) {
1321 hevc->idrPeriod = NVENC_INFINITE_GOPLENGTH;
1322 } else if (avctx->gop_size >= 0) {
1323 hevc->idrPeriod = avctx->gop_size;
Andrey Turkinf84dfbc2016-05-25 16:39:541324 }
1325
1326 if (IS_CBR(cc->rcParams.rateControlMode)) {
1327 hevc->outputBufferingPeriodSEI = 1;
Andrey Turkinf84dfbc2016-05-25 16:39:541328 }
Andrey Turkin82d705e2016-05-20 14:49:241329
Timo Rothenpieler4e6638a2017-09-02 13:39:241330 hevc->outputPictureTimingSEI = 1;
1331
Clément Bœschb7cc4eb2017-03-20 22:04:281332 switch (ctx->profile) {
Oliver Collyerd1bf8a32016-08-25 15:18:031333 case NV_ENC_HEVC_PROFILE_MAIN:
1334 cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
Clément Bœschb7cc4eb2017-03-20 22:04:281335 avctx->profile = FF_PROFILE_HEVC_MAIN;
Oliver Collyerd1bf8a32016-08-25 15:18:031336 break;
1337 case NV_ENC_HEVC_PROFILE_MAIN_10:
1338 cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
Clément Bœschb7cc4eb2017-03-20 22:04:281339 avctx->profile = FF_PROFILE_HEVC_MAIN_10;
Oliver Collyerd1bf8a32016-08-25 15:18:031340 break;
Timo Rothenpieler033f98c2016-09-28 12:21:031341 case NV_ENC_HEVC_PROFILE_REXT:
1342 cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID;
Clément Bœschb7cc4eb2017-03-20 22:04:281343 avctx->profile = FF_PROFILE_HEVC_REXT;
Timo Rothenpieler033f98c2016-09-28 12:21:031344 break;
Oliver Collyerd1bf8a32016-08-25 15:18:031345 }
1346
1347 // force setting profile as main10 if input is 10 bit
1348 if (IS_10BIT(ctx->data_pix_fmt)) {
1349 cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
1350 avctx->profile = FF_PROFILE_HEVC_MAIN_10;
1351 }
1352
Timo Rothenpieler033f98c2016-09-28 12:21:031353 // force setting profile as rext if input is yuv444
1354 if (IS_YUV444(ctx->data_pix_fmt)) {
1355 cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID;
1356 avctx->profile = FF_PROFILE_HEVC_REXT;
1357 }
1358
Oliver Collyerd1bf8a32016-08-25 15:18:031359 hevc->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1;
1360
1361 hevc->pixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
Andrey Turkin82d705e2016-05-20 14:49:241362
Andrey Turkinb0172872016-05-25 15:00:521363 hevc->level = ctx->level;
Andrey Turkin82d705e2016-05-20 14:49:241364
Andrey Turkin40df4682016-05-25 15:06:021365 hevc->tier = ctx->tier;
Andrey Turkin82d705e2016-05-20 14:49:241366
Roman Arzumanyanf1f66df2019-02-14 12:20:251367#ifdef NVENC_HAVE_HEVC_BFRAME_REF_MODE
Timo Rothenpieler28680e22022-11-02 18:02:561368 if (ctx->b_ref_mode >= 0)
1369 hevc->useBFramesAsRef = ctx->b_ref_mode;
Roman Arzumanyanf1f66df2019-02-14 12:20:251370#endif
1371
Roman Arzumanyan567b5e32019-09-27 15:56:111372#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES
1373 hevc->numRefL0 = avctx->refs;
1374 hevc->numRefL1 = avctx->refs;
1375#endif
1376
Andrey Turkin82d705e2016-05-20 14:49:241377 return 0;
1378}
1379
Timo Rothenpieler5c288a42022-11-05 20:17:371380#if CONFIG_AV1_NVENC_ENCODER
1381static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx)
1382{
1383 NvencContext *ctx = avctx->priv_data;
1384 NV_ENC_CONFIG *cc = &ctx->encode_config;
1385 NV_ENC_CONFIG_AV1 *av1 = &cc->encodeCodecConfig.av1Config;
1386
1387 const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(ctx->data_pix_fmt);
1388
1389 if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) && !IS_GBRP(ctx->data_pix_fmt)) {
1390 av1->matrixCoefficients = AVCOL_SPC_BT470BG;
1391 av1->colorPrimaries = avctx->color_primaries;
1392 av1->transferCharacteristics = avctx->color_trc;
1393 av1->colorRange = 0;
1394 } else {
1395 av1->matrixCoefficients = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace;
1396 av1->colorPrimaries = avctx->color_primaries;
1397 av1->transferCharacteristics = avctx->color_trc;
1398 av1->colorRange = (avctx->color_range == AVCOL_RANGE_JPEG
1399 || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
1400 }
1401
1402 if (IS_YUV444(ctx->data_pix_fmt)) {
Timo Rothenpieler939273d2022-11-10 14:26:431403 av_log(avctx, AV_LOG_ERROR, "AV1 High Profile not supported, required for 4:4:4 encoding\n");
1404 return AVERROR(ENOTSUP);
Timo Rothenpieler5c288a42022-11-05 20:17:371405 } else {
1406 cc->profileGUID = NV_ENC_AV1_PROFILE_MAIN_GUID;
1407 avctx->profile = FF_PROFILE_AV1_MAIN;
1408 }
1409
1410 if (ctx->dpb_size >= 0) {
1411 /* 0 means "let the hardware decide" */
1412 av1->maxNumRefFramesInDPB = ctx->dpb_size;
1413 }
1414
1415 if (ctx->intra_refresh) {
1416 av1->enableIntraRefresh = 1;
1417 av1->intraRefreshPeriod = avctx->gop_size;
1418 av1->intraRefreshCnt = avctx->gop_size - 1;
1419
1420 av1->idrPeriod = NVENC_INFINITE_GOPLENGTH;
1421 } else if (avctx->gop_size >= 0) {
1422 av1->idrPeriod = avctx->gop_size;
1423 }
1424
1425 if (IS_CBR(cc->rcParams.rateControlMode)) {
1426 av1->enableBitstreamPadding = 1;
1427 }
1428
1429 if (ctx->tile_cols >= 0)
1430 av1->numTileColumns = ctx->tile_cols;
1431 if (ctx->tile_rows >= 0)
1432 av1->numTileRows = ctx->tile_rows;
1433
1434 av1->outputAnnexBFormat = 0;
1435
1436 av1->level = ctx->level;
1437 av1->tier = ctx->tier;
1438
1439 av1->enableTimingInfo = ctx->timing_info;
1440
1441 /* mp4 encapsulation requires sequence headers to be present on all keyframes for AV1 */
1442 av1->disableSeqHdr = 0;
1443 av1->repeatSeqHdr = 1;
1444
1445 av1->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1;
1446
1447 av1->inputPixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
1448 av1->pixelBitDepthMinus8 = (IS_10BIT(ctx->data_pix_fmt) || ctx->highbitdepth) ? 2 : 0;
1449
1450 if (ctx->b_ref_mode >= 0)
1451 av1->useBFramesAsRef = ctx->b_ref_mode;
1452
1453 av1->numFwdRefs = avctx->refs;
1454 av1->numBwdRefs = avctx->refs;
1455
1456 return 0;
1457}
1458#endif
1459
Andrey Turkinfaffff82016-05-25 14:05:501460static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:241461{
1462 switch (avctx->codec->id) {
1463 case AV_CODEC_ID_H264:
Andrey Turkinfaffff82016-05-25 14:05:501464 return nvenc_setup_h264_config(avctx);
1465 case AV_CODEC_ID_HEVC:
Andrey Turkin82d705e2016-05-20 14:49:241466 return nvenc_setup_hevc_config(avctx);
Timo Rothenpieler5c288a42022-11-05 20:17:371467#if CONFIG_AV1_NVENC_ENCODER
1468 case AV_CODEC_ID_AV1:
1469 return nvenc_setup_av1_config(avctx);
1470#endif
Andrey Turkin82d705e2016-05-20 14:49:241471 /* Earlier switch/case will return if unknown codec is passed. */
1472 }
1473
1474 return 0;
1475}
1476
Miroslav Slugeň952421c2017-02-12 18:53:581477static void compute_dar(AVCodecContext *avctx, int *dw, int *dh) {
1478 int sw, sh;
1479
1480 sw = avctx->width;
1481 sh = avctx->height;
1482
Timo Rothenpielere7fbdda2022-11-10 12:05:591483#if CONFIG_AV1_NVENC_ENCODER
1484 if (avctx->codec->id == AV_CODEC_ID_AV1) {
1485 /* For AV1 we actually need to calculate the render width/height, not the dar */
1486 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0
1487 && avctx->sample_aspect_ratio.num != avctx->sample_aspect_ratio.den)
1488 {
1489 if (avctx->sample_aspect_ratio.num > avctx->sample_aspect_ratio.den) {
1490 sw = av_rescale(sw, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
1491 } else {
1492 sh = av_rescale(sh, avctx->sample_aspect_ratio.den, avctx->sample_aspect_ratio.num);
1493 }
1494 }
1495
1496 *dw = sw;
1497 *dh = sh;
1498 return;
1499 }
1500#endif
1501
Miroslav Slugeň952421c2017-02-12 18:53:581502 if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) {
1503 sw *= avctx->sample_aspect_ratio.num;
1504 sh *= avctx->sample_aspect_ratio.den;
1505 }
1506
1507 av_reduce(dw, dh, sw, sh, 1024 * 1024);
1508}
1509
Andrey Turkin82d705e2016-05-20 14:49:241510static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
1511{
1512 NvencContext *ctx = avctx->priv_data;
1513 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1514 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
1515
1516 NV_ENC_PRESET_CONFIG preset_config = { 0 };
Andrey Turkin82d705e2016-05-20 14:49:241517 NVENCSTATUS nv_status = NV_ENC_SUCCESS;
1518 AVCPBProperties *cpb_props;
Andrey Turkin82d705e2016-05-20 14:49:241519 int res = 0;
1520 int dw, dh;
1521
Andrey Turkin82d705e2016-05-20 14:49:241522 ctx->encode_config.version = NV_ENC_CONFIG_VER;
1523 ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
Andrey Turkinfaffff82016-05-25 14:05:501524
1525 ctx->init_encode_params.encodeHeight = avctx->height;
1526 ctx->init_encode_params.encodeWidth = avctx->width;
1527
1528 ctx->init_encode_params.encodeConfig = &ctx->encode_config;
1529
Andrey Turkin82d705e2016-05-20 14:49:241530 preset_config.version = NV_ENC_PRESET_CONFIG_VER;
1531 preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
1532
Roman Arzumanyan9115d772020-03-19 08:35:291533#ifdef NVENC_HAVE_NEW_PRESETS
Timo Rothenpielerbb6edf62020-10-29 20:59:371534 ctx->init_encode_params.tuningInfo = ctx->tuning_info;
Roman Arzumanyan9115d772020-03-19 08:35:291535
Timo Rothenpieler988f2e92021-04-18 09:17:541536 if (ctx->flags & NVENC_LOSSLESS)
1537 ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOSSLESS;
1538 else if (ctx->flags & NVENC_LOWLATENCY)
Timo Rothenpielerbb6edf62020-10-29 20:59:371539 ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOW_LATENCY;
Timo Rothenpielere0c8e512020-10-21 16:45:521540
Timo Rothenpielerbb6edf62020-10-29 20:59:371541 nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder,
1542 ctx->init_encode_params.encodeGUID,
1543 ctx->init_encode_params.presetGUID,
1544 ctx->init_encode_params.tuningInfo,
1545 &preset_config);
1546#else
Timo Rothenpielerbb6edf62020-10-29 20:59:371547 nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
1548 ctx->init_encode_params.encodeGUID,
1549 ctx->init_encode_params.presetGUID,
1550 &preset_config);
Roman Arzumanyan9115d772020-03-19 08:35:291551#endif
Andrey Turkinfaffff82016-05-25 14:05:501552 if (nv_status != NV_ENC_SUCCESS)
1553 return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration");
Timo Rothenpieler2a428db2014-11-29 23:04:371554
Andrey Turkinfaffff82016-05-25 14:05:501555 memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
Agatha Hu49046582015-09-11 09:07:101556
Andrey Turkinfaffff82016-05-25 14:05:501557 ctx->encode_config.version = NV_ENC_CONFIG_VER;
Timo Rothenpielerfb34c582015-01-26 12:28:221558
Miroslav Slugeň952421c2017-02-12 18:53:581559 compute_dar(avctx, &dw, &dh);
Miroslav Slugeňf2dd6ae2016-11-27 00:46:061560 ctx->init_encode_params.darHeight = dh;
1561 ctx->init_encode_params.darWidth = dw;
Timo Rothenpielerfb34c582015-01-26 12:28:221562
Zachariah Brownb18fd2b2020-05-14 18:15:331563 if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
1564 ctx->init_encode_params.frameRateNum = avctx->framerate.num;
1565 ctx->init_encode_params.frameRateDen = avctx->framerate.den;
1566 } else {
1567 ctx->init_encode_params.frameRateNum = avctx->time_base.den;
1568 ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame;
1569 }
Timo Rothenpieler2a428db2014-11-29 23:04:371570
Timo Rothenpieler2a428db2014-11-29 23:04:371571 ctx->init_encode_params.enableEncodeAsync = 0;
1572 ctx->init_encode_params.enablePTD = 1;
1573
Roman Arzumanyan9115d772020-03-19 08:35:291574#ifdef NVENC_HAVE_NEW_PRESETS
1575 /* If lookahead isn't set from CLI, use value from preset.
1576 * P6 & P7 presets may enable lookahead for better quality.
1577 * */
1578 if (ctx->rc_lookahead == 0 && ctx->encode_config.rcParams.enableLookahead)
1579 ctx->rc_lookahead = ctx->encode_config.rcParams.lookaheadDepth;
Roman Arzumanyan9115d772020-03-19 08:35:291580#endif
1581
Sumit Agarwal01775732017-05-09 14:24:541582 if (ctx->weighted_pred == 1)
1583 ctx->init_encode_params.enableWeightedPrediction = 1;
1584
Miroslav Slugen9b425bd2016-12-30 21:04:311585 if (ctx->bluray_compat) {
1586 ctx->aud = 1;
Timo Rothenpielere929b2f2019-09-27 15:55:231587 ctx->dpb_size = FFMIN(FFMAX(avctx->refs, 0), 6);
Miroslav Slugen9b425bd2016-12-30 21:04:311588 avctx->max_b_frames = FFMIN(avctx->max_b_frames, 3);
1589 switch (avctx->codec->id) {
1590 case AV_CODEC_ID_H264:
1591 /* maximum level depends on used resolution */
1592 break;
1593 case AV_CODEC_ID_HEVC:
1594 ctx->level = NV_ENC_LEVEL_HEVC_51;
1595 ctx->tier = NV_ENC_TIER_HEVC_HIGH;
1596 break;
1597 }
1598 }
1599
Timo Rothenpieler914fd422015-01-26 12:28:211600 if (avctx->gop_size > 0) {
1601 if (avctx->max_b_frames >= 0) {
Clément Bœsch8ef57a02016-06-21 19:55:201602 /* 0 is intra-only, 1 is I/P only, 2 is one B-Frame, 3 two B-frames, and so on. */
Timo Rothenpieler914fd422015-01-26 12:28:211603 ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1;
1604 }
1605
Timo Rothenpieler2a428db2014-11-29 23:04:371606 ctx->encode_config.gopLength = avctx->gop_size;
Timo Rothenpieler914fd422015-01-26 12:28:211607 } else if (avctx->gop_size == 0) {
1608 ctx->encode_config.frameIntervalP = 0;
1609 ctx->encode_config.gopLength = 1;
Timo Rothenpieler2a428db2014-11-29 23:04:371610 }
1611
Limin Wang37565252021-09-02 10:38:571612 /* force to enable intra refresh */
1613 if(ctx->single_slice_intra_refresh)
1614 ctx->intra_refresh = 1;
1615
Limin Wange6bd5172021-09-06 02:01:581616 if (ctx->intra_refresh)
1617 ctx->encode_config.gopLength = NVENC_INFINITE_GOPLENGTH;
1618
Miroslav Slugeňde2faec2016-11-21 11:17:431619 nvenc_recalc_surfaces(avctx);
1620
Andrey Turkinfaffff82016-05-25 14:05:501621 nvenc_setup_rate_control(avctx);
Timo Rothenpieler2a428db2014-11-29 23:04:371622
Vittorio Giovara7c6eb0a2015-06-29 19:59:371623 if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
Timo Rothenpieler2a428db2014-11-29 23:04:371624 ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
1625 } else {
1626 ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
1627 }
1628
Andrey Turkinfaffff82016-05-25 14:05:501629 res = nvenc_setup_codec_config(avctx);
Andrey Turkin82d705e2016-05-20 14:49:241630 if (res)
1631 return res;
Timo Rothenpieler2a428db2014-11-29 23:04:371632
Hendrik Leppkes6fcbf392017-11-11 15:13:241633 res = nvenc_push_context(avctx);
1634 if (res < 0)
1635 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141636
Timo Rothenpieler2a428db2014-11-29 23:04:371637 nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params);
Timo Rothenpieler51a23342019-09-27 16:30:101638 if (nv_status != NV_ENC_SUCCESS) {
1639 nvenc_pop_context(avctx);
1640 return nvenc_print_error(avctx, nv_status, "InitializeEncoder failed");
1641 }
1642
1643#ifdef NVENC_HAVE_CUSTREAM_PTR
1644 if (ctx->cu_context) {
1645 nv_status = p_nvenc->nvEncSetIOCudaStreams(ctx->nvencoder, &ctx->cu_stream, &ctx->cu_stream);
1646 if (nv_status != NV_ENC_SUCCESS) {
1647 nvenc_pop_context(avctx);
1648 return nvenc_print_error(avctx, nv_status, "SetIOCudaStreams failed");
1649 }
1650 }
1651#endif
Ganapathy Kasi43c417a2017-05-31 02:03:141652
Hendrik Leppkes6fcbf392017-11-11 15:13:241653 res = nvenc_pop_context(avctx);
1654 if (res < 0)
1655 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141656
Timo Rothenpieler2a428db2014-11-29 23:04:371657 if (ctx->encode_config.frameIntervalP > 1)
1658 avctx->has_b_frames = 2;
1659
1660 if (ctx->encode_config.rcParams.averageBitRate > 0)
1661 avctx->bit_rate = ctx->encode_config.rcParams.averageBitRate;
1662
Anton Khirnov1520c6f2015-10-03 13:19:101663 cpb_props = ff_add_cpb_side_data(avctx);
1664 if (!cpb_props)
1665 return AVERROR(ENOMEM);
Hendrik Leppkes5fc17ed2015-12-17 12:41:291666 cpb_props->max_bitrate = ctx->encode_config.rcParams.maxBitRate;
Anton Khirnov1520c6f2015-10-03 13:19:101667 cpb_props->avg_bitrate = avctx->bit_rate;
Hendrik Leppkes5fc17ed2015-12-17 12:41:291668 cpb_props->buffer_size = ctx->encode_config.rcParams.vbvBufferSize;
Anton Khirnov1520c6f2015-10-03 13:19:101669
Timo Rothenpieler2a428db2014-11-29 23:04:371670 return 0;
Andrey Turkin82d705e2016-05-20 14:49:241671}
1672
Philip Langdale27038692016-11-25 19:11:451673static NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum AVPixelFormat pix_fmt)
1674{
1675 switch (pix_fmt) {
1676 case AV_PIX_FMT_YUV420P:
1677 return NV_ENC_BUFFER_FORMAT_YV12_PL;
1678 case AV_PIX_FMT_NV12:
1679 return NV_ENC_BUFFER_FORMAT_NV12_PL;
1680 case AV_PIX_FMT_P010:
Philip Langdale6a89cdc2018-02-25 17:08:061681 case AV_PIX_FMT_P016:
Philip Langdale27038692016-11-25 19:11:451682 return NV_ENC_BUFFER_FORMAT_YUV420_10BIT;
Timo Rothenpieler7555d6f2021-03-30 20:08:491683 case AV_PIX_FMT_GBRP:
Philip Langdale27038692016-11-25 19:11:451684 case AV_PIX_FMT_YUV444P:
1685 return NV_ENC_BUFFER_FORMAT_YUV444_PL;
Timo Rothenpieler7555d6f2021-03-30 20:08:491686 case AV_PIX_FMT_GBRP16:
Philip Langdale27038692016-11-25 19:11:451687 case AV_PIX_FMT_YUV444P16:
1688 return NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
1689 case AV_PIX_FMT_0RGB32:
Timo Rothenpieler85bc6b52022-07-04 23:58:101690 case AV_PIX_FMT_RGB32:
Philip Langdale27038692016-11-25 19:11:451691 return NV_ENC_BUFFER_FORMAT_ARGB;
1692 case AV_PIX_FMT_0BGR32:
Timo Rothenpieler85bc6b52022-07-04 23:58:101693 case AV_PIX_FMT_BGR32:
Philip Langdale27038692016-11-25 19:11:451694 return NV_ENC_BUFFER_FORMAT_ABGR;
Timo Rothenpieler85bc6b52022-07-04 23:58:101695 case AV_PIX_FMT_X2RGB10:
1696 return NV_ENC_BUFFER_FORMAT_ARGB10;
1697 case AV_PIX_FMT_X2BGR10:
1698 return NV_ENC_BUFFER_FORMAT_ABGR10;
Philip Langdale27038692016-11-25 19:11:451699 default:
1700 return NV_ENC_BUFFER_FORMAT_UNDEFINED;
1701 }
1702}
1703
Andrey Turkin82d705e2016-05-20 14:49:241704static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
1705{
1706 NvencContext *ctx = avctx->priv_data;
1707 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1708 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
Ben Chang8de34582017-04-25 21:57:561709 NvencSurface* tmp_surface = &ctx->surfaces[idx];
Andrey Turkin82d705e2016-05-20 14:49:241710
1711 NVENCSTATUS nv_status;
Andrey Turkin82d705e2016-05-20 14:49:241712 NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 };
Andrey Turkin82d705e2016-05-20 14:49:241713 allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
1714
Hendrik Leppkesbff6d982017-11-11 15:51:581715 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Andrey Turkina8cf25d2016-05-20 22:08:061716 ctx->surfaces[idx].in_ref = av_frame_alloc();
1717 if (!ctx->surfaces[idx].in_ref)
1718 return AVERROR(ENOMEM);
1719 } else {
1720 NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 };
Philip Langdale27038692016-11-25 19:11:451721
1722 ctx->surfaces[idx].format = nvenc_map_buffer_format(ctx->data_pix_fmt);
1723 if (ctx->surfaces[idx].format == NV_ENC_BUFFER_FORMAT_UNDEFINED) {
1724 av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n",
1725 av_get_pix_fmt_name(ctx->data_pix_fmt));
1726 return AVERROR(EINVAL);
1727 }
1728
Andrey Turkina8cf25d2016-05-20 22:08:061729 allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
Timo Rothenpielera1652ac2017-05-23 09:24:401730 allocSurf.width = avctx->width;
1731 allocSurf.height = avctx->height;
Andrey Turkina8cf25d2016-05-20 22:08:061732 allocSurf.bufferFmt = ctx->surfaces[idx].format;
1733
1734 nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf);
1735 if (nv_status != NV_ENC_SUCCESS) {
1736 return nvenc_print_error(avctx, nv_status, "CreateInputBuffer failed");
1737 }
1738
1739 ctx->surfaces[idx].input_surface = allocSurf.inputBuffer;
1740 ctx->surfaces[idx].width = allocSurf.width;
1741 ctx->surfaces[idx].height = allocSurf.height;
Andrey Turkin82d705e2016-05-20 14:49:241742 }
1743
Andrey Turkin82d705e2016-05-20 14:49:241744 nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut);
1745 if (nv_status != NV_ENC_SUCCESS) {
Andrey Turkine1691c42016-05-20 15:37:001746 int err = nvenc_print_error(avctx, nv_status, "CreateBitstreamBuffer failed");
Hendrik Leppkesbff6d982017-11-11 15:51:581747 if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11)
Andrey Turkina8cf25d2016-05-20 22:08:061748 p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[idx].input_surface);
1749 av_frame_free(&ctx->surfaces[idx].in_ref);
Andrey Turkine1691c42016-05-20 15:37:001750 return err;
Andrey Turkin82d705e2016-05-20 14:49:241751 }
1752
Andrey Turkine1691c42016-05-20 15:37:001753 ctx->surfaces[idx].output_surface = allocOut.bitstreamBuffer;
Andrey Turkin82d705e2016-05-20 14:49:241754
Anton Khirnov587545c2022-01-06 15:59:491755 av_fifo_write(ctx->unused_surface_queue, &tmp_surface, 1);
Ben Chang8de34582017-04-25 21:57:561756
Andrey Turkin82d705e2016-05-20 14:49:241757 return 0;
1758}
1759
Andrey Turkinb6933532016-05-25 16:57:111760static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx)
Andrey Turkin82d705e2016-05-20 14:49:241761{
Andrey Turkin82d705e2016-05-20 14:49:241762 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler4e93f002017-11-15 17:33:311763 int i, res = 0, res2;
Andrey Turkin82d705e2016-05-20 14:49:241764
Andreas Rheinhardt1ea36502021-09-14 19:31:531765 ctx->surfaces = av_calloc(ctx->nb_surfaces, sizeof(*ctx->surfaces));
Andrey Turkinf052ef32016-05-29 10:07:341766 if (!ctx->surfaces)
Andrey Turkin82d705e2016-05-20 14:49:241767 return AVERROR(ENOMEM);
Andrey Turkin82d705e2016-05-20 14:49:241768
Anton Khirnov35538092022-07-12 09:25:091769 ctx->reorder_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(FrameData), 0);
1770 if (!ctx->reorder_queue)
Andrey Turkincfb49fc2016-05-20 16:13:201771 return AVERROR(ENOMEM);
Ben Chang8de34582017-04-25 21:57:561772
Anton Khirnov587545c2022-01-06 15:59:491773 ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
Ben Chang8de34582017-04-25 21:57:561774 if (!ctx->unused_surface_queue)
1775 return AVERROR(ENOMEM);
1776
Anton Khirnov587545c2022-01-06 15:59:491777 ctx->output_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
Andrey Turkincfb49fc2016-05-20 16:13:201778 if (!ctx->output_surface_queue)
1779 return AVERROR(ENOMEM);
Anton Khirnov587545c2022-01-06 15:59:491780 ctx->output_surface_ready_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
Andrey Turkincfb49fc2016-05-20 16:13:201781 if (!ctx->output_surface_ready_queue)
1782 return AVERROR(ENOMEM);
1783
Hendrik Leppkes6fcbf392017-11-11 15:13:241784 res = nvenc_push_context(avctx);
1785 if (res < 0)
1786 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141787
Andrey Turkinf052ef32016-05-29 10:07:341788 for (i = 0; i < ctx->nb_surfaces; i++) {
Andrey Turkinb6933532016-05-25 16:57:111789 if ((res = nvenc_alloc_surface(avctx, i)) < 0)
Timo Rothenpieler4e93f002017-11-15 17:33:311790 goto fail;
Ganapathy Kasi43c417a2017-05-31 02:03:141791 }
1792
Timo Rothenpieler4e93f002017-11-15 17:33:311793fail:
1794 res2 = nvenc_pop_context(avctx);
1795 if (res2 < 0)
1796 return res2;
Andrey Turkin82d705e2016-05-20 14:49:241797
Timo Rothenpieler4e93f002017-11-15 17:33:311798 return res;
Andrey Turkin82d705e2016-05-20 14:49:241799}
1800
1801static av_cold int nvenc_setup_extradata(AVCodecContext *avctx)
1802{
1803 NvencContext *ctx = avctx->priv_data;
1804 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1805 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
1806
1807 NVENCSTATUS nv_status;
1808 uint32_t outSize = 0;
Timo Rothenpielereb1e3592022-11-15 00:32:561809 char tmpHeader[NV_MAX_SEQ_HDR_LEN];
1810
Andrey Turkin82d705e2016-05-20 14:49:241811 NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 };
1812 payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;
1813
1814 payload.spsppsBuffer = tmpHeader;
1815 payload.inBufferSize = sizeof(tmpHeader);
1816 payload.outSPSPPSPayloadSize = &outSize;
1817
1818 nv_status = p_nvenc->nvEncGetSequenceParams(ctx->nvencoder, &payload);
1819 if (nv_status != NV_ENC_SUCCESS) {
Andrey Turkine1691c42016-05-20 15:37:001820 return nvenc_print_error(avctx, nv_status, "GetSequenceParams failed");
Andrey Turkin82d705e2016-05-20 14:49:241821 }
1822
1823 avctx->extradata_size = outSize;
1824 avctx->extradata = av_mallocz(outSize + AV_INPUT_BUFFER_PADDING_SIZE);
1825
1826 if (!avctx->extradata) {
1827 return AVERROR(ENOMEM);
1828 }
1829
1830 memcpy(avctx->extradata, tmpHeader, outSize);
1831
1832 return 0;
1833}
1834
Andrey Turkin7aa16d52016-05-25 13:04:281835av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
Timo Rothenpieler2a428db2014-11-29 23:04:371836{
Andrey Turkinb6933532016-05-25 16:57:111837 NvencContext *ctx = avctx->priv_data;
Timo Rothenpieler2a428db2014-11-29 23:04:371838 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
1839 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
Hendrik Leppkes6fcbf392017-11-11 15:13:241840 int i, res;
Timo Rothenpieler2a428db2014-11-29 23:04:371841
Andrey Turkinb6933532016-05-25 16:57:111842 /* the encoder has to be flushed before it can be closed */
1843 if (ctx->nvencoder) {
1844 NV_ENC_PIC_PARAMS params = { .version = NV_ENC_PIC_PARAMS_VER,
1845 .encodePicFlags = NV_ENC_PIC_FLAG_EOS };
1846
Hendrik Leppkes6fcbf392017-11-11 15:13:241847 res = nvenc_push_context(avctx);
1848 if (res < 0)
1849 return res;
Timo Rothenpieler0e995ea2017-08-30 19:12:231850
Andrey Turkinb6933532016-05-25 16:57:111851 p_nvenc->nvEncEncodePicture(ctx->nvencoder, &params);
1852 }
1853
Anton Khirnov35538092022-07-12 09:25:091854 reorder_queue_flush(ctx->reorder_queue);
1855 av_fifo_freep2(&ctx->reorder_queue);
Anton Khirnov587545c2022-01-06 15:59:491856 av_fifo_freep2(&ctx->output_surface_ready_queue);
1857 av_fifo_freep2(&ctx->output_surface_queue);
1858 av_fifo_freep2(&ctx->unused_surface_queue);
Timo Rothenpieler2a428db2014-11-29 23:04:371859
Hendrik Leppkesbff6d982017-11-11 15:51:581860 if (ctx->surfaces && (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11)) {
Andrey Turkina8cf25d2016-05-20 22:08:061861 for (i = 0; i < ctx->nb_registered_frames; i++) {
Timo Rothenpielerbbe1b212018-01-26 19:16:531862 if (ctx->registered_frames[i].mapped)
1863 p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[i].in_map.mappedResource);
Andrey Turkina8cf25d2016-05-20 22:08:061864 if (ctx->registered_frames[i].regptr)
1865 p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr);
1866 }
1867 ctx->nb_registered_frames = 0;
1868 }
1869
Andrey Turkinb6933532016-05-25 16:57:111870 if (ctx->surfaces) {
Andrey Turkinf052ef32016-05-29 10:07:341871 for (i = 0; i < ctx->nb_surfaces; ++i) {
Hendrik Leppkesbff6d982017-11-11 15:51:581872 if (avctx->pix_fmt != AV_PIX_FMT_CUDA && avctx->pix_fmt != AV_PIX_FMT_D3D11)
Andrey Turkinb6933532016-05-25 16:57:111873 p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[i].input_surface);
1874 av_frame_free(&ctx->surfaces[i].in_ref);
1875 p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->surfaces[i].output_surface);
1876 }
Timo Rothenpieler2a428db2014-11-29 23:04:371877 }
Andrey Turkincfb49fc2016-05-20 16:13:201878 av_freep(&ctx->surfaces);
Andrey Turkinf052ef32016-05-29 10:07:341879 ctx->nb_surfaces = 0;
Timo Rothenpieler2a428db2014-11-29 23:04:371880
James Almer827d6fe2020-06-09 21:31:321881 av_frame_free(&ctx->frame);
1882
Brad Hards63948a62021-05-25 10:11:571883 av_freep(&ctx->sei_data);
1884
Timo Rothenpieler0e995ea2017-08-30 19:12:231885 if (ctx->nvencoder) {
Andrey Turkinb6933532016-05-25 16:57:111886 p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
Timo Rothenpieler2a428db2014-11-29 23:04:371887
Hendrik Leppkes6fcbf392017-11-11 15:13:241888 res = nvenc_pop_context(avctx);
1889 if (res < 0)
1890 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:141891 }
Timo Rothenpieler0e995ea2017-08-30 19:12:231892 ctx->nvencoder = NULL;
Ganapathy Kasi43c417a2017-05-31 02:03:141893
Andrey Turkina8cf25d2016-05-20 22:08:061894 if (ctx->cu_context_internal)
Philip Langdale19d3d0c2018-11-11 06:47:281895 CHECK_CU(dl_fn->cuda_dl->cuCtxDestroy(ctx->cu_context_internal));
Andrey Turkina8cf25d2016-05-20 22:08:061896 ctx->cu_context = ctx->cu_context_internal = NULL;
Timo Rothenpieler2a428db2014-11-29 23:04:371897
Hendrik Leppkesbff6d982017-11-11 15:51:581898#if CONFIG_D3D11VA
1899 if (ctx->d3d11_device) {
1900 ID3D11Device_Release(ctx->d3d11_device);
1901 ctx->d3d11_device = NULL;
1902 }
1903#endif
1904
Timo Rothenpielera66835b2016-10-10 10:55:591905 nvenc_free_functions(&dl_fn->nvenc_dl);
1906 cuda_free_functions(&dl_fn->cuda_dl);
Andrey Turkinb6933532016-05-25 16:57:111907
1908 dl_fn->nvenc_device_count = 0;
1909
Andrey Turkinb6933532016-05-25 16:57:111910 av_log(avctx, AV_LOG_VERBOSE, "Nvenc unloaded\n");
1911
1912 return 0;
1913}
1914
1915av_cold int ff_nvenc_encode_init(AVCodecContext *avctx)
1916{
Andrey Turkin0d021cc2016-05-29 12:23:261917 NvencContext *ctx = avctx->priv_data;
1918 int ret;
Andrey Turkinb6933532016-05-25 16:57:111919
Hendrik Leppkesbff6d982017-11-11 15:51:581920 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Timo Rothenpieler2e700b02018-05-07 20:39:201921 AVHWFramesContext *frames_ctx;
1922 if (!avctx->hw_frames_ctx) {
Andrey Turkin0d021cc2016-05-29 12:23:261923 av_log(avctx, AV_LOG_ERROR,
Timo Rothenpieler2e700b02018-05-07 20:39:201924 "hw_frames_ctx must be set when using GPU frames as input\n");
Andrey Turkin0d021cc2016-05-29 12:23:261925 return AVERROR(EINVAL);
1926 }
Timo Rothenpieler2e700b02018-05-07 20:39:201927 frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
1928 if (frames_ctx->format != avctx->pix_fmt) {
1929 av_log(avctx, AV_LOG_ERROR,
1930 "hw_frames_ctx must match the GPU frame type\n");
1931 return AVERROR(EINVAL);
1932 }
1933 ctx->data_pix_fmt = frames_ctx->sw_format;
Andrey Turkin0d021cc2016-05-29 12:23:261934 } else {
1935 ctx->data_pix_fmt = avctx->pix_fmt;
1936 }
Andrey Turkinb6933532016-05-25 16:57:111937
James Almer827d6fe2020-06-09 21:31:321938 ctx->frame = av_frame_alloc();
1939 if (!ctx->frame)
1940 return AVERROR(ENOMEM);
1941
Andrey Turkin0d021cc2016-05-29 12:23:261942 if ((ret = nvenc_load_libraries(avctx)) < 0)
1943 return ret;
Andrey Turkinb6933532016-05-25 16:57:111944
Andrey Turkin0d021cc2016-05-29 12:23:261945 if ((ret = nvenc_setup_device(avctx)) < 0)
1946 return ret;
Andrey Turkinb6933532016-05-25 16:57:111947
Andrey Turkin0d021cc2016-05-29 12:23:261948 if ((ret = nvenc_setup_encoder(avctx)) < 0)
1949 return ret;
Andrey Turkinb6933532016-05-25 16:57:111950
Andrey Turkin0d021cc2016-05-29 12:23:261951 if ((ret = nvenc_setup_surfaces(avctx)) < 0)
1952 return ret;
Andrey Turkinb6933532016-05-25 16:57:111953
1954 if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
Andrey Turkin0d021cc2016-05-29 12:23:261955 if ((ret = nvenc_setup_extradata(avctx)) < 0)
1956 return ret;
Andrey Turkinb6933532016-05-25 16:57:111957 }
Timo Rothenpieler2a428db2014-11-29 23:04:371958
Timo Rothenpieler2a428db2014-11-29 23:04:371959 return 0;
1960}
1961
Andrey Turkine1691c42016-05-20 15:37:001962static NvencSurface *get_free_frame(NvencContext *ctx)
Andrey Turkin82d705e2016-05-20 14:49:241963{
Ben Chang8de34582017-04-25 21:57:561964 NvencSurface *tmp_surf;
Andrey Turkin82d705e2016-05-20 14:49:241965
Anton Khirnov587545c2022-01-06 15:59:491966 if (av_fifo_read(ctx->unused_surface_queue, &tmp_surf, 1) < 0)
Ben Chang8de34582017-04-25 21:57:561967 // queue empty
1968 return NULL;
Andrey Turkin82d705e2016-05-20 14:49:241969
Ben Chang8de34582017-04-25 21:57:561970 return tmp_surf;
Andrey Turkin82d705e2016-05-20 14:49:241971}
1972
Timo Rothenpieler96cba1c2016-09-07 13:49:281973static int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *nv_surface,
1974 NV_ENC_LOCK_INPUT_BUFFER *lock_buffer_params, const AVFrame *frame)
Andrey Turkin82d705e2016-05-20 14:49:241975{
Timo Rothenpieler96cba1c2016-09-07 13:49:281976 int dst_linesize[4] = {
1977 lock_buffer_params->pitch,
1978 lock_buffer_params->pitch,
1979 lock_buffer_params->pitch,
1980 lock_buffer_params->pitch
1981 };
1982 uint8_t *dst_data[4];
1983 int ret;
Andrey Turkin82d705e2016-05-20 14:49:241984
Timo Rothenpieler96cba1c2016-09-07 13:49:281985 if (frame->format == AV_PIX_FMT_YUV420P)
1986 dst_linesize[1] = dst_linesize[2] >>= 1;
Andrey Turkin82d705e2016-05-20 14:49:241987
Timo Rothenpieler96cba1c2016-09-07 13:49:281988 ret = av_image_fill_pointers(dst_data, frame->format, nv_surface->height,
1989 lock_buffer_params->bufferDataPtr, dst_linesize);
1990 if (ret < 0)
1991 return ret;
Andrey Turkin82d705e2016-05-20 14:49:241992
Timo Rothenpieler96cba1c2016-09-07 13:49:281993 if (frame->format == AV_PIX_FMT_YUV420P)
1994 FFSWAP(uint8_t*, dst_data[1], dst_data[2]);
Andrey Turkin82d705e2016-05-20 14:49:241995
Timo Rothenpieler96cba1c2016-09-07 13:49:281996 av_image_copy(dst_data, dst_linesize,
1997 (const uint8_t**)frame->data, frame->linesize, frame->format,
Timo Rothenpieler8ebe1dd2016-09-08 17:08:311998 avctx->width, avctx->height);
Andrey Turkin82d705e2016-05-20 14:49:241999
2000 return 0;
2001}
2002
Andrey Turkina8cf25d2016-05-20 22:08:062003static int nvenc_find_free_reg_resource(AVCodecContext *avctx)
2004{
2005 NvencContext *ctx = avctx->priv_data;
2006 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2007 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
Timo Rothenpieler48e52e42018-01-28 11:51:202008 NVENCSTATUS nv_status;
Andrey Turkina8cf25d2016-05-20 22:08:062009
Timo Rothenpieler23ed1472019-04-24 17:00:252010 int i, first_round;
Andrey Turkina8cf25d2016-05-20 22:08:062011
2012 if (ctx->nb_registered_frames == FF_ARRAY_ELEMS(ctx->registered_frames)) {
Timo Rothenpieler23ed1472019-04-24 17:00:252013 for (first_round = 1; first_round >= 0; first_round--) {
Timo Rothenpieler2e254bb2019-04-24 20:47:242014 for (i = 0; i < ctx->nb_registered_frames; i++) {
2015 if (!ctx->registered_frames[i].mapped) {
2016 if (ctx->registered_frames[i].regptr) {
2017 if (first_round)
2018 continue;
2019 nv_status = p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr);
2020 if (nv_status != NV_ENC_SUCCESS)
2021 return nvenc_print_error(avctx, nv_status, "Failed unregistering unused input resource");
2022 ctx->registered_frames[i].ptr = NULL;
2023 ctx->registered_frames[i].regptr = NULL;
2024 }
2025 return i;
Andrey Turkina8cf25d2016-05-20 22:08:062026 }
Andrey Turkina8cf25d2016-05-20 22:08:062027 }
2028 }
2029 } else {
2030 return ctx->nb_registered_frames++;
2031 }
2032
2033 av_log(avctx, AV_LOG_ERROR, "Too many registered CUDA frames\n");
2034 return AVERROR(ENOMEM);
2035}
2036
2037static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame)
2038{
2039 NvencContext *ctx = avctx->priv_data;
2040 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2041 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2042
Timo Rothenpieler2e700b02018-05-07 20:39:202043 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frame->hw_frames_ctx->data;
Timo Rothenpieler0b13c342022-01-10 14:41:502044 NV_ENC_REGISTER_RESOURCE reg = { 0 };
Andrey Turkina8cf25d2016-05-20 22:08:062045 int i, idx, ret;
2046
2047 for (i = 0; i < ctx->nb_registered_frames; i++) {
Hendrik Leppkesbff6d982017-11-11 15:51:582048 if (avctx->pix_fmt == AV_PIX_FMT_CUDA && ctx->registered_frames[i].ptr == frame->data[0])
2049 return i;
2050 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:062051 return i;
2052 }
2053
2054 idx = nvenc_find_free_reg_resource(avctx);
2055 if (idx < 0)
2056 return idx;
2057
2058 reg.version = NV_ENC_REGISTER_RESOURCE_VER;
Timo Rothenpieler2e700b02018-05-07 20:39:202059 reg.width = frames_ctx->width;
2060 reg.height = frames_ctx->height;
Andrey Turkina8cf25d2016-05-20 22:08:062061 reg.pitch = frame->linesize[0];
2062 reg.resourceToRegister = frame->data[0];
2063
Hendrik Leppkesbff6d982017-11-11 15:51:582064 if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
2065 reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR;
2066 }
2067 else if (avctx->pix_fmt == AV_PIX_FMT_D3D11) {
2068 reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX;
2069 reg.subResourceIndex = (intptr_t)frame->data[1];
2070 }
2071
Timo Rothenpieler2e700b02018-05-07 20:39:202072 reg.bufferFormat = nvenc_map_buffer_format(frames_ctx->sw_format);
Philip Langdale27038692016-11-25 19:11:452073 if (reg.bufferFormat == NV_ENC_BUFFER_FORMAT_UNDEFINED) {
2074 av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n",
Timo Rothenpieler2e700b02018-05-07 20:39:202075 av_get_pix_fmt_name(frames_ctx->sw_format));
Philip Langdale27038692016-11-25 19:11:452076 return AVERROR(EINVAL);
2077 }
2078
Andrey Turkina8cf25d2016-05-20 22:08:062079 ret = p_nvenc->nvEncRegisterResource(ctx->nvencoder, &reg);
2080 if (ret != NV_ENC_SUCCESS) {
2081 nvenc_print_error(avctx, ret, "Error registering an input resource");
2082 return AVERROR_UNKNOWN;
2083 }
2084
Hendrik Leppkesbff6d982017-11-11 15:51:582085 ctx->registered_frames[idx].ptr = frame->data[0];
2086 ctx->registered_frames[idx].ptr_index = reg.subResourceIndex;
2087 ctx->registered_frames[idx].regptr = reg.registeredResource;
Andrey Turkina8cf25d2016-05-20 22:08:062088 return idx;
2089}
2090
Andrey Turkin82d705e2016-05-20 14:49:242091static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame,
Andrey Turkine1691c42016-05-20 15:37:002092 NvencSurface *nvenc_frame)
Andrey Turkin82d705e2016-05-20 14:49:242093{
2094 NvencContext *ctx = avctx->priv_data;
2095 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2096 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2097
2098 int res;
2099 NVENCSTATUS nv_status;
Andrey Turkin82d705e2016-05-20 14:49:242100
Hendrik Leppkesbff6d982017-11-11 15:51:582101 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Andrey Turkina8cf25d2016-05-20 22:08:062102 int reg_idx = nvenc_register_frame(avctx, frame);
2103 if (reg_idx < 0) {
Hendrik Leppkesbff6d982017-11-11 15:51:582104 av_log(avctx, AV_LOG_ERROR, "Could not register an input HW frame\n");
Andrey Turkina8cf25d2016-05-20 22:08:062105 return reg_idx;
2106 }
Andrey Turkin82d705e2016-05-20 14:49:242107
Andrey Turkina8cf25d2016-05-20 22:08:062108 res = av_frame_ref(nvenc_frame->in_ref, frame);
2109 if (res < 0)
2110 return res;
2111
Timo Rothenpielerbbe1b212018-01-26 19:16:532112 if (!ctx->registered_frames[reg_idx].mapped) {
2113 ctx->registered_frames[reg_idx].in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER;
2114 ctx->registered_frames[reg_idx].in_map.registeredResource = ctx->registered_frames[reg_idx].regptr;
2115 nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &ctx->registered_frames[reg_idx].in_map);
2116 if (nv_status != NV_ENC_SUCCESS) {
2117 av_frame_unref(nvenc_frame->in_ref);
2118 return nvenc_print_error(avctx, nv_status, "Error mapping an input resource");
2119 }
Andrey Turkina8cf25d2016-05-20 22:08:062120 }
2121
Timo Rothenpielerbbe1b212018-01-26 19:16:532122 ctx->registered_frames[reg_idx].mapped += 1;
2123
Andrey Turkina8cf25d2016-05-20 22:08:062124 nvenc_frame->reg_idx = reg_idx;
Timo Rothenpielerbbe1b212018-01-26 19:16:532125 nvenc_frame->input_surface = ctx->registered_frames[reg_idx].in_map.mappedResource;
2126 nvenc_frame->format = ctx->registered_frames[reg_idx].in_map.mappedBufferFmt;
Timo Rothenpielerfa3ecad2016-09-07 16:15:222127 nvenc_frame->pitch = frame->linesize[0];
Timo Rothenpielerbbe1b212018-01-26 19:16:532128
Andrey Turkina8cf25d2016-05-20 22:08:062129 return 0;
2130 } else {
2131 NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 };
2132
2133 lockBufferParams.version = NV_ENC_LOCK_INPUT_BUFFER_VER;
2134 lockBufferParams.inputBuffer = nvenc_frame->input_surface;
2135
2136 nv_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams);
2137 if (nv_status != NV_ENC_SUCCESS) {
2138 return nvenc_print_error(avctx, nv_status, "Failed locking nvenc input buffer");
2139 }
2140
Timo Rothenpielerfa3ecad2016-09-07 16:15:222141 nvenc_frame->pitch = lockBufferParams.pitch;
Andrey Turkina8cf25d2016-05-20 22:08:062142 res = nvenc_copy_frame(avctx, nvenc_frame, &lockBufferParams, frame);
2143
2144 nv_status = p_nvenc->nvEncUnlockInputBuffer(ctx->nvencoder, nvenc_frame->input_surface);
2145 if (nv_status != NV_ENC_SUCCESS) {
2146 return nvenc_print_error(avctx, nv_status, "Failed unlocking input buffer!");
2147 }
2148
2149 return res;
Andrey Turkin82d705e2016-05-20 14:49:242150 }
Andrey Turkin82d705e2016-05-20 14:49:242151}
2152
2153static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
Roman Arzumanyan5a88e8c2018-03-22 09:30:062154 NV_ENC_PIC_PARAMS *params,
Limin Wang4ef766e2020-06-15 14:08:402155 NV_ENC_SEI_PAYLOAD *sei_data,
2156 int sei_count)
Andrey Turkin82d705e2016-05-20 14:49:242157{
2158 NvencContext *ctx = avctx->priv_data;
2159
2160 switch (avctx->codec->id) {
2161 case AV_CODEC_ID_H264:
Andrey Turkin2f53b5b2016-05-29 12:50:062162 params->codecPicParams.h264PicParams.sliceMode =
2163 ctx->encode_config.encodeCodecConfig.h264Config.sliceMode;
2164 params->codecPicParams.h264PicParams.sliceModeData =
2165 ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData;
Limin Wang4ef766e2020-06-15 14:08:402166 if (sei_count > 0) {
Roman Arzumanyan5a88e8c2018-03-22 09:30:062167 params->codecPicParams.h264PicParams.seiPayloadArray = sei_data;
Limin Wang4ef766e2020-06-15 14:08:402168 params->codecPicParams.h264PicParams.seiPayloadArrayCnt = sei_count;
Roman Arzumanyan5a88e8c2018-03-22 09:30:062169 }
2170
Andrey Turkin82d705e2016-05-20 14:49:242171 break;
Andrey Turkin2f53b5b2016-05-29 12:50:062172 case AV_CODEC_ID_HEVC:
2173 params->codecPicParams.hevcPicParams.sliceMode =
2174 ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode;
2175 params->codecPicParams.hevcPicParams.sliceModeData =
2176 ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData;
Limin Wang4ef766e2020-06-15 14:08:402177 if (sei_count > 0) {
Roman Arzumanyan5a88e8c2018-03-22 09:30:062178 params->codecPicParams.hevcPicParams.seiPayloadArray = sei_data;
Limin Wang4ef766e2020-06-15 14:08:402179 params->codecPicParams.hevcPicParams.seiPayloadArrayCnt = sei_count;
Roman Arzumanyan5a88e8c2018-03-22 09:30:062180 }
2181
Andrey Turkin2f53b5b2016-05-29 12:50:062182 break;
Timo Rothenpieler5c288a42022-11-05 20:17:372183#if CONFIG_AV1_NVENC_ENCODER
2184 case AV_CODEC_ID_AV1:
2185 params->codecPicParams.av1PicParams.numTileColumns =
2186 ctx->encode_config.encodeCodecConfig.av1Config.numTileColumns;
2187 params->codecPicParams.av1PicParams.numTileRows =
2188 ctx->encode_config.encodeCodecConfig.av1Config.numTileRows;
2189 if (sei_count > 0) {
2190 params->codecPicParams.av1PicParams.obuPayloadArray = sei_data;
2191 params->codecPicParams.av1PicParams.obuPayloadArrayCnt = sei_count;
2192 }
2193
2194 break;
2195#endif
Andrey Turkin82d705e2016-05-20 14:49:242196 }
2197}
2198
Anton Khirnov35538092022-07-12 09:25:092199static void reorder_queue_enqueue(AVFifo *queue, const AVCodecContext *avctx,
2200 const AVFrame *frame, AVBufferRef **opaque_ref)
Andrey Turkin2f53b5b2016-05-29 12:50:062201{
Anton Khirnov35538092022-07-12 09:25:092202 FrameData fd;
2203
2204 fd.pts = frame->pts;
2205 fd.duration = frame->duration;
2206 fd.reordered_opaque = frame->reordered_opaque;
2207 fd.frame_opaque = frame->opaque;
2208 fd.frame_opaque_ref = *opaque_ref;
2209
2210 *opaque_ref = NULL;
2211
2212 av_fifo_write(queue, &fd, 1);
Andrey Turkin2f53b5b2016-05-29 12:50:062213}
2214
Anton Khirnov35538092022-07-12 09:25:092215static int64_t reorder_queue_dequeue(AVFifo *queue, AVCodecContext *avctx,
2216 AVPacket *pkt)
Andrey Turkin2f53b5b2016-05-29 12:50:062217{
Anton Khirnov35538092022-07-12 09:25:092218 FrameData fd;
Andrey Turkin2f53b5b2016-05-29 12:50:062219
Anton Khirnov35538092022-07-12 09:25:092220 // The following call might fail if the queue is empty.
2221 if (av_fifo_read(queue, &fd, 1) < 0)
2222 return AV_NOPTS_VALUE;
2223
2224 if (pkt) {
2225 avctx->reordered_opaque = fd.reordered_opaque;
2226 pkt->duration = fd.duration;
2227
2228 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
2229 pkt->opaque = fd.frame_opaque;
2230 pkt->opaque_ref = fd.frame_opaque_ref;
2231 fd.frame_opaque_ref = NULL;
2232 }
2233 }
2234
2235 av_buffer_unref(&fd.frame_opaque_ref);
2236
2237 return fd.pts;
Andrey Turkin2f53b5b2016-05-29 12:50:062238}
2239
Andrey Turkind3463912016-05-29 12:34:382240static int nvenc_set_timestamp(AVCodecContext *avctx,
2241 NV_ENC_LOCK_BITSTREAM *params,
2242 AVPacket *pkt)
2243{
2244 NvencContext *ctx = avctx->priv_data;
Anton Khirnov35538092022-07-12 09:25:092245 int64_t dts;
Andrey Turkind3463912016-05-29 12:34:382246
2247 pkt->pts = params->outputTimeStamp;
Timo Rothenpielere5babcc2016-05-31 16:59:352248
Anton Khirnov35538092022-07-12 09:25:092249 dts = reorder_queue_dequeue(ctx->reorder_queue, avctx, pkt);
2250
Timo Rothenpieleraa3d9822022-11-05 20:20:062251 if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) {
Anton Khirnov35538092022-07-12 09:25:092252 pkt->dts = dts - FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1);
Timo Rothenpieleraa3d9822022-11-05 20:20:062253 } else {
2254 pkt->dts = pkt->pts;
2255 }
Andrey Turkind3463912016-05-29 12:34:382256
Andrey Turkind3463912016-05-29 12:34:382257 return 0;
2258}
2259
Andrey Turkine1691c42016-05-20 15:37:002260static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSurface *tmpoutsurf)
Timo Rothenpieler2a428db2014-11-29 23:04:372261{
2262 NvencContext *ctx = avctx->priv_data;
2263 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2264 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2265
Timo Rothenpieler2a428db2014-11-29 23:04:372266 NV_ENC_LOCK_BITSTREAM lock_params = { 0 };
2267 NVENCSTATUS nv_status;
2268 int res = 0;
2269
Lucas Cooperfd554702016-03-07 23:47:562270 enum AVPictureType pict_type;
2271
Timo Rothenpieler2a428db2014-11-29 23:04:372272 lock_params.version = NV_ENC_LOCK_BITSTREAM_VER;
2273
2274 lock_params.doNotWait = 0;
2275 lock_params.outputBitstream = tmpoutsurf->output_surface;
Timo Rothenpieler2a428db2014-11-29 23:04:372276
2277 nv_status = p_nvenc->nvEncLockBitstream(ctx->nvencoder, &lock_params);
2278 if (nv_status != NV_ENC_SUCCESS) {
Andrey Turkine1691c42016-05-20 15:37:002279 res = nvenc_print_error(avctx, nv_status, "Failed locking bitstream buffer");
Timo Rothenpieler2a428db2014-11-29 23:04:372280 goto error;
2281 }
2282
James Almer238e08b2021-03-12 23:50:012283 res = ff_get_encode_buffer(avctx, pkt, lock_params.bitstreamSizeInBytes, 0);
Timo Rothenpieler4fb6ce22019-11-17 00:27:442284
2285 if (res < 0) {
Timo Rothenpieler2a428db2014-11-29 23:04:372286 p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
2287 goto error;
2288 }
2289
2290 memcpy(pkt->data, lock_params.bitstreamBufferPtr, lock_params.bitstreamSizeInBytes);
2291
2292 nv_status = p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
Timo Rothenpieler48e52e42018-01-28 11:51:202293 if (nv_status != NV_ENC_SUCCESS) {
2294 res = nvenc_print_error(avctx, nv_status, "Failed unlocking bitstream buffer, expect the gates of mordor to open");
2295 goto error;
2296 }
Timo Rothenpieler2a428db2014-11-29 23:04:372297
Andrey Turkina8cf25d2016-05-20 22:08:062298
Hendrik Leppkesbff6d982017-11-11 15:51:582299 if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11) {
Timo Rothenpielerbbe1b212018-01-26 19:16:532300 ctx->registered_frames[tmpoutsurf->reg_idx].mapped -= 1;
2301 if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped == 0) {
Timo Rothenpieler48e52e42018-01-28 11:51:202302 nv_status = p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->registered_frames[tmpoutsurf->reg_idx].in_map.mappedResource);
2303 if (nv_status != NV_ENC_SUCCESS) {
2304 res = nvenc_print_error(avctx, nv_status, "Failed unmapping input resource");
2305 goto error;
2306 }
Timo Rothenpielerbbe1b212018-01-26 19:16:532307 } else if (ctx->registered_frames[tmpoutsurf->reg_idx].mapped < 0) {
2308 res = AVERROR_BUG;
2309 goto error;
2310 }
2311
Andrey Turkina8cf25d2016-05-20 22:08:062312 av_frame_unref(tmpoutsurf->in_ref);
Andrey Turkina8cf25d2016-05-20 22:08:062313
2314 tmpoutsurf->input_surface = NULL;
2315 }
2316
Timo Rothenpieler2a428db2014-11-29 23:04:372317 switch (lock_params.pictureType) {
2318 case NV_ENC_PIC_TYPE_IDR:
2319 pkt->flags |= AV_PKT_FLAG_KEY;
2320 case NV_ENC_PIC_TYPE_I:
Lucas Cooperfd554702016-03-07 23:47:562321 pict_type = AV_PICTURE_TYPE_I;
Timo Rothenpieler2a428db2014-11-29 23:04:372322 break;
2323 case NV_ENC_PIC_TYPE_P:
Lucas Cooperfd554702016-03-07 23:47:562324 pict_type = AV_PICTURE_TYPE_P;
Timo Rothenpieler2a428db2014-11-29 23:04:372325 break;
2326 case NV_ENC_PIC_TYPE_B:
Lucas Cooperfd554702016-03-07 23:47:562327 pict_type = AV_PICTURE_TYPE_B;
Timo Rothenpieler2a428db2014-11-29 23:04:372328 break;
2329 case NV_ENC_PIC_TYPE_BI:
Lucas Cooperfd554702016-03-07 23:47:562330 pict_type = AV_PICTURE_TYPE_BI;
Timo Rothenpieler2a428db2014-11-29 23:04:372331 break;
2332 default:
2333 av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered, expect the output to be broken.\n");
2334 av_log(avctx, AV_LOG_ERROR, "Please report this error and include as much information on how to reproduce it as possible.\n");
2335 res = AVERROR_EXTERNAL;
2336 goto error;
Lucas Cooperfd554702016-03-07 23:47:562337 }
2338
Lucas Cooperfd554702016-03-07 23:47:562339 ff_side_data_set_encoder_stats(pkt,
2340 (lock_params.frameAvgQP - 1) * FF_QP2LAMBDA, NULL, 0, pict_type);
Timo Rothenpieler2a428db2014-11-29 23:04:372341
Andrey Turkind3463912016-05-29 12:34:382342 res = nvenc_set_timestamp(avctx, &lock_params, pkt);
2343 if (res < 0)
2344 goto error2;
Timo Rothenpieler2a428db2014-11-29 23:04:372345
Timo Rothenpieler2a428db2014-11-29 23:04:372346 return 0;
2347
2348error:
Anton Khirnov35538092022-07-12 09:25:092349 reorder_queue_dequeue(ctx->reorder_queue, avctx, NULL);
Timo Rothenpieler2a428db2014-11-29 23:04:372350
Andrey Turkind3463912016-05-29 12:34:382351error2:
Timo Rothenpieler2a428db2014-11-29 23:04:372352 return res;
2353}
2354
Andrey Turkin2f53b5b2016-05-29 12:50:062355static int output_ready(AVCodecContext *avctx, int flush)
Andrey Turkincfb49fc2016-05-20 16:13:202356{
Andrey Turkin2f53b5b2016-05-29 12:50:062357 NvencContext *ctx = avctx->priv_data;
Andrey Turkincfb49fc2016-05-20 16:13:202358 int nb_ready, nb_pending;
2359
Anton Khirnov587545c2022-01-06 15:59:492360 nb_ready = av_fifo_can_read(ctx->output_surface_ready_queue);
2361 nb_pending = av_fifo_can_read(ctx->output_surface_queue);
Andrey Turkin2f53b5b2016-05-29 12:50:062362 if (flush)
2363 return nb_ready > 0;
2364 return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth);
Andrey Turkincfb49fc2016-05-20 16:13:202365}
2366
Timo Rothenpieler57de8062021-06-04 16:40:172367static int prepare_sei_data_array(AVCodecContext *avctx, const AVFrame *frame)
2368{
2369 NvencContext *ctx = avctx->priv_data;
2370 int sei_count = 0;
2371 int i, res;
2372
2373 if (ctx->a53_cc && av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC)) {
2374 void *a53_data = NULL;
2375 size_t a53_size = 0;
2376
2377 if (ff_alloc_a53_sei(frame, 0, &a53_data, &a53_size) < 0) {
2378 av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
2379 }
2380
2381 if (a53_data) {
2382 void *tmp = av_fast_realloc(ctx->sei_data,
2383 &ctx->sei_data_size,
2384 (sei_count + 1) * sizeof(*ctx->sei_data));
2385 if (!tmp) {
2386 av_free(a53_data);
2387 res = AVERROR(ENOMEM);
2388 goto error;
2389 } else {
2390 ctx->sei_data = tmp;
2391 ctx->sei_data[sei_count].payloadSize = (uint32_t)a53_size;
Timo Rothenpieler57de8062021-06-04 16:40:172392 ctx->sei_data[sei_count].payload = (uint8_t*)a53_data;
Timo Rothenpieler6362b8c2022-11-05 20:18:362393
2394#if CONFIG_AV1_NVENC_ENCODER
2395 if (avctx->codec->id == AV_CODEC_ID_AV1)
2396 ctx->sei_data[sei_count].payloadType = AV1_METADATA_TYPE_ITUT_T35;
2397 else
2398#endif
2399 ctx->sei_data[sei_count].payloadType = SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35;
2400
Timo Rothenpieler57de8062021-06-04 16:40:172401 sei_count++;
2402 }
2403 }
2404 }
2405
2406 if (ctx->s12m_tc && av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE)) {
2407 void *tc_data = NULL;
2408 size_t tc_size = 0;
2409
2410 if (ff_alloc_timecode_sei(frame, avctx->framerate, 0, &tc_data, &tc_size) < 0) {
2411 av_log(ctx, AV_LOG_ERROR, "Not enough memory for timecode sei, skipping\n");
2412 }
2413
2414 if (tc_data) {
2415 void *tmp = av_fast_realloc(ctx->sei_data,
2416 &ctx->sei_data_size,
2417 (sei_count + 1) * sizeof(*ctx->sei_data));
2418 if (!tmp) {
2419 av_free(tc_data);
2420 res = AVERROR(ENOMEM);
2421 goto error;
2422 } else {
2423 ctx->sei_data = tmp;
2424 ctx->sei_data[sei_count].payloadSize = (uint32_t)tc_size;
Timo Rothenpieler57de8062021-06-04 16:40:172425 ctx->sei_data[sei_count].payload = (uint8_t*)tc_data;
Timo Rothenpieler6362b8c2022-11-05 20:18:362426
2427#if CONFIG_AV1_NVENC_ENCODER
2428 if (avctx->codec->id == AV_CODEC_ID_AV1)
2429 ctx->sei_data[sei_count].payloadType = AV1_METADATA_TYPE_TIMECODE;
2430 else
2431#endif
2432 ctx->sei_data[sei_count].payloadType = SEI_TYPE_TIME_CODE;
2433
Timo Rothenpieler57de8062021-06-04 16:40:172434 sei_count++;
2435 }
2436 }
2437 }
2438
Limin Wang0c8741f2021-12-24 04:32:472439 if (!ctx->udu_sei)
2440 return sei_count;
2441
Timo Rothenpieler57de8062021-06-04 16:40:172442 for (i = 0; i < frame->nb_side_data; i++) {
2443 AVFrameSideData *side_data = frame->side_data[i];
2444 void *tmp;
2445
2446 if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED)
2447 continue;
2448
2449 tmp = av_fast_realloc(ctx->sei_data,
2450 &ctx->sei_data_size,
2451 (sei_count + 1) * sizeof(*ctx->sei_data));
2452 if (!tmp) {
2453 res = AVERROR(ENOMEM);
2454 goto error;
2455 } else {
2456 ctx->sei_data = tmp;
2457 ctx->sei_data[sei_count].payloadSize = side_data->size;
2458 ctx->sei_data[sei_count].payloadType = SEI_TYPE_USER_DATA_UNREGISTERED;
2459 ctx->sei_data[sei_count].payload = av_memdup(side_data->data, side_data->size);
2460
2461 if (!ctx->sei_data[sei_count].payload) {
2462 res = AVERROR(ENOMEM);
2463 goto error;
2464 }
2465
2466 sei_count++;
2467 }
2468 }
2469
2470 return sei_count;
2471
2472error:
2473 for (i = 0; i < sei_count; i++)
2474 av_freep(&(ctx->sei_data[i].payload));
2475
2476 return res;
2477}
2478
Timo Rothenpielerfdbb4b92018-05-03 16:57:402479static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
Miroslav Slugeň952421c2017-02-12 18:53:582480{
2481 NvencContext *ctx = avctx->priv_data;
2482 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
2483 NVENCSTATUS ret;
2484
2485 NV_ENC_RECONFIGURE_PARAMS params = { 0 };
2486 int needs_reconfig = 0;
2487 int needs_encode_config = 0;
pkviet15537512018-05-03 00:15:522488 int reconfig_bitrate = 0, reconfig_dar = 0;
Miroslav Slugeň952421c2017-02-12 18:53:582489 int dw, dh;
2490
2491 params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
2492 params.reInitEncodeParams = ctx->init_encode_params;
2493
2494 compute_dar(avctx, &dw, &dh);
2495 if (dw != ctx->init_encode_params.darWidth || dh != ctx->init_encode_params.darHeight) {
2496 av_log(avctx, AV_LOG_VERBOSE,
2497 "aspect ratio change (DAR): %d:%d -> %d:%d\n",
2498 ctx->init_encode_params.darWidth,
2499 ctx->init_encode_params.darHeight, dw, dh);
2500
2501 params.reInitEncodeParams.darHeight = dh;
2502 params.reInitEncodeParams.darWidth = dw;
2503
2504 needs_reconfig = 1;
pkviet15537512018-05-03 00:15:522505 reconfig_dar = 1;
2506 }
2507
2508 if (ctx->rc != NV_ENC_PARAMS_RC_CONSTQP && ctx->support_dyn_bitrate) {
2509 if (avctx->bit_rate > 0 && params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate != avctx->bit_rate) {
2510 av_log(avctx, AV_LOG_VERBOSE,
2511 "avg bitrate change: %d -> %d\n",
2512 params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate,
2513 (uint32_t)avctx->bit_rate);
2514
2515 params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate = avctx->bit_rate;
2516 reconfig_bitrate = 1;
2517 }
2518
2519 if (avctx->rc_max_rate > 0 && ctx->encode_config.rcParams.maxBitRate != avctx->rc_max_rate) {
2520 av_log(avctx, AV_LOG_VERBOSE,
2521 "max bitrate change: %d -> %d\n",
2522 params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate,
2523 (uint32_t)avctx->rc_max_rate);
2524
2525 params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate = avctx->rc_max_rate;
2526 reconfig_bitrate = 1;
2527 }
2528
2529 if (avctx->rc_buffer_size > 0 && ctx->encode_config.rcParams.vbvBufferSize != avctx->rc_buffer_size) {
2530 av_log(avctx, AV_LOG_VERBOSE,
2531 "vbv buffer size change: %d -> %d\n",
2532 params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize,
2533 avctx->rc_buffer_size);
2534
2535 params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize = avctx->rc_buffer_size;
2536 reconfig_bitrate = 1;
2537 }
2538
2539 if (reconfig_bitrate) {
2540 params.resetEncoder = 1;
2541 params.forceIDR = 1;
2542
2543 needs_encode_config = 1;
2544 needs_reconfig = 1;
2545 }
Miroslav Slugeň952421c2017-02-12 18:53:582546 }
2547
2548 if (!needs_encode_config)
2549 params.reInitEncodeParams.encodeConfig = NULL;
2550
2551 if (needs_reconfig) {
2552 ret = p_nvenc->nvEncReconfigureEncoder(ctx->nvencoder, &params);
2553 if (ret != NV_ENC_SUCCESS) {
2554 nvenc_print_error(avctx, ret, "failed to reconfigure nvenc");
2555 } else {
pkviet15537512018-05-03 00:15:522556 if (reconfig_dar) {
2557 ctx->init_encode_params.darHeight = dh;
2558 ctx->init_encode_params.darWidth = dw;
2559 }
2560
2561 if (reconfig_bitrate) {
2562 ctx->encode_config.rcParams.averageBitRate = params.reInitEncodeParams.encodeConfig->rcParams.averageBitRate;
2563 ctx->encode_config.rcParams.maxBitRate = params.reInitEncodeParams.encodeConfig->rcParams.maxBitRate;
2564 ctx->encode_config.rcParams.vbvBufferSize = params.reInitEncodeParams.encodeConfig->rcParams.vbvBufferSize;
2565 }
2566
Miroslav Slugeň952421c2017-02-12 18:53:582567 }
2568 }
Miroslav Slugeň952421c2017-02-12 18:53:582569}
2570
James Almer827d6fe2020-06-09 21:31:322571static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Timo Rothenpieler2a428db2014-11-29 23:04:372572{
2573 NVENCSTATUS nv_status;
Timo Rothenpielerd0961d32017-09-02 17:42:132574 NvencSurface *tmp_out_surf, *in_surf;
Hendrik Leppkes6fcbf392017-11-11 15:13:242575 int res, res2;
Limin Wang4ef766e2020-06-15 14:08:402576 int sei_count = 0;
2577 int i;
Timo Rothenpieler2a428db2014-11-29 23:04:372578
Anton Khirnov35538092022-07-12 09:25:092579 AVBufferRef *opaque_ref = NULL;
2580
Timo Rothenpieler2a428db2014-11-29 23:04:372581 NvencContext *ctx = avctx->priv_data;
2582 NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
2583 NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
2584
2585 NV_ENC_PIC_PARAMS pic_params = { 0 };
2586 pic_params.version = NV_ENC_PIC_PARAMS_VER;
2587
Hendrik Leppkesbff6d982017-11-11 15:51:582588 if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
Timo Rothenpielera56d0492017-09-02 17:30:212589 return AVERROR(EINVAL);
2590
James Almer827d6fe2020-06-09 21:31:322591 if (frame && frame->buf[0]) {
Timo Rothenpielerd0961d32017-09-02 17:42:132592 in_surf = get_free_frame(ctx);
2593 if (!in_surf)
Timo Rothenpielera56d0492017-09-02 17:30:212594 return AVERROR(EAGAIN);
Timo Rothenpieler2a428db2014-11-29 23:04:372595
Hendrik Leppkes6fcbf392017-11-11 15:13:242596 res = nvenc_push_context(avctx);
2597 if (res < 0)
2598 return res;
Timo Rothenpielerbe74ba62017-02-13 21:59:462599
Timo Rothenpielerfdbb4b92018-05-03 16:57:402600 reconfig_encoder(avctx, frame);
2601
Timo Rothenpielerd0961d32017-09-02 17:42:132602 res = nvenc_upload_frame(avctx, frame, in_surf);
Timo Rothenpielerbe74ba62017-02-13 21:59:462603
Hendrik Leppkes6fcbf392017-11-11 15:13:242604 res2 = nvenc_pop_context(avctx);
2605 if (res2 < 0)
2606 return res2;
Timo Rothenpielerbe74ba62017-02-13 21:59:462607
Timo Rothenpielera56d0492017-09-02 17:30:212608 if (res)
Andrey Turkin82d705e2016-05-20 14:49:242609 return res;
Timo Rothenpieler2a428db2014-11-29 23:04:372610
Timo Rothenpielerd0961d32017-09-02 17:42:132611 pic_params.inputBuffer = in_surf->input_surface;
2612 pic_params.bufferFmt = in_surf->format;
2613 pic_params.inputWidth = in_surf->width;
2614 pic_params.inputHeight = in_surf->height;
2615 pic_params.inputPitch = in_surf->pitch;
2616 pic_params.outputBitstream = in_surf->output_surface;
Timo Rothenpieler2a428db2014-11-29 23:04:372617
Michael Niedermayer94d68a42015-07-27 19:14:312618 if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
Andrey Turkin2f53b5b2016-05-29 12:50:062619 if (frame->top_field_first)
Timo Rothenpieler2a428db2014-11-29 23:04:372620 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM;
Andrey Turkin2f53b5b2016-05-29 12:50:062621 else
Timo Rothenpieler2a428db2014-11-29 23:04:372622 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP;
Timo Rothenpieler2a428db2014-11-29 23:04:372623 } else {
2624 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
2625 }
2626
Timo Rothenpieler30c55872016-10-12 18:51:432627 if (ctx->forced_idr >= 0 && frame->pict_type == AV_PICTURE_TYPE_I) {
2628 pic_params.encodePicFlags =
2629 ctx->forced_idr ? NV_ENC_PIC_FLAG_FORCEIDR : NV_ENC_PIC_FLAG_FORCEINTRA;
2630 } else {
2631 pic_params.encodePicFlags = 0;
2632 }
2633
Timo Rothenpieler2a428db2014-11-29 23:04:372634 pic_params.inputTimeStamp = frame->pts;
Andrey Turkin82d705e2016-05-20 14:49:242635
Timo Rothenpieler8bcce562021-06-06 19:53:532636 if (ctx->extra_sei) {
2637 res = prepare_sei_data_array(avctx, frame);
2638 if (res < 0)
2639 return res;
2640 sei_count = res;
2641 }
Brad Hardscee9f962021-06-04 14:06:382642
Brad Hards63948a62021-05-25 10:11:572643 nvenc_codec_specific_pic_params(avctx, &pic_params, ctx->sei_data, sei_count);
Timo Rothenpieler2a428db2014-11-29 23:04:372644 } else {
2645 pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
Timo Rothenpieler2a428db2014-11-29 23:04:372646 }
2647
Anton Khirnov35538092022-07-12 09:25:092648 // make a reference for enqueing in the reorder queue here,
2649 // so that reorder_queue_enqueue() cannot fail
2650 if (frame && frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
2651 opaque_ref = av_buffer_ref(frame->opaque_ref);
2652 if (!opaque_ref)
2653 return AVERROR(ENOMEM);
2654 }
2655
Hendrik Leppkes6fcbf392017-11-11 15:13:242656 res = nvenc_push_context(avctx);
2657 if (res < 0)
Anton Khirnov35538092022-07-12 09:25:092658 goto opaque_ref_fail;
Timo Rothenpielerbe74ba62017-02-13 21:59:462659
Timo Rothenpieler2a428db2014-11-29 23:04:372660 nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
Limin Wang4ef766e2020-06-15 14:08:402661
Brad Hards63948a62021-05-25 10:11:572662 for (i = 0; i < sei_count; i++)
2663 av_freep(&(ctx->sei_data[i].payload));
Timo Rothenpielerbe74ba62017-02-13 21:59:462664
Hendrik Leppkes6fcbf392017-11-11 15:13:242665 res = nvenc_pop_context(avctx);
2666 if (res < 0)
Anton Khirnov35538092022-07-12 09:25:092667 goto opaque_ref_fail;
Timo Rothenpielerbe74ba62017-02-13 21:59:462668
Andrey Turkin2f53b5b2016-05-29 12:50:062669 if (nv_status != NV_ENC_SUCCESS &&
Anton Khirnov35538092022-07-12 09:25:092670 nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
2671 res = nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
2672 goto opaque_ref_fail;
2673 }
Timo Rothenpieler2a428db2014-11-29 23:04:372674
James Almer827d6fe2020-06-09 21:31:322675 if (frame && frame->buf[0]) {
Anton Khirnov587545c2022-01-06 15:59:492676 av_fifo_write(ctx->output_surface_queue, &in_surf, 1);
Anton Khirnov35538092022-07-12 09:25:092677 reorder_queue_enqueue(ctx->reorder_queue, avctx, frame, &opaque_ref);
Andrey Turkin58c6dcb2016-05-29 12:51:362678 }
Timo Rothenpieler2a428db2014-11-29 23:04:372679
Andrey Turkin2f53b5b2016-05-29 12:50:062680 /* all the pending buffers are now ready for output */
2681 if (nv_status == NV_ENC_SUCCESS) {
Anton Khirnov587545c2022-01-06 15:59:492682 while (av_fifo_read(ctx->output_surface_queue, &tmp_out_surf, 1) >= 0)
2683 av_fifo_write(ctx->output_surface_ready_queue, &tmp_out_surf, 1);
Timo Rothenpieler2a428db2014-11-29 23:04:372684 }
2685
Timo Rothenpielera56d0492017-09-02 17:30:212686 return 0;
Anton Khirnov35538092022-07-12 09:25:092687
2688opaque_ref_fail:
2689 av_buffer_unref(&opaque_ref);
2690 return res;
Timo Rothenpielera56d0492017-09-02 17:30:212691}
2692
2693int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
2694{
Timo Rothenpielerd0961d32017-09-02 17:42:132695 NvencSurface *tmp_out_surf;
Hendrik Leppkes6fcbf392017-11-11 15:13:242696 int res, res2;
Timo Rothenpielera56d0492017-09-02 17:30:212697
2698 NvencContext *ctx = avctx->priv_data;
Timo Rothenpielera56d0492017-09-02 17:30:212699
James Almer827d6fe2020-06-09 21:31:322700 AVFrame *frame = ctx->frame;
2701
Hendrik Leppkesbff6d982017-11-11 15:51:582702 if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
Timo Rothenpielera56d0492017-09-02 17:30:212703 return AVERROR(EINVAL);
2704
James Almer827d6fe2020-06-09 21:31:322705 if (!frame->buf[0]) {
2706 res = ff_encode_get_frame(avctx, frame);
2707 if (res < 0 && res != AVERROR_EOF)
2708 return res;
2709 }
2710
2711 res = nvenc_send_frame(avctx, frame);
2712 if (res < 0) {
2713 if (res != AVERROR(EAGAIN))
2714 return res;
2715 } else
2716 av_frame_unref(frame);
2717
2718 if (output_ready(avctx, avctx->internal->draining)) {
Anton Khirnov587545c2022-01-06 15:59:492719 av_fifo_read(ctx->output_surface_ready_queue, &tmp_out_surf, 1);
Timo Rothenpieler2a428db2014-11-29 23:04:372720
Hendrik Leppkes6fcbf392017-11-11 15:13:242721 res = nvenc_push_context(avctx);
2722 if (res < 0)
2723 return res;
Ganapathy Kasi43c417a2017-05-31 02:03:142724
Timo Rothenpielerd0961d32017-09-02 17:42:132725 res = process_output_surface(avctx, pkt, tmp_out_surf);
Timo Rothenpieler2a428db2014-11-29 23:04:372726
Hendrik Leppkes6fcbf392017-11-11 15:13:242727 res2 = nvenc_pop_context(avctx);
2728 if (res2 < 0)
2729 return res2;
Ganapathy Kasi43c417a2017-05-31 02:03:142730
Timo Rothenpieler2a428db2014-11-29 23:04:372731 if (res)
2732 return res;
2733
Anton Khirnov587545c2022-01-06 15:59:492734 av_fifo_write(ctx->unused_surface_queue, &tmp_out_surf, 1);
James Almer827d6fe2020-06-09 21:31:322735 } else if (avctx->internal->draining) {
Timo Rothenpielera56d0492017-09-02 17:30:212736 return AVERROR_EOF;
Timo Rothenpieler2a428db2014-11-29 23:04:372737 } else {
Timo Rothenpielera56d0492017-09-02 17:30:212738 return AVERROR(EAGAIN);
2739 }
2740
2741 return 0;
2742}
2743
Philip Langdale3ea70572019-12-20 23:34:332744av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx)
2745{
James Almer827d6fe2020-06-09 21:31:322746 NvencContext *ctx = avctx->priv_data;
2747
2748 nvenc_send_frame(avctx, NULL);
Anton Khirnov35538092022-07-12 09:25:092749 reorder_queue_flush(ctx->reorder_queue);
Philip Langdale3ea70572019-12-20 23:34:332750}