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