2df752962428d79c907eb0cbe6c2ab452964e08a
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / nvcodec / plugin.c
1 /*
2  * Copyright (C) 2017 Ericsson AB. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "gstnvdec.h"
33 #include "gstnvenc.h"
34 #include "gstnvh264dec.h"
35 #include "gstnvh265dec.h"
36 #include "gstnvvp8dec.h"
37 #include "gstnvvp9dec.h"
38 #include "gstnvdecoder.h"
39 #include "gstcudamemorycopy.h"
40 #include "gstcudafilter.h"
41 #include "gstcudamemory.h"
42 #ifdef HAVE_NVCODEC_NVMM
43 #include "gstcudanvmm.h"
44 #endif
45
46 #ifdef HAVE_NVCODEC_GST_D3D11
47 #include <gst/d3d11/gstd3d11.h>
48 #endif
49 #include "gstnvh264encoder.h"
50 #include "gstnvh265encoder.h"
51
52 GST_DEBUG_CATEGORY (gst_nvcodec_debug);
53 GST_DEBUG_CATEGORY (gst_nvdec_debug);
54 GST_DEBUG_CATEGORY (gst_nvenc_debug);
55 GST_DEBUG_CATEGORY (gst_nv_decoder_debug);
56
57 #ifdef HAVE_NVCODEC_NVMM
58 GST_DEBUG_CATEGORY (gst_cuda_nvmm_debug);
59 #endif
60
61 #define GST_CAT_DEFAULT gst_nvcodec_debug
62
63 static gboolean
64 plugin_init (GstPlugin * plugin)
65 {
66   CUresult cuda_ret;
67   gint dev_count = 0;
68   guint i;
69   gboolean nvdec_available = TRUE;
70   gboolean nvenc_available = TRUE;
71   /* hardcoded minimum supported version */
72   guint api_major_ver = 8;
73   guint api_minor_ver = 1;
74   const gchar *env;
75   gboolean use_h264_sl_dec = FALSE;
76   gboolean use_h265_sl_dec = FALSE;
77   gboolean use_vp8_sl_dec = FALSE;
78   gboolean use_vp9_sl_dec = FALSE;
79
80   GST_DEBUG_CATEGORY_INIT (gst_nvcodec_debug, "nvcodec", 0, "nvcodec");
81   GST_DEBUG_CATEGORY_INIT (gst_nvdec_debug, "nvdec", 0, "nvdec");
82   GST_DEBUG_CATEGORY_INIT (gst_nvenc_debug, "nvenc", 0, "nvenc");
83   GST_DEBUG_CATEGORY_INIT (gst_nv_decoder_debug, "nvdecoder", 0, "nvdecoder");
84
85 #ifdef HAVE_NVCODEC_NVMM
86   GST_DEBUG_CATEGORY_INIT (gst_cuda_nvmm_debug, "cudanvmm", 0, "cudanvmm");
87 #endif
88
89   if (!gst_cuda_load_library ()) {
90     GST_WARNING ("Failed to load cuda library");
91     return TRUE;
92   }
93
94   /* get available API version from nvenc and it will be passed to
95    * nvdec */
96   if (!gst_nvenc_load_library (&api_major_ver, &api_minor_ver)) {
97     GST_WARNING ("Failed to load nvenc library");
98     nvenc_available = FALSE;
99   }
100
101   if (!gst_cuvid_load_library (api_major_ver, api_minor_ver)) {
102     GST_WARNING ("Failed to load nvdec library");
103     nvdec_available = FALSE;
104   }
105
106   if (!nvdec_available && !nvenc_available)
107     return TRUE;
108
109   cuda_ret = CuInit (0);
110   if (cuda_ret != CUDA_SUCCESS) {
111     GST_WARNING ("Failed to init cuda, ret: 0x%x", (gint) cuda_ret);
112     return TRUE;
113   }
114
115   if (CuDeviceGetCount (&dev_count) != CUDA_SUCCESS || !dev_count) {
116     GST_WARNING ("No available device, ret: 0x%x", (gint) cuda_ret);
117     return TRUE;
118   }
119
120   /* check environment to determine primary h264decoder */
121   env = g_getenv ("GST_USE_NV_STATELESS_CODEC");
122   if (env) {
123     gchar **split;
124     gchar **iter;
125
126     split = g_strsplit (env, ",", 0);
127
128     for (iter = split; *iter; iter++) {
129       if (g_ascii_strcasecmp (*iter, "h264") == 0) {
130         GST_INFO ("Found %s in GST_USE_NV_STATELESS_CODEC environment", *iter);
131         use_h264_sl_dec = TRUE;
132       } else if (g_ascii_strcasecmp (*iter, "h265") == 0) {
133         GST_INFO ("Found %s in GST_USE_NV_STATELESS_CODEC environment", *iter);
134         use_h265_sl_dec = TRUE;
135       } else if (g_ascii_strcasecmp (*iter, "vp8") == 0) {
136         GST_INFO ("Found %s in GST_USE_NV_STATELESS_CODEC environment", *iter);
137         use_vp8_sl_dec = TRUE;
138       } else if (g_ascii_strcasecmp (*iter, "vp9") == 0) {
139         GST_INFO ("Found %s in GST_USE_NV_STATELESS_CODEC environment", *iter);
140         use_vp9_sl_dec = TRUE;
141       }
142     }
143
144     g_strfreev (split);
145   }
146
147   for (i = 0; i < dev_count; i++) {
148     GstCudaContext *context = gst_cuda_context_new (i);
149     CUcontext cuda_ctx;
150
151     if (!context) {
152       GST_WARNING ("Failed to create context for deevice %d", i);
153       continue;
154     }
155
156     cuda_ctx = gst_cuda_context_get_handle (context);
157     if (nvdec_available) {
158       gint j;
159
160       for (j = 0; j < cudaVideoCodec_NumCodecs; j++) {
161         GstCaps *sink_template = NULL;
162         GstCaps *src_template = NULL;
163         cudaVideoCodec codec = (cudaVideoCodec) j;
164         gboolean register_cuviddec = TRUE;
165
166         if (gst_nv_decoder_check_device_caps (cuda_ctx,
167                 codec, &sink_template, &src_template)) {
168           const gchar *codec_name = gst_cuda_video_codec_to_string (codec);
169
170           GST_INFO ("CUDA video codec %s, sink template %" GST_PTR_FORMAT
171               "src template %" GST_PTR_FORMAT, codec_name,
172               sink_template, src_template);
173
174           switch (codec) {
175             case cudaVideoCodec_H264:
176               gst_nv_h264_dec_register (plugin,
177                   i, GST_RANK_SECONDARY, sink_template, src_template, FALSE);
178               if (use_h264_sl_dec) {
179                 GST_INFO
180                     ("Skipping registration of CUVID parser based nvh264dec element");
181                 register_cuviddec = FALSE;
182
183                 gst_nv_h264_dec_register (plugin,
184                     i, GST_RANK_PRIMARY, sink_template, src_template, TRUE);
185               }
186               break;
187             case cudaVideoCodec_HEVC:
188               gst_nv_h265_dec_register (plugin,
189                   i, GST_RANK_SECONDARY, sink_template, src_template, FALSE);
190               if (use_h265_sl_dec) {
191                 GST_INFO
192                     ("Skipping registration of CUVID parser based nvh265dec element");
193                 register_cuviddec = FALSE;
194
195                 gst_nv_h265_dec_register (plugin,
196                     i, GST_RANK_PRIMARY, sink_template, src_template, TRUE);
197               }
198               break;
199             case cudaVideoCodec_VP8:
200               gst_nv_vp8_dec_register (plugin,
201                   i, GST_RANK_SECONDARY, sink_template, src_template, FALSE);
202               if (use_vp8_sl_dec) {
203                 GST_INFO
204                     ("Skipping registration of CUVID parser based nvhvp8dec element");
205                 register_cuviddec = FALSE;
206
207                 gst_nv_vp8_dec_register (plugin,
208                     i, GST_RANK_PRIMARY, sink_template, src_template, TRUE);
209               }
210               break;
211             case cudaVideoCodec_VP9:
212               gst_nv_vp9_dec_register (plugin,
213                   i, GST_RANK_SECONDARY, sink_template, src_template, FALSE);
214               if (use_vp9_sl_dec) {
215                 GST_INFO ("Skip register cuvid parser based nvhvp9dec");
216                 register_cuviddec = FALSE;
217
218                 gst_nv_vp9_dec_register (plugin,
219                     i, GST_RANK_PRIMARY, sink_template, src_template, TRUE);
220               }
221               break;
222             default:
223               break;
224           }
225
226           if (register_cuviddec) {
227             gst_nvdec_plugin_init (plugin,
228                 i, codec, codec_name, sink_template, src_template);
229           }
230
231           gst_caps_unref (sink_template);
232           gst_caps_unref (src_template);
233         }
234       }
235     }
236
237     if (nvenc_available) {
238 #ifdef HAVE_NVCODEC_GST_D3D11
239       if (g_win32_check_windows_version (6, 0, 0, G_WIN32_OS_ANY)) {
240         gint64 adapter_luid;
241         GstD3D11Device *d3d11_device;
242
243         g_object_get (context, "dxgi-adapter-luid", &adapter_luid, NULL);
244         d3d11_device = gst_d3d11_device_new_for_adapter_luid (adapter_luid,
245             D3D11_CREATE_DEVICE_BGRA_SUPPORT);
246         if (!d3d11_device) {
247           GST_WARNING ("Failed to d3d11 create device");
248         } else {
249           gst_nv_h264_encoder_register_d3d11 (plugin,
250               d3d11_device, GST_RANK_NONE);
251           gst_nv_h265_encoder_register_d3d11 (plugin,
252               d3d11_device, GST_RANK_NONE);
253           gst_object_unref (d3d11_device);
254         }
255       }
256 #endif
257       gst_nv_h264_encoder_register_cuda (plugin, context, GST_RANK_NONE);
258       gst_nv_h265_encoder_register_cuda (plugin, context, GST_RANK_NONE);
259       gst_nvenc_plugin_init (plugin, i, cuda_ctx);
260     }
261
262     gst_object_unref (context);
263   }
264
265   gst_cuda_memory_copy_register (plugin, GST_RANK_NONE);
266
267   gst_cuda_filter_plugin_init (plugin);
268   gst_cuda_memory_init_once ();
269
270 #ifdef HAVE_NVCODEC_NVMM
271   if (gst_cuda_nvmm_init_once ()) {
272     GST_INFO ("Enable NVMM support");
273   }
274 #endif
275
276   return TRUE;
277 }
278
279 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, nvcodec,
280     "GStreamer NVCODEC plugin", plugin_init, VERSION, "LGPL",
281     GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)