1 /* GStreamer NVENC plugin
2 * Copyright (C) 2015 Centricular Ltd
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
25 #include "gstnvh264enc.h"
26 #include "gstnvh265enc.h"
27 #include "gstcudabufferpool.h"
31 #if HAVE_NVCODEC_GST_GL
32 #include <gst/gl/gl.h>
37 #define NVENC_LIBRARY_NAME "nvEncodeAPI64.dll"
39 #define NVENC_LIBRARY_NAME "nvEncodeAPI.dll"
42 #define NVENC_LIBRARY_NAME "libnvidia-encode.so.1"
45 /* For backward compatibility */
46 #define GST_NVENC_MIN_API_MAJOR_VERSION 8
47 #define GST_NVENC_MIN_API_MINOR_VERSION 1
49 #define GST_NVENCAPI_VERSION(major,minor) ((major) | ((minor) << 24))
50 #define GST_NVENCAPI_STRUCT_VERSION(ver,api_ver) ((uint32_t)(api_ver) | ((ver)<<16) | (0x7 << 28))
52 static guint32 gst_nvenc_api_version = NVENCAPI_VERSION;
54 typedef NVENCSTATUS NVENCAPI
55 tNvEncodeAPICreateInstance (NV_ENCODE_API_FUNCTION_LIST * functionList);
56 tNvEncodeAPICreateInstance *nvEncodeAPICreateInstance;
58 typedef NVENCSTATUS NVENCAPI
59 tNvEncodeAPIGetMaxSupportedVersion (uint32_t * version);
60 tNvEncodeAPIGetMaxSupportedVersion *nvEncodeAPIGetMaxSupportedVersion;
62 GST_DEBUG_CATEGORY_EXTERN (gst_nvenc_debug);
63 #define GST_CAT_DEFAULT gst_nvenc_debug
65 static NV_ENCODE_API_FUNCTION_LIST nvenc_api;
68 NvEncOpenEncodeSessionEx (NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS * params,
71 g_assert (nvenc_api.nvEncOpenEncodeSessionEx != NULL);
72 return nvenc_api.nvEncOpenEncodeSessionEx (params, encoder);
76 NvEncDestroyEncoder (void *encoder)
78 g_assert (nvenc_api.nvEncDestroyEncoder != NULL);
79 return nvenc_api.nvEncDestroyEncoder (encoder);
83 NvEncGetEncodeGUIDs (void *encoder, GUID * array, uint32_t array_size,
86 g_assert (nvenc_api.nvEncGetEncodeGUIDs != NULL);
87 return nvenc_api.nvEncGetEncodeGUIDs (encoder, array, array_size, count);
91 NvEncGetEncodeProfileGUIDCount (void *encoder, GUID encodeGUID,
92 uint32_t * encodeProfileGUIDCount)
94 g_assert (nvenc_api.nvEncGetEncodeProfileGUIDCount != NULL);
95 return nvenc_api.nvEncGetEncodeProfileGUIDCount (encoder, encodeGUID,
96 encodeProfileGUIDCount);
100 NvEncGetEncodeProfileGUIDs (void *encoder, GUID encodeGUID,
101 GUID * profileGUIDs, uint32_t guidArraySize, uint32_t * GUIDCount)
103 g_assert (nvenc_api.nvEncGetEncodeProfileGUIDs != NULL);
104 return nvenc_api.nvEncGetEncodeProfileGUIDs (encoder, encodeGUID,
105 profileGUIDs, guidArraySize, GUIDCount);
109 NvEncGetInputFormats (void *encoder, GUID enc_guid,
110 NV_ENC_BUFFER_FORMAT * array, uint32_t size, uint32_t * num)
112 g_assert (nvenc_api.nvEncGetInputFormats != NULL);
113 return nvenc_api.nvEncGetInputFormats (encoder, enc_guid, array, size, num);
117 NvEncGetEncodePresetCount (void *encoder, GUID encodeGUID,
118 uint32_t * encodePresetGUIDCount)
120 g_assert (nvenc_api.nvEncGetEncodeProfileGUIDCount != NULL);
121 return nvenc_api.nvEncGetEncodePresetCount (encoder, encodeGUID,
122 encodePresetGUIDCount);
126 NvEncGetEncodePresetGUIDs (void *encoder, GUID encodeGUID,
127 GUID * presetGUIDs, uint32_t guidArraySize, uint32_t * GUIDCount)
129 g_assert (nvenc_api.nvEncGetEncodeProfileGUIDs != NULL);
130 return nvenc_api.nvEncGetEncodePresetGUIDs (encoder, encodeGUID,
131 presetGUIDs, guidArraySize, GUIDCount);
135 NvEncGetEncodePresetConfig (void *encoder, GUID encodeGUID,
136 GUID presetGUID, NV_ENC_PRESET_CONFIG * presetConfig)
138 g_assert (nvenc_api.nvEncGetEncodePresetConfig != NULL);
139 return nvenc_api.nvEncGetEncodePresetConfig (encoder, encodeGUID, presetGUID,
144 NvEncGetEncodeCaps (void *encoder, GUID encodeGUID,
145 NV_ENC_CAPS_PARAM * capsParam, int *capsVal)
147 g_assert (nvenc_api.nvEncGetEncodeCaps != NULL);
148 return nvenc_api.nvEncGetEncodeCaps (encoder, encodeGUID, capsParam, capsVal);
152 NvEncGetSequenceParams (void *encoder,
153 NV_ENC_SEQUENCE_PARAM_PAYLOAD * sequenceParamPayload)
155 g_assert (nvenc_api.nvEncGetSequenceParams != NULL);
156 return nvenc_api.nvEncGetSequenceParams (encoder, sequenceParamPayload);
160 NvEncInitializeEncoder (void *encoder, NV_ENC_INITIALIZE_PARAMS * params)
162 g_assert (nvenc_api.nvEncInitializeEncoder != NULL);
163 return nvenc_api.nvEncInitializeEncoder (encoder, params);
167 NvEncReconfigureEncoder (void *encoder, NV_ENC_RECONFIGURE_PARAMS * params)
169 g_assert (nvenc_api.nvEncReconfigureEncoder != NULL);
170 return nvenc_api.nvEncReconfigureEncoder (encoder, params);
174 NvEncRegisterResource (void *encoder, NV_ENC_REGISTER_RESOURCE * params)
176 g_assert (nvenc_api.nvEncRegisterResource != NULL);
177 return nvenc_api.nvEncRegisterResource (encoder, params);
181 NvEncUnregisterResource (void *encoder, NV_ENC_REGISTERED_PTR resource)
183 g_assert (nvenc_api.nvEncUnregisterResource != NULL);
184 return nvenc_api.nvEncUnregisterResource (encoder, resource);
188 NvEncMapInputResource (void *encoder, NV_ENC_MAP_INPUT_RESOURCE * params)
190 g_assert (nvenc_api.nvEncMapInputResource != NULL);
191 return nvenc_api.nvEncMapInputResource (encoder, params);
195 NvEncUnmapInputResource (void *encoder, NV_ENC_INPUT_PTR input_buffer)
197 g_assert (nvenc_api.nvEncUnmapInputResource != NULL);
198 return nvenc_api.nvEncUnmapInputResource (encoder, input_buffer);
202 NvEncCreateInputBuffer (void *encoder, NV_ENC_CREATE_INPUT_BUFFER * input_buf)
204 g_assert (nvenc_api.nvEncCreateInputBuffer != NULL);
205 return nvenc_api.nvEncCreateInputBuffer (encoder, input_buf);
209 NvEncLockInputBuffer (void *encoder, NV_ENC_LOCK_INPUT_BUFFER * input_buf)
211 g_assert (nvenc_api.nvEncLockInputBuffer != NULL);
212 return nvenc_api.nvEncLockInputBuffer (encoder, input_buf);
216 NvEncUnlockInputBuffer (void *encoder, NV_ENC_INPUT_PTR input_buf)
218 g_assert (nvenc_api.nvEncUnlockInputBuffer != NULL);
219 return nvenc_api.nvEncUnlockInputBuffer (encoder, input_buf);
223 NvEncDestroyInputBuffer (void *encoder, NV_ENC_INPUT_PTR input_buf)
225 g_assert (nvenc_api.nvEncDestroyInputBuffer != NULL);
226 return nvenc_api.nvEncDestroyInputBuffer (encoder, input_buf);
230 NvEncCreateBitstreamBuffer (void *encoder, NV_ENC_CREATE_BITSTREAM_BUFFER * bb)
232 g_assert (nvenc_api.nvEncCreateBitstreamBuffer != NULL);
233 return nvenc_api.nvEncCreateBitstreamBuffer (encoder, bb);
237 NvEncLockBitstream (void *encoder, NV_ENC_LOCK_BITSTREAM * lock_bs)
239 g_assert (nvenc_api.nvEncLockBitstream != NULL);
240 return nvenc_api.nvEncLockBitstream (encoder, lock_bs);
244 NvEncUnlockBitstream (void *encoder, NV_ENC_OUTPUT_PTR bb)
246 g_assert (nvenc_api.nvEncUnlockBitstream != NULL);
247 return nvenc_api.nvEncUnlockBitstream (encoder, bb);
251 NvEncDestroyBitstreamBuffer (void *encoder, NV_ENC_OUTPUT_PTR bit_buf)
253 g_assert (nvenc_api.nvEncDestroyBitstreamBuffer != NULL);
254 return nvenc_api.nvEncDestroyBitstreamBuffer (encoder, bit_buf);
258 NvEncEncodePicture (void *encoder, NV_ENC_PIC_PARAMS * pic_params)
260 g_assert (nvenc_api.nvEncEncodePicture != NULL);
261 return nvenc_api.nvEncEncodePicture (encoder, pic_params);
265 gst_nvenc_cmp_guid (GUID g1, GUID g2)
267 return (g1.Data1 == g2.Data1 && g1.Data2 == g2.Data2 && g1.Data3 == g2.Data3
268 && g1.Data4[0] == g2.Data4[0] && g1.Data4[1] == g2.Data4[1]
269 && g1.Data4[2] == g2.Data4[2] && g1.Data4[3] == g2.Data4[3]
270 && g1.Data4[4] == g2.Data4[4] && g1.Data4[5] == g2.Data4[5]
271 && g1.Data4[6] == g2.Data4[6] && g1.Data4[7] == g2.Data4[7]);
275 gst_nvenc_get_nv_buffer_format (GstVideoFormat fmt)
278 case GST_VIDEO_FORMAT_NV12:
279 return NV_ENC_BUFFER_FORMAT_NV12_PL;
280 case GST_VIDEO_FORMAT_YV12:
281 return NV_ENC_BUFFER_FORMAT_YV12_PL;
282 case GST_VIDEO_FORMAT_I420:
283 return NV_ENC_BUFFER_FORMAT_IYUV_PL;
284 case GST_VIDEO_FORMAT_Y444:
285 return NV_ENC_BUFFER_FORMAT_YUV444_PL;
286 case GST_VIDEO_FORMAT_P010_10LE:
287 case GST_VIDEO_FORMAT_P010_10BE:
288 return NV_ENC_BUFFER_FORMAT_YUV420_10BIT;
289 case GST_VIDEO_FORMAT_BGRA:
290 return NV_ENC_BUFFER_FORMAT_ARGB;
291 case GST_VIDEO_FORMAT_RGBA:
292 return NV_ENC_BUFFER_FORMAT_ABGR;
293 case GST_VIDEO_FORMAT_BGR10A2_LE:
294 return NV_ENC_BUFFER_FORMAT_ARGB10;
295 case GST_VIDEO_FORMAT_RGB10A2_LE:
296 return NV_ENC_BUFFER_FORMAT_ABGR10;
297 case GST_VIDEO_FORMAT_Y444_16LE:
298 case GST_VIDEO_FORMAT_Y444_16BE:
299 return NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
300 case GST_VIDEO_FORMAT_VUYA:
301 return NV_ENC_BUFFER_FORMAT_AYUV;
305 return NV_ENC_BUFFER_FORMAT_UNDEFINED;
310 GstVideoFormat gst_format;
311 NV_ENC_BUFFER_FORMAT nv_format;
318 gst_nvenc_get_supported_input_formats (gpointer encoder, GUID codec_id,
321 guint32 i, count = 0;
322 NV_ENC_BUFFER_FORMAT format_list[64];
323 GValue val = G_VALUE_INIT;
325 NV_ENC_CAPS_PARAM param = { 0, };
326 gint support_yuv444 = 0;
327 gint support_10bit = 0;
328 guint num_format = 0;
329 GstNvEncFormat format_map[] = {
330 {GST_VIDEO_FORMAT_NV12, NV_ENC_BUFFER_FORMAT_NV12, FALSE, FALSE},
331 {GST_VIDEO_FORMAT_YV12, NV_ENC_BUFFER_FORMAT_YV12, FALSE, FALSE},
332 {GST_VIDEO_FORMAT_I420, NV_ENC_BUFFER_FORMAT_IYUV, FALSE, FALSE},
333 {GST_VIDEO_FORMAT_BGRA, NV_ENC_BUFFER_FORMAT_ARGB, FALSE, FALSE},
334 {GST_VIDEO_FORMAT_RGBA, NV_ENC_BUFFER_FORMAT_ABGR, FALSE, FALSE},
335 {GST_VIDEO_FORMAT_Y444, NV_ENC_BUFFER_FORMAT_YUV444, FALSE, FALSE},
336 {GST_VIDEO_FORMAT_VUYA, NV_ENC_BUFFER_FORMAT_AYUV, FALSE, FALSE},
337 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
338 {GST_VIDEO_FORMAT_P010_10LE, NV_ENC_BUFFER_FORMAT_YUV420_10BIT, TRUE,
340 {GST_VIDEO_FORMAT_BGR10A2_LE, NV_ENC_BUFFER_FORMAT_ARGB10, TRUE,
342 {GST_VIDEO_FORMAT_RGB10A2_LE, NV_ENC_BUFFER_FORMAT_ABGR10, TRUE,
344 {GST_VIDEO_FORMAT_Y444_16LE, NV_ENC_BUFFER_FORMAT_YUV444_10BIT, TRUE,
347 {GST_VIDEO_FORMAT_P010_10BE, NV_ENC_BUFFER_FORMAT_YUV420_10BIT, TRUE,
349 {GST_VIDEO_FORMAT_Y444_16BE, NV_ENC_BUFFER_FORMAT_YUV444_10BIT, TRUE,
351 /* FIXME: No 10bits big-endian ARGB10 format is defined */
355 param.version = gst_nvenc_get_caps_param_version ();
356 param.capsToQuery = NV_ENC_CAPS_SUPPORT_YUV444_ENCODE;
357 if (NvEncGetEncodeCaps (encoder,
358 codec_id, ¶m, &support_yuv444) != NV_ENC_SUCCESS) {
362 param.capsToQuery = NV_ENC_CAPS_SUPPORT_10BIT_ENCODE;
363 if (NvEncGetEncodeCaps (encoder,
364 codec_id, ¶m, &support_10bit) != NV_ENC_SUCCESS) {
368 if (NvEncGetInputFormats (encoder,
369 codec_id, format_list, G_N_ELEMENTS (format_list),
370 &count) != NV_ENC_SUCCESS || count == 0) {
374 for (i = 0; i < count; i++) {
375 GST_INFO ("input format: 0x%08x", format_list[i]);
376 switch (format_list[i]) {
377 case NV_ENC_BUFFER_FORMAT_NV12:
378 case NV_ENC_BUFFER_FORMAT_YV12:
379 case NV_ENC_BUFFER_FORMAT_IYUV:
380 case NV_ENC_BUFFER_FORMAT_ARGB:
381 case NV_ENC_BUFFER_FORMAT_ABGR:
382 if (!format_map[i].supported) {
383 format_map[i].supported = TRUE;
387 case NV_ENC_BUFFER_FORMAT_YUV444:
388 case NV_ENC_BUFFER_FORMAT_AYUV:
389 if (support_yuv444 && !format_map[i].supported) {
390 format_map[i].supported = TRUE;
394 case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
395 if (support_10bit && !format_map[i].supported) {
396 format_map[i].supported = TRUE;
400 case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
401 if (support_yuv444 && support_10bit && !format_map[i].supported) {
402 format_map[i].supported = TRUE;
406 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
407 case NV_ENC_BUFFER_FORMAT_ARGB10:
408 case NV_ENC_BUFFER_FORMAT_ABGR10:
409 if (support_10bit && !format_map[i].supported) {
410 format_map[i].supported = TRUE;
416 GST_FIXME ("unmapped input format: 0x%08x", format_list[i]);
424 /* process a second time so we can add formats in the order we want */
425 g_value_init (&val, G_TYPE_STRING);
426 ret = g_new0 (GValue, 1);
427 g_value_init (ret, GST_TYPE_LIST);
429 for (i = 0; i < G_N_ELEMENTS (format_map); i++) {
430 if (!format_map[i].supported)
433 g_value_set_static_string (&val,
434 gst_video_format_to_string (format_map[i].gst_format));
436 gst_value_list_append_value (ret, &val);
439 g_value_unset (&val);
447 gst_nvenc_get_interlace_modes (gpointer enc, GUID codec_id)
449 NV_ENC_CAPS_PARAM caps_param = { 0, };
451 GValue val = G_VALUE_INIT;
452 gint interlace_modes = 0;
454 caps_param.version = gst_nvenc_get_caps_param_version ();
455 caps_param.capsToQuery = NV_ENC_CAPS_SUPPORT_FIELD_ENCODING;
457 if (NvEncGetEncodeCaps (enc, codec_id, &caps_param,
458 &interlace_modes) != NV_ENC_SUCCESS)
461 list = g_new0 (GValue, 1);
463 g_value_init (list, GST_TYPE_LIST);
464 g_value_init (&val, G_TYPE_STRING);
466 g_value_set_static_string (&val, "progressive");
467 gst_value_list_append_value (list, &val);
469 if (interlace_modes == 0)
472 if (interlace_modes >= 1) {
473 g_value_set_static_string (&val, "interleaved");
474 gst_value_list_append_value (list, &val);
475 g_value_set_static_string (&val, "mixed");
476 gst_value_list_append_value (list, &val);
477 g_value_unset (&val);
479 /* TODO: figure out what nvenc frame based interlacing means in gst terms */
486 const gchar *gst_profile;
487 const GUID nv_profile;
489 const gboolean need_yuv444;
490 const gboolean need_10bit;
493 } GstNvEncCodecProfile;
496 gst_nvenc_get_supported_codec_profiles (gpointer enc, GUID codec_id)
499 GUID profile_guids[64];
501 GValue val = G_VALUE_INIT;
502 guint i, j, n, n_profiles;
503 NV_ENC_CAPS_PARAM param = { 0, };
504 gint support_yuv444 = 0;
505 gint support_10bit = 0;
506 GstNvEncCodecProfile profiles[] = {
508 {"main", NV_ENC_H264_PROFILE_MAIN_GUID, NV_ENC_CODEC_H264_GUID, FALSE,
510 {"high", NV_ENC_H264_PROFILE_HIGH_GUID, NV_ENC_CODEC_H264_GUID, FALSE,
512 {"high-4:4:4", NV_ENC_H264_PROFILE_HIGH_444_GUID, NV_ENC_CODEC_H264_GUID,
514 /* put baseline to last since it does not support bframe */
515 {"baseline", NV_ENC_H264_PROFILE_BASELINE_GUID, NV_ENC_CODEC_H264_GUID,
516 FALSE, FALSE, FALSE},
518 {"main", NV_ENC_HEVC_PROFILE_MAIN_GUID, NV_ENC_CODEC_HEVC_GUID, FALSE,
520 {"main-10", NV_ENC_HEVC_PROFILE_MAIN10_GUID, NV_ENC_CODEC_HEVC_GUID, FALSE,
522 {"main-444", NV_ENC_HEVC_PROFILE_FREXT_GUID, NV_ENC_CODEC_HEVC_GUID, TRUE,
525 /* FIXME: seems to unsupported format */
526 {"main-444-10", NV_ENC_HEVC_PROFILE_FREXT_GUID, FALSE}
530 param.version = gst_nvenc_get_caps_param_version ();
531 param.capsToQuery = NV_ENC_CAPS_SUPPORT_YUV444_ENCODE;
532 if (NvEncGetEncodeCaps (enc,
533 codec_id, ¶m, &support_yuv444) != NV_ENC_SUCCESS) {
537 param.capsToQuery = NV_ENC_CAPS_SUPPORT_10BIT_ENCODE;
538 if (NvEncGetEncodeCaps (enc,
539 codec_id, ¶m, &support_10bit) != NV_ENC_SUCCESS) {
543 nv_ret = NvEncGetEncodeProfileGUIDCount (enc, codec_id, &n);
545 if (nv_ret != NV_ENC_SUCCESS)
548 nv_ret = NvEncGetEncodeProfileGUIDs (enc,
549 codec_id, profile_guids, G_N_ELEMENTS (profile_guids), &n);
551 if (nv_ret != NV_ENC_SUCCESS)
556 for (i = 0; i < n; i++) {
557 for (j = 0; j < G_N_ELEMENTS (profiles); j++) {
558 if (profiles[j].supported == FALSE &&
559 gst_nvenc_cmp_guid (profile_guids[i], profiles[j].nv_profile) &&
560 gst_nvenc_cmp_guid (codec_id, profiles[j].codec_id)) {
561 if (profiles[j].need_yuv444 && !support_yuv444)
564 if (profiles[j].need_10bit && !support_10bit)
567 profiles[j].supported = TRUE;
576 ret = g_new0 (GValue, 1);
578 g_value_init (ret, GST_TYPE_LIST);
579 g_value_init (&val, G_TYPE_STRING);
581 for (i = 0; i < G_N_ELEMENTS (profiles); i++) {
582 if (!profiles[i].supported)
585 g_value_set_static_string (&val, profiles[i].gst_profile);
586 gst_value_list_append_value (ret, &val);
589 g_value_unset (&val);
594 #define DEBUG_DEVICE_CAPS(d,c,caps,s) \
595 GST_DEBUG ("[device-%d %s] %s: %s", \
596 d, c, caps, s ? "supported" : "not supported");
598 #define ERROR_DETAILS "codec %s, device %i, error code %i"
601 gst_nv_enc_register (GstPlugin * plugin, GUID codec_id, const gchar * codec,
602 guint rank, gint device_index, CUcontext cuda_ctx)
605 GValue *formats = NULL;
607 GValue *interlace_modes;
609 NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = { 0, };
610 NV_ENC_CAPS_PARAM caps_param = { 0, };
616 gint min_height = 16;
617 GstCaps *sink_templ = NULL;
618 GstCaps *src_templ = NULL;
621 GstNvEncDeviceCaps device_caps = { 0, };
625 params.version = gst_nvenc_get_open_encode_session_ex_params_version ();
626 params.apiVersion = gst_nvenc_get_api_version ();
627 params.device = cuda_ctx;
628 params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
630 if ((cu_res = CuCtxPushCurrent (cuda_ctx)) != CUDA_SUCCESS) {
631 GST_ERROR ("CuCtxPushCurrent failed: " ERROR_DETAILS, codec,
632 device_index, cu_res);
636 if ((status = NvEncOpenEncodeSessionEx (¶ms, &enc)) != NV_ENC_SUCCESS) {
637 CuCtxPopCurrent (NULL);
638 GST_ERROR ("NvEncOpenEncodeSessionEx failed: " ERROR_DETAILS, codec,
639 device_index, status);
643 if ((status = NvEncGetEncodeGUIDs (enc, guids, G_N_ELEMENTS (guids),
644 &count)) != NV_ENC_SUCCESS) {
645 GST_ERROR ("NvEncGetEncodeGUIDs failed: " ERROR_DETAILS, codec,
646 device_index, status);
650 for (j = 0; j < count; j++) {
651 if (gst_nvenc_cmp_guid (guids[j], codec_id))
658 if (!gst_nvenc_get_supported_input_formats (enc, codec_id, &formats))
661 profiles = gst_nvenc_get_supported_codec_profiles (enc, codec_id);
665 caps_param.version = gst_nvenc_get_caps_param_version ();
666 caps_param.capsToQuery = NV_ENC_CAPS_WIDTH_MAX;
667 if ((status = NvEncGetEncodeCaps (enc,
668 codec_id, &caps_param, &max_width)) != NV_ENC_SUCCESS) {
670 GST_WARNING ("could not query max width, setting as %i: "
671 ERROR_DETAILS, max_width, codec, device_index, status);
672 } else if (max_width < 4096) {
673 GST_WARNING ("max width %d is less than expected value", max_width);
677 caps_param.capsToQuery = NV_ENC_CAPS_HEIGHT_MAX;
678 if ((status = NvEncGetEncodeCaps (enc,
679 codec_id, &caps_param, &max_height)) != NV_ENC_SUCCESS) {
680 GST_WARNING ("could not query max height, setting as %i: "
681 ERROR_DETAILS, max_height, codec, device_index, status);
683 } else if (max_height < 4096) {
684 GST_WARNING ("max height %d is less than expected value", max_height);
688 caps_param.capsToQuery = NV_ENC_CAPS_WIDTH_MIN;
689 if ((status = NvEncGetEncodeCaps (enc,
690 codec_id, &caps_param, &min_width)) != NV_ENC_SUCCESS) {
691 GST_WARNING ("could not query min width, setting as %i: "
692 ERROR_DETAILS, min_width, codec, device_index, status);
696 caps_param.capsToQuery = NV_ENC_CAPS_HEIGHT_MIN;
697 if ((status = NvEncGetEncodeCaps (enc,
698 codec_id, &caps_param, &min_height)) != NV_ENC_SUCCESS) {
699 GST_WARNING ("could not query min height, setting as %i: "
700 ERROR_DETAILS, min_height, codec, device_index, status);
704 caps_param.capsToQuery = NV_ENC_CAPS_SUPPORTED_RATECONTROL_MODES;
705 if (NvEncGetEncodeCaps (enc, codec_id, &caps_param,
706 &device_caps.rc_modes) != NV_ENC_SUCCESS) {
707 device_caps.rc_modes = 0;
709 GST_DEBUG ("[device-%d %s] rate control modes: 0x%x",
710 device_index, codec, device_caps.rc_modes);
711 #define IS_SUPPORTED_RC(rc_modes,mode) \
712 ((((rc_modes) & (mode)) == mode) ? "supported" : "not supported")
714 GST_DEBUG ("\tconst-qp: %s",
715 IS_SUPPORTED_RC (device_caps.rc_modes, NV_ENC_PARAMS_RC_CONSTQP));
716 GST_DEBUG ("\tvbr: %s",
717 IS_SUPPORTED_RC (device_caps.rc_modes, NV_ENC_PARAMS_RC_VBR));
718 GST_DEBUG ("\tcbr: %s",
719 IS_SUPPORTED_RC (device_caps.rc_modes, NV_ENC_PARAMS_RC_CBR));
720 GST_DEBUG ("\tcbr-lowdelay-hq: %s",
721 IS_SUPPORTED_RC (device_caps.rc_modes,
722 NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ));
723 GST_DEBUG ("\tcbr-hq: %s",
724 IS_SUPPORTED_RC (device_caps.rc_modes, NV_ENC_PARAMS_RC_CBR_HQ));
725 GST_DEBUG ("\tvbr-hq: %s",
726 IS_SUPPORTED_RC (device_caps.rc_modes, NV_ENC_PARAMS_RC_VBR_HQ));
727 GST_DEBUG ("\tvbr-minqp: %s (deprecated)",
728 IS_SUPPORTED_RC (device_caps.rc_modes, NV_ENC_PARAMS_RC_VBR_MINQP));
729 #undef IS_SUPPORTED_RC
732 caps_param.capsToQuery = NV_ENC_CAPS_SUPPORT_WEIGHTED_PREDICTION;
733 if (NvEncGetEncodeCaps (enc, codec_id, &caps_param,
734 &device_caps.weighted_prediction) != NV_ENC_SUCCESS) {
735 device_caps.weighted_prediction = FALSE;
738 caps_param.capsToQuery = NV_ENC_CAPS_SUPPORT_CUSTOM_VBV_BUF_SIZE;
739 if (NvEncGetEncodeCaps (enc, codec_id, &caps_param,
740 &device_caps.custom_vbv_bufsize) != NV_ENC_SUCCESS) {
741 device_caps.custom_vbv_bufsize = FALSE;
744 caps_param.capsToQuery = NV_ENC_CAPS_SUPPORT_LOOKAHEAD;
745 if (NvEncGetEncodeCaps (enc,
746 codec_id, &caps_param, &device_caps.lookahead) != NV_ENC_SUCCESS) {
747 device_caps.lookahead = FALSE;
750 caps_param.capsToQuery = NV_ENC_CAPS_SUPPORT_TEMPORAL_AQ;
751 if (NvEncGetEncodeCaps (enc, codec_id, &caps_param,
752 &device_caps.temporal_aq) != NV_ENC_SUCCESS) {
753 device_caps.temporal_aq = FALSE;
756 caps_param.capsToQuery = NV_ENC_CAPS_NUM_MAX_BFRAMES;
757 if (NvEncGetEncodeCaps (enc, codec_id, &caps_param,
758 &device_caps.bframes) != NV_ENC_SUCCESS) {
759 device_caps.bframes = 0;
762 DEBUG_DEVICE_CAPS (device_index,
763 codec, "weighted prediction", device_caps.weighted_prediction);
765 DEBUG_DEVICE_CAPS (device_index, codec, "custom vbv-buffer-size",
766 device_caps.custom_vbv_bufsize);
768 DEBUG_DEVICE_CAPS (device_index, codec, "rc-loockahead",
769 device_caps.lookahead);
771 DEBUG_DEVICE_CAPS (device_index, codec, "temporal adaptive quantization",
772 device_caps.temporal_aq);
774 GST_DEBUG ("[device-%d %s] max bframes: %d", device_index, codec,
775 device_caps.bframes);
777 interlace_modes = gst_nvenc_get_interlace_modes (enc, codec_id);
779 sink_templ = gst_caps_new_empty_simple ("video/x-raw");
780 gst_caps_set_value (sink_templ, "format", formats);
782 gst_caps_set_simple (sink_templ,
783 "width", GST_TYPE_INT_RANGE, min_width, max_width,
784 "height", GST_TYPE_INT_RANGE, min_height, max_height,
785 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
787 if (interlace_modes) {
788 gst_caps_set_value (sink_templ, "interlace-mode", interlace_modes);
789 g_value_unset (interlace_modes);
790 g_free (interlace_modes);
794 GstCaps *cuda_caps = gst_caps_copy (sink_templ);
795 #if HAVE_NVCODEC_GST_GL
796 GstCaps *gl_caps = gst_caps_copy (sink_templ);
797 gst_caps_set_features_simple (gl_caps,
798 gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY));
799 gst_caps_append (sink_templ, gl_caps);
802 gst_caps_set_features_simple (cuda_caps,
803 gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY));
804 gst_caps_append (sink_templ, cuda_caps);
807 name = g_strdup_printf ("video/x-%s", codec);
808 src_templ = gst_caps_new_simple (name,
809 "width", GST_TYPE_INT_RANGE, min_width, max_width,
810 "height", GST_TYPE_INT_RANGE, min_height, max_height,
811 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
812 "stream-format", G_TYPE_STRING, "byte-stream",
813 "alignment", G_TYPE_STRING, "au", NULL);
814 gst_caps_set_value (src_templ, "profile", profiles);
817 GST_DEBUG ("sink template caps %" GST_PTR_FORMAT, sink_templ);
818 GST_DEBUG ("src template caps %" GST_PTR_FORMAT, src_templ);
820 g_value_unset (profiles);
825 g_value_unset (formats);
831 NvEncDestroyEncoder (enc);
832 CuCtxPopCurrent (NULL);
836 if (sink_templ && src_templ) {
837 if (gst_nvenc_cmp_guid (codec_id, NV_ENC_CODEC_H264_GUID)) {
838 gst_nv_h264_enc_register (plugin, device_index, rank, sink_templ,
839 src_templ, &device_caps);
840 } else if (gst_nvenc_cmp_guid (codec_id, NV_ENC_CODEC_HEVC_GUID)) {
841 gst_nv_h265_enc_register (plugin, device_index, rank, sink_templ,
842 src_templ, &device_caps);
844 g_assert_not_reached ();
848 gst_clear_caps (&sink_templ);
849 gst_clear_caps (&src_templ);
860 gst_nvenc_load_library (guint * api_major_ver, guint * api_minor_ver)
863 NVENCSTATUS ret = NV_ENC_SUCCESS;
864 uint32_t max_supported_version;
865 gint major_ver, minor_ver;
867 static const GstNvEncVersion version_list[] = {
868 {NVENCAPI_MAJOR_VERSION, NVENCAPI_MINOR_VERSION},
870 {GST_NVENC_MIN_API_MAJOR_VERSION, GST_NVENC_MIN_API_MINOR_VERSION}
873 module = g_module_open (NVENC_LIBRARY_NAME, G_MODULE_BIND_LAZY);
874 if (module == NULL) {
875 GST_WARNING ("Could not open library %s, %s",
876 NVENC_LIBRARY_NAME, g_module_error ());
880 if (!g_module_symbol (module, "NvEncodeAPICreateInstance",
881 (gpointer *) & nvEncodeAPICreateInstance)) {
882 GST_ERROR ("%s", g_module_error ());
886 if (!g_module_symbol (module, "NvEncodeAPIGetMaxSupportedVersion",
887 (gpointer *) & nvEncodeAPIGetMaxSupportedVersion)) {
888 GST_ERROR ("NvEncodeAPIGetMaxSupportedVersion unavailable");
892 /* WARNING: Any developers who want to bump SDK version must ensure that
893 * following macro values were not changed and also need to check ABI compatibility.
894 * Otherwise, gst_nvenc_get_ helpers also should be updated.
895 * Currently SDK 8.1 and 9.0 compatible
897 * NVENCAPI_VERSION (NVENCAPI_MAJOR_VERSION | (NVENCAPI_MINOR_VERSION << 24))
899 * NVENCAPI_STRUCT_VERSION(ver) ((uint32_t)NVENCAPI_VERSION | ((ver)<<16) | (0x7 << 28))
901 * NV_ENC_CAPS_PARAM_VER NVENCAPI_STRUCT_VERSION(1)
902 * NV_ENC_ENCODE_OUT_PARAMS_VER NVENCAPI_STRUCT_VERSION(1)
903 * NV_ENC_CREATE_INPUT_BUFFER_VER NVENCAPI_STRUCT_VERSION(1)
904 * NV_ENC_CREATE_BITSTREAM_BUFFER_VER NVENCAPI_STRUCT_VERSION(1)
905 * NV_ENC_CREATE_MV_BUFFER_VER NVENCAPI_STRUCT_VERSION(1)
906 * NV_ENC_RC_PARAMS_VER NVENCAPI_STRUCT_VERSION(1)
907 * NV_ENC_CONFIG_VER (NVENCAPI_STRUCT_VERSION(7) | ( 1<<31 ))
908 * NV_ENC_INITIALIZE_PARAMS_VER (NVENCAPI_STRUCT_VERSION(5) | ( 1<<31 ))
909 * NV_ENC_RECONFIGURE_PARAMS_VER (NVENCAPI_STRUCT_VERSION(1) | ( 1<<31 ))
910 * NV_ENC_PRESET_CONFIG_VER (NVENCAPI_STRUCT_VERSION(4) | ( 1<<31 ))
911 * NV_ENC_PIC_PARAMS_VER (NVENCAPI_STRUCT_VERSION(4) | ( 1<<31 ))
912 * NV_ENC_MEONLY_PARAMS_VER NVENCAPI_STRUCT_VERSION(3)
913 * NV_ENC_LOCK_BITSTREAM_VER NVENCAPI_STRUCT_VERSION(1)
914 * NV_ENC_LOCK_INPUT_BUFFER_VER NVENCAPI_STRUCT_VERSION(1)
915 * NV_ENC_MAP_INPUT_RESOURCE_VER NVENCAPI_STRUCT_VERSION(4)
916 * NV_ENC_REGISTER_RESOURCE_VER NVENCAPI_STRUCT_VERSION(3)
917 * NV_ENC_STAT_VER NVENCAPI_STRUCT_VERSION(1)
918 * NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER NVENCAPI_STRUCT_VERSION(1)
919 * NV_ENC_EVENT_PARAMS_VER NVENCAPI_STRUCT_VERSION(1)
920 * NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER NVENCAPI_STRUCT_VERSION(1)
921 * NV_ENCODE_API_FUNCTION_LIST_VER NVENCAPI_STRUCT_VERSION(2)
924 ret = nvEncodeAPIGetMaxSupportedVersion (&max_supported_version);
926 if (ret != NV_ENC_SUCCESS) {
927 GST_ERROR ("Could not query max supported api version, ret %d", ret);
931 /* 4 LSB: minor version
932 * the rest: major version */
933 major_ver = max_supported_version >> 4;
934 minor_ver = max_supported_version & 0xf;
936 GST_INFO ("Maximum supported API version by driver: %d.%d",
937 major_ver, minor_ver);
939 ret = NV_ENC_ERR_INVALID_VERSION;
940 for (i = 0; i < G_N_ELEMENTS (version_list); i++) {
941 if (version_list[i].major > major_ver ||
942 (version_list[i].major == major_ver
943 && version_list[i].minor > minor_ver)) {
947 gst_nvenc_api_version =
948 GST_NVENCAPI_VERSION (version_list[i].major, version_list[i].minor);
950 nvenc_api.version = GST_NVENCAPI_STRUCT_VERSION (2, gst_nvenc_api_version);
951 ret = nvEncodeAPICreateInstance (&nvenc_api);
953 if (ret == NV_ENC_SUCCESS) {
954 GST_INFO ("API version %d.%d load done",
955 version_list[i].major, version_list[i].minor);
957 *api_major_ver = version_list[i].major;
958 *api_minor_ver = version_list[i].minor;
963 return ret == NV_ENC_SUCCESS;
967 gst_nvenc_plugin_init (GstPlugin * plugin, guint device_index,
970 gst_nv_enc_register (plugin, NV_ENC_CODEC_H264_GUID,
971 "h264", GST_RANK_PRIMARY * 2, device_index, cuda_ctx);
972 gst_nv_enc_register (plugin, NV_ENC_CODEC_HEVC_GUID,
973 "h265", GST_RANK_PRIMARY * 2, device_index, cuda_ctx);
977 gst_nvenc_get_api_version (void)
979 /* NVENCAPI_VERSION == (NVENCAPI_MAJOR_VERSION | (NVENCAPI_MINOR_VERSION << 24)) */
980 return gst_nvenc_api_version;
984 gst_nvenc_get_caps_param_version (void)
986 /* NV_ENC_CAPS_PARAM_VER == NVENCAPI_STRUCT_VERSION(1) */
987 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
991 gst_nvenc_get_encode_out_params_version (void)
993 /* NV_ENC_ENCODE_OUT_PARAMS_VER == NVENCAPI_STRUCT_VERSION(1) */
994 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
998 gst_nvenc_get_create_input_buffer_version (void)
1000 /* NV_ENC_CREATE_INPUT_BUFFER_VER == NVENCAPI_STRUCT_VERSION(1) */
1001 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1005 gst_nvenc_get_create_bitstream_buffer_version (void)
1007 /* NV_ENC_CREATE_BITSTREAM_BUFFER_VER == NVENCAPI_STRUCT_VERSION(1) */
1008 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1012 gst_nvenc_get_create_mv_buffer_version (void)
1014 /* NV_ENC_CREATE_MV_BUFFER_VER == NVENCAPI_STRUCT_VERSION(1) */
1015 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1019 gst_nvenc_get_rc_params_version (void)
1021 /* NV_ENC_RC_PARAMS_VER == NVENCAPI_STRUCT_VERSION(1) */
1022 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1026 gst_nvenc_get_config_version (void)
1028 /* NV_ENC_CONFIG_VER ==
1029 * (NVENCAPI_STRUCT_VERSION(7) | ( 1<<31 )) */
1030 return GST_NVENCAPI_STRUCT_VERSION (7, gst_nvenc_api_version) | (1 << 31);
1034 gst_nvenc_get_initialize_params_version (void)
1036 /* NV_ENC_INITIALIZE_PARAMS_VER ==
1037 * (NVENCAPI_STRUCT_VERSION(5) | ( 1<<31 )) */
1038 return GST_NVENCAPI_STRUCT_VERSION (5, gst_nvenc_api_version) | (1 << 31);
1042 gst_nvenc_get_reconfigure_params_version (void)
1044 /* NV_ENC_RECONFIGURE_PARAMS_VER ==
1045 * (NVENCAPI_STRUCT_VERSION(1) | ( 1<<31 )) */
1046 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version) | (1 << 31);
1050 gst_nvenc_get_preset_config_version (void)
1052 /* NV_ENC_PRESET_CONFIG_VER ==
1053 * (NVENCAPI_STRUCT_VERSION(4) | ( 1<<31 )) */
1054 return GST_NVENCAPI_STRUCT_VERSION (4, gst_nvenc_api_version) | (1 << 31);
1058 gst_nvenc_get_pic_params_version (void)
1060 /* NV_ENC_PIC_PARAMS_VER ==
1061 * (NVENCAPI_STRUCT_VERSION(4) | ( 1<<31 )) */
1062 return GST_NVENCAPI_STRUCT_VERSION (4, gst_nvenc_api_version) | (1 << 31);
1066 gst_nvenc_get_meonly_params_version (void)
1068 /* NV_ENC_MEONLY_PARAMS_VER == NVENCAPI_STRUCT_VERSION(3) */
1069 return GST_NVENCAPI_STRUCT_VERSION (3, gst_nvenc_api_version);
1073 gst_nvenc_get_lock_bitstream_version (void)
1075 /* NV_ENC_LOCK_BITSTREAM_VER == NVENCAPI_STRUCT_VERSION(1) */
1076 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1080 gst_nvenc_get_lock_input_buffer_version (void)
1082 /* NV_ENC_LOCK_INPUT_BUFFER_VER == NVENCAPI_STRUCT_VERSION(1) */
1083 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1087 gst_nvenc_get_map_input_resource_version (void)
1089 /* NV_ENC_MAP_INPUT_RESOURCE_VER == NVENCAPI_STRUCT_VERSION(4) */
1090 return GST_NVENCAPI_STRUCT_VERSION (4, gst_nvenc_api_version);
1094 gst_nvenc_get_register_resource_version (void)
1096 /* NV_ENC_REGISTER_RESOURCE_VER == NVENCAPI_STRUCT_VERSION(3) */
1097 return GST_NVENCAPI_STRUCT_VERSION (3, gst_nvenc_api_version);
1101 gst_nvenc_get_stat_version (void)
1103 /* NV_ENC_STAT_VER == NVENCAPI_STRUCT_VERSION(1) */
1104 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1108 gst_nvenc_get_sequence_param_payload_version (void)
1110 /* NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER == NVENCAPI_STRUCT_VERSION(1) */
1111 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1115 gst_nvenc_get_event_params_version (void)
1117 /* NV_ENC_EVENT_PARAMS_VER == NVENCAPI_STRUCT_VERSION(1) */
1118 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);
1122 gst_nvenc_get_open_encode_session_ex_params_version (void)
1124 /* NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER == NVENCAPI_STRUCT_VERSION(1) */
1125 return GST_NVENCAPI_STRUCT_VERSION (1, gst_nvenc_api_version);