FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nvenc.c
Go to the documentation of this file.
1 /*
2  * H.264 hardware encoding using nvidia nvenc
3  * Copyright (c) 2014 Timo Rothenpieler <timo@rothenpieler.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #if defined(_WIN32)
23 #include <windows.h>
24 #else
25 #include <dlfcn.h>
26 #endif
27 
28 #include <nvEncodeAPI.h>
29 
30 #include "libavutil/internal.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/avassert.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/mem.h"
35 #include "avcodec.h"
36 #include "internal.h"
37 #include "thread.h"
38 
39 #if defined(_WIN32)
40 #define CUDAAPI __stdcall
41 #else
42 #define CUDAAPI
43 #endif
44 
45 #if defined(_WIN32)
46 #define LOAD_FUNC(l, s) GetProcAddress(l, s)
47 #define DL_CLOSE_FUNC(l) FreeLibrary(l)
48 #else
49 #define LOAD_FUNC(l, s) dlsym(l, s)
50 #define DL_CLOSE_FUNC(l) dlclose(l)
51 #endif
52 
53 typedef enum cudaError_enum {
55 } CUresult;
56 typedef int CUdevice;
57 typedef void* CUcontext;
58 
59 typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags);
61 typedef CUresult(CUDAAPI *PCUDEVICEGET)(CUdevice *device, int ordinal);
62 typedef CUresult(CUDAAPI *PCUDEVICEGETNAME)(char *name, int len, CUdevice dev);
63 typedef CUresult(CUDAAPI *PCUDEVICECOMPUTECAPABILITY)(int *major, int *minor, CUdevice dev);
64 typedef CUresult(CUDAAPI *PCUCTXCREATE)(CUcontext *pctx, unsigned int flags, CUdevice dev);
67 
68 typedef NVENCSTATUS (NVENCAPI* PNVENCODEAPICREATEINSTANCE)(NV_ENCODE_API_FUNCTION_LIST *functionList);
69 
70 #if NVENCAPI_MAJOR_VERSION < 5
71 static const GUID dummy_license = { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
72 #endif
73 
74 typedef struct NvencInputSurface
75 {
76  NV_ENC_INPUT_PTR input_surface;
77  int width;
78  int height;
79 
80  int lockCount;
81 
82  NV_ENC_BUFFER_FORMAT format;
84 
85 typedef struct NvencOutputSurface
86 {
87  NV_ENC_OUTPUT_PTR output_surface;
88  int size;
89 
91 
92  int busy;
94 
95 typedef struct NvencData
96 {
97  union {
98  int64_t timestamp;
100  };
101 } NvencData;
102 
103 typedef struct NvencDataList
104 {
106 
107  uint32_t pos;
108  uint32_t count;
109  uint32_t size;
110 } NvencDataList;
111 
112 typedef struct NvencDynLoadFunctions
113 {
122 
123  NV_ENCODE_API_FUNCTION_LIST nvenc_funcs;
126 
127 #if defined(_WIN32)
130 #else
131  void* cuda_lib;
132  void* nvenc_lib;
133 #endif
135 
136 typedef struct NvencContext
137 {
139 
141 
142  NV_ENC_INITIALIZE_PARAMS init_encode_params;
143  NV_ENC_CONFIG encode_config;
145 
149 
153  int64_t last_dts;
154 
155  void *nvencoder;
156 
157  char *preset;
158  int cbr;
159  int twopass;
160  int gpu;
161 } NvencContext;
162 
164 {
165  uint32_t mask;
166  uint32_t read_pos;
167 
168  av_assert0(queue);
169  av_assert0(queue->size);
170  av_assert0(queue->data);
171 
172  if (!queue->count)
173  return NULL;
174 
175  /* Size always is a multiple of two */
176  mask = queue->size - 1;
177  read_pos = (queue->pos - queue->count) & mask;
178  queue->count--;
179 
180  return &queue->data[read_pos];
181 }
182 
184 {
185  NvencDataList new_queue;
186  NvencData* tmp_data;
187  uint32_t mask;
188 
189  if (!queue->size) {
190  /* size always has to be a multiple of two */
191  queue->size = 4;
192  queue->pos = 0;
193  queue->count = 0;
194 
195  queue->data = av_malloc(queue->size * sizeof(*(queue->data)));
196 
197  if (!queue->data) {
198  queue->size = 0;
199  return AVERROR(ENOMEM);
200  }
201  }
202 
203  if (queue->count == queue->size) {
204  new_queue.size = queue->size << 1;
205  new_queue.pos = 0;
206  new_queue.count = 0;
207  new_queue.data = av_malloc(new_queue.size * sizeof(*(queue->data)));
208 
209  if (!new_queue.data)
210  return AVERROR(ENOMEM);
211 
212  while (tmp_data = data_queue_dequeue(queue))
213  data_queue_enqueue(&new_queue, tmp_data);
214 
215  av_free(queue->data);
216  *queue = new_queue;
217  }
218 
219  mask = queue->size - 1;
220 
221  queue->data[queue->pos] = *data;
222  queue->pos = (queue->pos + 1) & mask;
223  queue->count++;
224 
225  return 0;
226 }
227 
229 {
230  NvencData data;
231  data.surface = surface;
232 
233  return data_queue_enqueue(queue, &data);
234 }
235 
237 {
238  NvencData* res = data_queue_dequeue(queue);
239 
240  if (!res)
241  return NULL;
242 
243  return res->surface;
244 }
245 
246 static int timestamp_queue_enqueue(NvencDataList* queue, int64_t timestamp)
247 {
248  NvencData data;
249  data.timestamp = timestamp;
250 
251  return data_queue_enqueue(queue, &data);
252 }
253 
255 {
256  NvencData* res = data_queue_dequeue(queue);
257 
258  if (!res)
259  return AV_NOPTS_VALUE;
260 
261  return res->timestamp;
262 }
263 
264 #define CHECK_LOAD_FUNC(t, f, s) \
265 do { \
266  (f) = (t)LOAD_FUNC(dl_fn->cuda_lib, s); \
267  if (!(f)) { \
268  av_log(avctx, AV_LOG_FATAL, "Failed loading %s from CUDA library\n", s); \
269  goto error; \
270  } \
271 } while (0)
272 
274 {
275  NvencContext *ctx = avctx->priv_data;
277 
278  if (dl_fn->cuda_lib)
279  return 1;
280 
281 #if defined(_WIN32)
282  dl_fn->cuda_lib = LoadLibrary(TEXT("nvcuda.dll"));
283 #else
284  dl_fn->cuda_lib = dlopen("libcuda.so", RTLD_LAZY);
285 #endif
286 
287  if (!dl_fn->cuda_lib) {
288  av_log(avctx, AV_LOG_FATAL, "Failed loading CUDA library\n");
289  goto error;
290  }
291 
292  CHECK_LOAD_FUNC(PCUINIT, dl_fn->cu_init, "cuInit");
293  CHECK_LOAD_FUNC(PCUDEVICEGETCOUNT, dl_fn->cu_device_get_count, "cuDeviceGetCount");
294  CHECK_LOAD_FUNC(PCUDEVICEGET, dl_fn->cu_device_get, "cuDeviceGet");
295  CHECK_LOAD_FUNC(PCUDEVICEGETNAME, dl_fn->cu_device_get_name, "cuDeviceGetName");
296  CHECK_LOAD_FUNC(PCUDEVICECOMPUTECAPABILITY, dl_fn->cu_device_compute_capability, "cuDeviceComputeCapability");
297  CHECK_LOAD_FUNC(PCUCTXCREATE, dl_fn->cu_ctx_create, "cuCtxCreate_v2");
298  CHECK_LOAD_FUNC(PCUCTXPOPCURRENT, dl_fn->cu_ctx_pop_current, "cuCtxPopCurrent_v2");
299  CHECK_LOAD_FUNC(PCUCTXDESTROY, dl_fn->cu_ctx_destroy, "cuCtxDestroy_v2");
300 
301  return 1;
302 
303 error:
304 
305  if (dl_fn->cuda_lib)
306  DL_CLOSE_FUNC(dl_fn->cuda_lib);
307 
308  dl_fn->cuda_lib = NULL;
309 
310  return 0;
311 }
312 
313 static av_cold int check_cuda_errors(AVCodecContext *avctx, CUresult err, const char *func)
314 {
315  if (err != CUDA_SUCCESS) {
316  av_log(avctx, AV_LOG_FATAL, ">> %s - failed with error code 0x%x\n", func, err);
317  return 0;
318  }
319  return 1;
320 }
321 #define check_cuda_errors(f) if (!check_cuda_errors(avctx, f, #f)) goto error
322 
324 {
325  int device_count = 0;
326  CUdevice cu_device = 0;
327  char gpu_name[128];
328  int smminor = 0, smmajor = 0;
329  int i, smver;
330 
331  NvencContext *ctx = avctx->priv_data;
333 
334  if (!nvenc_dyload_cuda(avctx))
335  return 0;
336 
337  if (dl_fn->nvenc_device_count > 0)
338  return 1;
339 
340  check_cuda_errors(dl_fn->cu_init(0));
341 
342  check_cuda_errors(dl_fn->cu_device_get_count(&device_count));
343 
344  if (!device_count) {
345  av_log(avctx, AV_LOG_FATAL, "No CUDA capable devices found\n");
346  goto error;
347  }
348 
349  av_log(avctx, AV_LOG_VERBOSE, "%d CUDA capable devices found\n", device_count);
350 
351  dl_fn->nvenc_device_count = 0;
352 
353  for (i = 0; i < device_count; ++i) {
354  check_cuda_errors(dl_fn->cu_device_get(&cu_device, i));
355  check_cuda_errors(dl_fn->cu_device_get_name(gpu_name, sizeof(gpu_name), cu_device));
356  check_cuda_errors(dl_fn->cu_device_compute_capability(&smmajor, &smminor, cu_device));
357 
358  smver = (smmajor << 4) | smminor;
359 
360  av_log(avctx, AV_LOG_VERBOSE, "[ GPU #%d - < %s > has Compute SM %d.%d, NVENC %s ]\n", i, gpu_name, smmajor, smminor, (smver >= 0x30) ? "Available" : "Not Available");
361 
362  if (smver >= 0x30)
363  dl_fn->nvenc_devices[dl_fn->nvenc_device_count++] = cu_device;
364  }
365 
366  if (!dl_fn->nvenc_device_count) {
367  av_log(avctx, AV_LOG_FATAL, "No NVENC capable devices found\n");
368  goto error;
369  }
370 
371  return 1;
372 
373 error:
374 
375  dl_fn->nvenc_device_count = 0;
376 
377  return 0;
378 }
379 
381 {
382  PNVENCODEAPICREATEINSTANCE nvEncodeAPICreateInstance = 0;
383  NVENCSTATUS nvstatus;
384 
385  NvencContext *ctx = avctx->priv_data;
387 
388  if (!nvenc_check_cuda(avctx))
389  return 0;
390 
391  if (dl_fn->nvenc_lib)
392  return 1;
393 
394 #if defined(_WIN32)
395  if (sizeof(void*) == 8) {
396  dl_fn->nvenc_lib = LoadLibrary(TEXT("nvEncodeAPI64.dll"));
397  } else {
398  dl_fn->nvenc_lib = LoadLibrary(TEXT("nvEncodeAPI.dll"));
399  }
400 #else
401  dl_fn->nvenc_lib = dlopen("libnvidia-encode.so.1", RTLD_LAZY);
402 #endif
403 
404  if (!dl_fn->nvenc_lib) {
405  av_log(avctx, AV_LOG_FATAL, "Failed loading the nvenc library\n");
406  goto error;
407  }
408 
409  nvEncodeAPICreateInstance = (PNVENCODEAPICREATEINSTANCE)LOAD_FUNC(dl_fn->nvenc_lib, "NvEncodeAPICreateInstance");
410 
411  if (!nvEncodeAPICreateInstance) {
412  av_log(avctx, AV_LOG_FATAL, "Failed to load nvenc entrypoint\n");
413  goto error;
414  }
415 
416  dl_fn->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER;
417 
418  nvstatus = nvEncodeAPICreateInstance(&dl_fn->nvenc_funcs);
419 
420  if (nvstatus != NV_ENC_SUCCESS) {
421  av_log(avctx, AV_LOG_FATAL, "Failed to create nvenc instance\n");
422  goto error;
423  }
424 
425  av_log(avctx, AV_LOG_VERBOSE, "Nvenc initialized successfully\n");
426 
427  return 1;
428 
429 error:
430  if (dl_fn->nvenc_lib)
431  DL_CLOSE_FUNC(dl_fn->nvenc_lib);
432 
433  dl_fn->nvenc_lib = NULL;
434 
435  return 0;
436 }
437 
439 {
440  NvencContext *ctx = avctx->priv_data;
442 
443  DL_CLOSE_FUNC(dl_fn->nvenc_lib);
444  dl_fn->nvenc_lib = NULL;
445 
446  dl_fn->nvenc_device_count = 0;
447 
448  DL_CLOSE_FUNC(dl_fn->cuda_lib);
449  dl_fn->cuda_lib = NULL;
450 
451  dl_fn->cu_init = NULL;
452  dl_fn->cu_device_get_count = NULL;
453  dl_fn->cu_device_get = NULL;
454  dl_fn->cu_device_get_name = NULL;
456  dl_fn->cu_ctx_create = NULL;
457  dl_fn->cu_ctx_pop_current = NULL;
458  dl_fn->cu_ctx_destroy = NULL;
459 
460  av_log(avctx, AV_LOG_VERBOSE, "Nvenc unloaded\n");
461 }
462 
464 {
465  NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS encode_session_params = { 0 };
466  NV_ENC_PRESET_CONFIG preset_config = { 0 };
467  CUcontext cu_context_curr;
468  CUresult cu_res;
469  GUID encoder_preset = NV_ENC_PRESET_HQ_GUID;
470  NVENCSTATUS nv_status = NV_ENC_SUCCESS;
471  int surfaceCount = 0;
472  int i, num_mbs;
473  int isLL = 0;
474  int res = 0;
475  int dw, dh;
476 
477 #if NVENCAPI_MAJOR_VERSION < 5
478  GUID license = dummy_license;
479 #endif
480 
481  NvencContext *ctx = avctx->priv_data;
483  NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
484 
485  if (!nvenc_dyload_nvenc(avctx))
486  return AVERROR_EXTERNAL;
487 
488  avctx->coded_frame = av_frame_alloc();
489  if (!avctx->coded_frame) {
490  res = AVERROR(ENOMEM);
491  goto error;
492  }
493 
494  ctx->last_dts = AV_NOPTS_VALUE;
495 
496  ctx->encode_config.version = NV_ENC_CONFIG_VER;
497  ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
498  preset_config.version = NV_ENC_PRESET_CONFIG_VER;
499  preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
500  encode_session_params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
501  encode_session_params.apiVersion = NVENCAPI_VERSION;
502 
503 #if NVENCAPI_MAJOR_VERSION < 5
504  encode_session_params.clientKeyPtr = &license;
505 #endif
506 
507  if (ctx->gpu >= dl_fn->nvenc_device_count) {
508  av_log(avctx, AV_LOG_FATAL, "Requested GPU %d, but only %d GPUs are available!\n", ctx->gpu, dl_fn->nvenc_device_count);
509  res = AVERROR(EINVAL);
510  goto error;
511  }
512 
513  ctx->cu_context = NULL;
514  cu_res = dl_fn->cu_ctx_create(&ctx->cu_context, 0, dl_fn->nvenc_devices[ctx->gpu]);
515 
516  if (cu_res != CUDA_SUCCESS) {
517  av_log(avctx, AV_LOG_FATAL, "Failed creating CUDA context for NVENC: 0x%x\n", (int)cu_res);
518  res = AVERROR_EXTERNAL;
519  goto error;
520  }
521 
522  cu_res = dl_fn->cu_ctx_pop_current(&cu_context_curr);
523 
524  if (cu_res != CUDA_SUCCESS) {
525  av_log(avctx, AV_LOG_FATAL, "Failed popping CUDA context: 0x%x\n", (int)cu_res);
526  res = AVERROR_EXTERNAL;
527  goto error;
528  }
529 
530  encode_session_params.device = ctx->cu_context;
531  encode_session_params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
532 
533  nv_status = p_nvenc->nvEncOpenEncodeSessionEx(&encode_session_params, &ctx->nvencoder);
534  if (nv_status != NV_ENC_SUCCESS) {
535  ctx->nvencoder = NULL;
536  av_log(avctx, AV_LOG_FATAL, "OpenEncodeSessionEx failed: 0x%x - invalid license key?\n", (int)nv_status);
537  res = AVERROR_EXTERNAL;
538  goto error;
539  }
540 
541  if (ctx->preset) {
542  if (!strcmp(ctx->preset, "hp")) {
543  encoder_preset = NV_ENC_PRESET_HP_GUID;
544  } else if (!strcmp(ctx->preset, "hq")) {
545  encoder_preset = NV_ENC_PRESET_HQ_GUID;
546  } else if (!strcmp(ctx->preset, "bd")) {
547  encoder_preset = NV_ENC_PRESET_BD_GUID;
548  } else if (!strcmp(ctx->preset, "ll")) {
549  encoder_preset = NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID;
550  isLL = 1;
551  } else if (!strcmp(ctx->preset, "llhp")) {
552  encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HP_GUID;
553  isLL = 1;
554  } else if (!strcmp(ctx->preset, "llhq")) {
555  encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID;
556  isLL = 1;
557  } else if (!strcmp(ctx->preset, "default")) {
558  encoder_preset = NV_ENC_PRESET_DEFAULT_GUID;
559  } else {
560  av_log(avctx, AV_LOG_FATAL, "Preset \"%s\" is unknown! Supported presets: hp, hq, bd, ll, llhp, llhq, default\n", ctx->preset);
561  res = AVERROR(EINVAL);
562  goto error;
563  }
564  }
565 
566  nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder, NV_ENC_CODEC_H264_GUID, encoder_preset, &preset_config);
567  if (nv_status != NV_ENC_SUCCESS) {
568  av_log(avctx, AV_LOG_FATAL, "GetEncodePresetConfig failed: 0x%x\n", (int)nv_status);
569  res = AVERROR_EXTERNAL;
570  goto error;
571  }
572 
573  ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_H264_GUID;
574  ctx->init_encode_params.encodeHeight = avctx->height;
575  ctx->init_encode_params.encodeWidth = avctx->width;
576 
577  if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den &&
578  (avctx->sample_aspect_ratio.num != 1 || avctx->sample_aspect_ratio.num != 1)) {
579  av_reduce(&dw, &dh,
580  avctx->width * avctx->sample_aspect_ratio.num,
581  avctx->height * avctx->sample_aspect_ratio.den,
582  1024 * 1024);
583  ctx->init_encode_params.darHeight = dh;
584  ctx->init_encode_params.darWidth = dw;
585  } else {
586  ctx->init_encode_params.darHeight = avctx->height;
587  ctx->init_encode_params.darWidth = avctx->width;
588  }
589 
590  // De-compensate for hardware, dubiously, trying to compensate for
591  // playback at 704 pixel width.
592  if (avctx->width == 720 &&
593  (avctx->height == 480 || avctx->height == 576)) {
594  av_reduce(&dw, &dh,
595  ctx->init_encode_params.darWidth * 44,
596  ctx->init_encode_params.darHeight * 45,
597  1024 * 1204);
598  ctx->init_encode_params.darHeight = dh;
599  ctx->init_encode_params.darWidth = dw;
600  }
601 
602  ctx->init_encode_params.frameRateNum = avctx->time_base.den;
603  ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame;
604 
605  num_mbs = ((avctx->width + 15) >> 4) * ((avctx->height + 15) >> 4);
606  ctx->max_surface_count = (num_mbs >= 8160) ? 32 : 48;
607 
608  ctx->init_encode_params.enableEncodeAsync = 0;
609  ctx->init_encode_params.enablePTD = 1;
610 
611  ctx->init_encode_params.presetGUID = encoder_preset;
612 
613  ctx->init_encode_params.encodeConfig = &ctx->encode_config;
614  memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
615  ctx->encode_config.version = NV_ENC_CONFIG_VER;
616 
617  if (avctx->refs >= 0) {
618  /* 0 means "let the hardware decide" */
619  ctx->encode_config.encodeCodecConfig.h264Config.maxNumRefFrames = avctx->refs;
620  }
621 
622  if (avctx->gop_size > 0) {
623  if (avctx->max_b_frames >= 0) {
624  /* 0 is intra-only, 1 is I/P only, 2 is one B Frame, 3 two B frames, and so on. */
625  ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1;
626  }
627 
628  ctx->encode_config.gopLength = avctx->gop_size;
629  ctx->encode_config.encodeCodecConfig.h264Config.idrPeriod = avctx->gop_size;
630  } else if (avctx->gop_size == 0) {
631  ctx->encode_config.frameIntervalP = 0;
632  ctx->encode_config.gopLength = 1;
633  ctx->encode_config.encodeCodecConfig.h264Config.idrPeriod = 1;
634  }
635 
636  /* when there're b frames, set dts offset */
637  if (ctx->encode_config.frameIntervalP >= 2)
638  ctx->last_dts = -2;
639 
640  if (avctx->bit_rate > 0)
641  ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate;
642 
643  if (avctx->rc_max_rate > 0)
644  ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
645 
646  if (ctx->cbr) {
647  if (!ctx->twopass) {
648  ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR;
649  } else if (ctx->twopass == 1 || isLL) {
650  ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_2_PASS_QUALITY;
651 
652  ctx->encode_config.encodeCodecConfig.h264Config.adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE;
653  ctx->encode_config.encodeCodecConfig.h264Config.fmoMode = NV_ENC_H264_FMO_DISABLE;
654 
655  if (!isLL)
656  av_log(avctx, AV_LOG_WARNING, "Twopass mode is only known to work with low latency (ll, llhq, llhp) presets.\n");
657  } else {
658  ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR;
659  }
660  } else if (avctx->global_quality > 0) {
661  ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
662  ctx->encode_config.rcParams.constQP.qpInterB = avctx->global_quality;
663  ctx->encode_config.rcParams.constQP.qpInterP = avctx->global_quality;
664  ctx->encode_config.rcParams.constQP.qpIntra = avctx->global_quality;
665 
666  avctx->qmin = -1;
667  avctx->qmax = -1;
668  } else if (avctx->qmin >= 0 && avctx->qmax >= 0) {
669  ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
670 
671  ctx->encode_config.rcParams.enableMinQP = 1;
672  ctx->encode_config.rcParams.enableMaxQP = 1;
673 
674  ctx->encode_config.rcParams.minQP.qpInterB = avctx->qmin;
675  ctx->encode_config.rcParams.minQP.qpInterP = avctx->qmin;
676  ctx->encode_config.rcParams.minQP.qpIntra = avctx->qmin;
677 
678  ctx->encode_config.rcParams.maxQP.qpInterB = avctx->qmax;
679  ctx->encode_config.rcParams.maxQP.qpInterP = avctx->qmax;
680  ctx->encode_config.rcParams.maxQP.qpIntra = avctx->qmax;
681  }
682 
683  if (avctx->rc_buffer_size > 0)
684  ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size;
685 
686  if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
687  ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
688  } else {
689  ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
690  }
691 
692  switch (avctx->profile) {
694  ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
695  break;
697  ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
698  break;
700  case FF_PROFILE_UNKNOWN:
701  ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
702  break;
703  default:
704  av_log(avctx, AV_LOG_WARNING, "Unsupported h264 profile requested, falling back to high\n");
705  ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
706  break;
707  }
708 
709  ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourDescriptionPresentFlag = 1;
710  ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoSignalTypePresentFlag = 1;
711 
712  ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourMatrix = avctx->colorspace;
713  ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourPrimaries = avctx->color_primaries;
714  ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.transferCharacteristics = avctx->color_trc;
715 
716  ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag = avctx->color_range == AVCOL_RANGE_JPEG;
717 
718  ctx->encode_config.encodeCodecConfig.h264Config.disableSPSPPS = (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
719  ctx->encode_config.encodeCodecConfig.h264Config.repeatSPSPPS = (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
720 
721  nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params);
722  if (nv_status != NV_ENC_SUCCESS) {
723  av_log(avctx, AV_LOG_FATAL, "InitializeEncoder failed: 0x%x\n", (int)nv_status);
724  res = AVERROR_EXTERNAL;
725  goto error;
726  }
727 
728  ctx->input_surfaces = av_malloc(ctx->max_surface_count * sizeof(*ctx->input_surfaces));
729 
730  if (!ctx->input_surfaces) {
731  res = AVERROR(ENOMEM);
732  goto error;
733  }
734 
735  ctx->output_surfaces = av_malloc(ctx->max_surface_count * sizeof(*ctx->output_surfaces));
736 
737  if (!ctx->output_surfaces) {
738  res = AVERROR(ENOMEM);
739  goto error;
740  }
741 
742  for (surfaceCount = 0; surfaceCount < ctx->max_surface_count; ++surfaceCount) {
743  NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 };
744  NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 };
745  allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
746  allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
747 
748  allocSurf.width = (avctx->width + 31) & ~31;
749  allocSurf.height = (avctx->height + 31) & ~31;
750 
751  allocSurf.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
752 
753  switch (avctx->pix_fmt) {
754  case AV_PIX_FMT_YUV420P:
755  allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_YV12_PL;
756  break;
757 
758  case AV_PIX_FMT_NV12:
759  allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_NV12_PL;
760  break;
761 
762  case AV_PIX_FMT_YUV444P:
763  allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_YUV444_PL;
764  break;
765 
766  default:
767  av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n");
768  res = AVERROR(EINVAL);
769  goto error;
770  }
771 
772  nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf);
773  if (nv_status = NV_ENC_SUCCESS){
774  av_log(avctx, AV_LOG_FATAL, "CreateInputBuffer failed\n");
775  res = AVERROR_EXTERNAL;
776  goto error;
777  }
778 
779  ctx->input_surfaces[surfaceCount].lockCount = 0;
780  ctx->input_surfaces[surfaceCount].input_surface = allocSurf.inputBuffer;
781  ctx->input_surfaces[surfaceCount].format = allocSurf.bufferFmt;
782  ctx->input_surfaces[surfaceCount].width = allocSurf.width;
783  ctx->input_surfaces[surfaceCount].height = allocSurf.height;
784 
785  /* 1MB is large enough to hold most output frames. NVENC increases this automaticaly if it's not enough. */
786  allocOut.size = 1024 * 1024;
787 
788  allocOut.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
789 
790  nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut);
791  if (nv_status = NV_ENC_SUCCESS) {
792  av_log(avctx, AV_LOG_FATAL, "CreateBitstreamBuffer failed\n");
793  ctx->output_surfaces[surfaceCount++].output_surface = NULL;
794  res = AVERROR_EXTERNAL;
795  goto error;
796  }
797 
798  ctx->output_surfaces[surfaceCount].output_surface = allocOut.bitstreamBuffer;
799  ctx->output_surfaces[surfaceCount].size = allocOut.size;
800  ctx->output_surfaces[surfaceCount].busy = 0;
801  }
802 
803  if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
804  uint32_t outSize = 0;
805  char tmpHeader[256];
806  NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 };
807  payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;
808 
809  payload.spsppsBuffer = tmpHeader;
810  payload.inBufferSize = sizeof(tmpHeader);
811  payload.outSPSPPSPayloadSize = &outSize;
812 
813  nv_status = p_nvenc->nvEncGetSequenceParams(ctx->nvencoder, &payload);
814  if (nv_status != NV_ENC_SUCCESS) {
815  av_log(avctx, AV_LOG_FATAL, "GetSequenceParams failed\n");
816  goto error;
817  }
818 
819  avctx->extradata_size = outSize;
821 
822  if (!avctx->extradata) {
823  res = AVERROR(ENOMEM);
824  goto error;
825  }
826 
827  memcpy(avctx->extradata, tmpHeader, outSize);
828  }
829 
830  if (ctx->encode_config.frameIntervalP > 1)
831  avctx->has_b_frames = 2;
832 
833  if (ctx->encode_config.rcParams.averageBitRate > 0)
834  avctx->bit_rate = ctx->encode_config.rcParams.averageBitRate;
835 
836  return 0;
837 
838 error:
839 
840  for (i = 0; i < surfaceCount; ++i) {
841  p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->input_surfaces[i].input_surface);
842  if (ctx->output_surfaces[i].output_surface)
843  p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->output_surfaces[i].output_surface);
844  }
845 
846  if (ctx->nvencoder)
847  p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
848 
849  if (ctx->cu_context)
850  dl_fn->cu_ctx_destroy(ctx->cu_context);
851 
852  av_frame_free(&avctx->coded_frame);
853 
854  nvenc_unload_nvenc(avctx);
855 
856  ctx->nvencoder = NULL;
857  ctx->cu_context = NULL;
858 
859  return res;
860 }
861 
863 {
864  NvencContext *ctx = avctx->priv_data;
866  NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
867  int i;
868 
872 
873  for (i = 0; i < ctx->max_surface_count; ++i) {
874  p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->input_surfaces[i].input_surface);
875  p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->output_surfaces[i].output_surface);
876  }
877  ctx->max_surface_count = 0;
878 
879  p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
880  ctx->nvencoder = NULL;
881 
882  dl_fn->cu_ctx_destroy(ctx->cu_context);
883  ctx->cu_context = NULL;
884 
885  nvenc_unload_nvenc(avctx);
886 
887  av_frame_free(&avctx->coded_frame);
888 
889  return 0;
890 }
891 
892 static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, AVFrame *coded_frame, NvencOutputSurface *tmpoutsurf)
893 {
894  NvencContext *ctx = avctx->priv_data;
896  NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
897 
898  uint32_t *slice_offsets = av_mallocz(ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData * sizeof(*slice_offsets));
899  NV_ENC_LOCK_BITSTREAM lock_params = { 0 };
900  NVENCSTATUS nv_status;
901  int res = 0;
902 
903  if (!slice_offsets)
904  return AVERROR(ENOMEM);
905 
906  lock_params.version = NV_ENC_LOCK_BITSTREAM_VER;
907 
908  lock_params.doNotWait = 0;
909  lock_params.outputBitstream = tmpoutsurf->output_surface;
910  lock_params.sliceOffsets = slice_offsets;
911 
912  nv_status = p_nvenc->nvEncLockBitstream(ctx->nvencoder, &lock_params);
913  if (nv_status != NV_ENC_SUCCESS) {
914  av_log(avctx, AV_LOG_ERROR, "Failed locking bitstream buffer\n");
915  res = AVERROR_EXTERNAL;
916  goto error;
917  }
918 
919  if (res = ff_alloc_packet2(avctx, pkt, lock_params.bitstreamSizeInBytes)) {
920  p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
921  goto error;
922  }
923 
924  memcpy(pkt->data, lock_params.bitstreamBufferPtr, lock_params.bitstreamSizeInBytes);
925 
926  nv_status = p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
927  if (nv_status != NV_ENC_SUCCESS)
928  av_log(avctx, AV_LOG_ERROR, "Failed unlocking bitstream buffer, expect the gates of mordor to open\n");
929 
930  switch (lock_params.pictureType) {
931  case NV_ENC_PIC_TYPE_IDR:
932  pkt->flags |= AV_PKT_FLAG_KEY;
933  case NV_ENC_PIC_TYPE_I:
935  break;
936  case NV_ENC_PIC_TYPE_P:
938  break;
939  case NV_ENC_PIC_TYPE_B:
941  break;
942  case NV_ENC_PIC_TYPE_BI:
944  break;
945  default:
946  av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered, expect the output to be broken.\n");
947  av_log(avctx, AV_LOG_ERROR, "Please report this error and include as much information on how to reproduce it as possible.\n");
948  res = AVERROR_EXTERNAL;
949  goto error;
950  }
951 
952  pkt->pts = lock_params.outputTimeStamp;
954 
955  /* when there're b frame(s), set dts offset */
956  if (ctx->encode_config.frameIntervalP >= 2)
957  pkt->dts -= 1;
958 
959  if (pkt->dts > pkt->pts)
960  pkt->dts = pkt->pts;
961 
962  if (ctx->last_dts != AV_NOPTS_VALUE && pkt->dts <= ctx->last_dts)
963  pkt->dts = ctx->last_dts + 1;
964 
965  ctx->last_dts = pkt->dts;
966 
967  av_free(slice_offsets);
968 
969  return 0;
970 
971 error:
972 
973  av_free(slice_offsets);
975 
976  return res;
977 }
978 
980  const AVFrame *frame, int *got_packet)
981 {
982  NVENCSTATUS nv_status;
983  NvencOutputSurface *tmpoutsurf;
984  int res, i = 0;
985 
986  NvencContext *ctx = avctx->priv_data;
988  NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
989 
990  NV_ENC_PIC_PARAMS pic_params = { 0 };
991  pic_params.version = NV_ENC_PIC_PARAMS_VER;
992 
993  if (frame) {
994  NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 };
995  NvencInputSurface *inSurf = NULL;
996 
997  for (i = 0; i < ctx->max_surface_count; ++i) {
998  if (!ctx->input_surfaces[i].lockCount) {
999  inSurf = &ctx->input_surfaces[i];
1000  break;
1001  }
1002  }
1003 
1004  av_assert0(inSurf);
1005 
1006  inSurf->lockCount = 1;
1007 
1008  lockBufferParams.version = NV_ENC_LOCK_INPUT_BUFFER_VER;
1009  lockBufferParams.inputBuffer = inSurf->input_surface;
1010 
1011  nv_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams);
1012  if (nv_status != NV_ENC_SUCCESS) {
1013  av_log(avctx, AV_LOG_ERROR, "Failed locking nvenc input buffer\n");
1014  return 0;
1015  }
1016 
1017  if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
1018  uint8_t *buf = lockBufferParams.bufferDataPtr;
1019 
1020  av_image_copy_plane(buf, lockBufferParams.pitch,
1021  frame->data[0], frame->linesize[0],
1022  avctx->width, avctx->height);
1023 
1024  buf += inSurf->height * lockBufferParams.pitch;
1025 
1026  av_image_copy_plane(buf, lockBufferParams.pitch >> 1,
1027  frame->data[2], frame->linesize[2],
1028  avctx->width >> 1, avctx->height >> 1);
1029 
1030  buf += (inSurf->height * lockBufferParams.pitch) >> 2;
1031 
1032  av_image_copy_plane(buf, lockBufferParams.pitch >> 1,
1033  frame->data[1], frame->linesize[1],
1034  avctx->width >> 1, avctx->height >> 1);
1035  } else if (avctx->pix_fmt == AV_PIX_FMT_NV12) {
1036  uint8_t *buf = lockBufferParams.bufferDataPtr;
1037 
1038  av_image_copy_plane(buf, lockBufferParams.pitch,
1039  frame->data[0], frame->linesize[0],
1040  avctx->width, avctx->height);
1041 
1042  buf += inSurf->height * lockBufferParams.pitch;
1043 
1044  av_image_copy_plane(buf, lockBufferParams.pitch,
1045  frame->data[1], frame->linesize[1],
1046  avctx->width, avctx->height >> 1);
1047  } else if (avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
1048  uint8_t *buf = lockBufferParams.bufferDataPtr;
1049 
1050  av_image_copy_plane(buf, lockBufferParams.pitch,
1051  frame->data[0], frame->linesize[0],
1052  avctx->width, avctx->height);
1053 
1054  buf += inSurf->height * lockBufferParams.pitch;
1055 
1056  av_image_copy_plane(buf, lockBufferParams.pitch,
1057  frame->data[1], frame->linesize[1],
1058  avctx->width, avctx->height);
1059 
1060  buf += inSurf->height * lockBufferParams.pitch;
1061 
1062  av_image_copy_plane(buf, lockBufferParams.pitch,
1063  frame->data[2], frame->linesize[2],
1064  avctx->width, avctx->height);
1065  } else {
1066  av_log(avctx, AV_LOG_FATAL, "Invalid pixel format!\n");
1067  return AVERROR(EINVAL);
1068  }
1069 
1070  nv_status = p_nvenc->nvEncUnlockInputBuffer(ctx->nvencoder, inSurf->input_surface);
1071  if (nv_status != NV_ENC_SUCCESS) {
1072  av_log(avctx, AV_LOG_FATAL, "Failed unlocking input buffer!\n");
1073  return AVERROR_EXTERNAL;
1074  }
1075 
1076  for (i = 0; i < ctx->max_surface_count; ++i)
1077  if (!ctx->output_surfaces[i].busy)
1078  break;
1079 
1080  if (i == ctx->max_surface_count) {
1081  inSurf->lockCount = 0;
1082  av_log(avctx, AV_LOG_FATAL, "No free output surface found!\n");
1083  return AVERROR_EXTERNAL;
1084  }
1085 
1086  ctx->output_surfaces[i].input_surface = inSurf;
1087 
1088  pic_params.inputBuffer = inSurf->input_surface;
1089  pic_params.bufferFmt = inSurf->format;
1090  pic_params.inputWidth = avctx->width;
1091  pic_params.inputHeight = avctx->height;
1092  pic_params.outputBitstream = ctx->output_surfaces[i].output_surface;
1093  pic_params.completionEvent = 0;
1094 
1095  if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
1096  if (frame->top_field_first) {
1097  pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM;
1098  } else {
1099  pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP;
1100  }
1101  } else {
1102  pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
1103  }
1104 
1105  pic_params.encodePicFlags = 0;
1106  pic_params.inputTimeStamp = frame->pts;
1107  pic_params.inputDuration = 0;
1108  pic_params.codecPicParams.h264PicParams.sliceMode = ctx->encode_config.encodeCodecConfig.h264Config.sliceMode;
1109  pic_params.codecPicParams.h264PicParams.sliceModeData = ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData;
1110 
1111 #if NVENCAPI_MAJOR_VERSION < 5
1112  memcpy(&pic_params.rcParams, &ctx->encode_config.rcParams, sizeof(NV_ENC_RC_PARAMS));
1113 #endif
1114 
1115  res = timestamp_queue_enqueue(&ctx->timestamp_list, frame->pts);
1116 
1117  if (res)
1118  return res;
1119  } else {
1120  pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
1121  }
1122 
1123  nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
1124 
1125  if (frame && nv_status == NV_ENC_ERR_NEED_MORE_INPUT) {
1127 
1128  if (res)
1129  return res;
1130 
1131  ctx->output_surfaces[i].busy = 1;
1132  }
1133 
1134  if (nv_status != NV_ENC_SUCCESS && nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
1135  av_log(avctx, AV_LOG_ERROR, "EncodePicture failed!\n");
1136  return AVERROR_EXTERNAL;
1137  }
1138 
1139  if (nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
1140  while (ctx->output_surface_queue.count) {
1141  tmpoutsurf = out_surf_queue_dequeue(&ctx->output_surface_queue);
1142  res = out_surf_queue_enqueue(&ctx->output_surface_ready_queue, tmpoutsurf);
1143 
1144  if (res)
1145  return res;
1146  }
1147 
1148  if (frame) {
1150 
1151  if (res)
1152  return res;
1153 
1154  ctx->output_surfaces[i].busy = 1;
1155  }
1156  }
1157 
1158  if (ctx->output_surface_ready_queue.count) {
1160 
1161  res = process_output_surface(avctx, pkt, avctx->coded_frame, tmpoutsurf);
1162 
1163  if (res)
1164  return res;
1165 
1166  tmpoutsurf->busy = 0;
1167  av_assert0(tmpoutsurf->input_surface->lockCount);
1168  tmpoutsurf->input_surface->lockCount--;
1169 
1170  *got_packet = 1;
1171  } else {
1172  *got_packet = 0;
1173  }
1174 
1175  return 0;
1176 }
1177 
1181 };
1182 
1183 #define OFFSET(x) offsetof(NvencContext, x)
1184 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1185 static const AVOption options[] = {
1186  { "preset", "Set the encoding preset (one of hq, hp, bd, ll, llhq, llhp, default)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "hq" }, 0, 0, VE },
1187  { "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
1188  { "2pass", "Use 2pass cbr encoding mode (low latency mode only)", OFFSET(twopass), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE },
1189  { "gpu", "Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.", OFFSET(gpu), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
1190  { NULL }
1191 };
1192 
1193 static const AVClass nvenc_class = {
1194  .class_name = "nvenc",
1195  .item_name = av_default_item_name,
1196  .option = options,
1197  .version = LIBAVUTIL_VERSION_INT,
1198 };
1199 
1200 static const AVCodecDefault nvenc_defaults[] = {
1201  { "b", "0" },
1202  { "qmin", "-1" },
1203  { "qmax", "-1" },
1204  { "qdiff", "-1" },
1205  { "qblur", "-1" },
1206  { "qcomp", "-1" },
1207  { NULL },
1208 };
1209 
1211  .name = "nvenc",
1212  .long_name = NULL_IF_CONFIG_SMALL("Nvidia NVENC h264 encoder"),
1213  .type = AVMEDIA_TYPE_VIDEO,
1214  .id = AV_CODEC_ID_H264,
1215  .priv_data_size = sizeof(NvencContext),
1217  .encode2 = nvenc_encode_frame,
1218  .close = nvenc_encode_close,
1219  .capabilities = CODEC_CAP_DELAY,
1220  .priv_class = &nvenc_class,
1221  .defaults = nvenc_defaults,
1222  .pix_fmts = pix_fmts_nvenc,
1223 };