3532624839093caffa59a159794febb35623f4f2
[platform/upstream/gstreamer.git] / subprojects / gstreamer-vaapi / gst / vaapi / gstvaapi.c
1 /*
2  *  gstvaapi.c - VA-API element registration
3  *
4  *  Copyright (C) 2011-2013 Intel Corporation
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
6  *  Copyright (C) 2011 Collabora Ltd.
7  *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation; either version 2.1
12  *  of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free
21  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301 USA
23  */
24
25 #include "gstcompat.h"
26 #include "gstvaapidecode.h"
27 #include "gstvaapioverlay.h"
28 #include "gstvaapipostproc.h"
29 #include "gstvaapisink.h"
30 #include "gstvaapidecodebin.h"
31
32 #if USE_ENCODERS
33 #include "gstvaapiencode_h264.h"
34 #include "gstvaapiencode_mpeg2.h"
35 #include "gstvaapiencode_jpeg.h"
36 #include "gstvaapiencode_vp8.h"
37 #include "gstvaapiencode_h265.h"
38
39 #if USE_VP9_ENCODER
40 #include "gstvaapiencode_vp9.h"
41 #endif
42 #endif
43
44 gboolean _gst_vaapi_has_video_processing = FALSE;
45
46 #define PLUGIN_NAME     "vaapi"
47 #define PLUGIN_DESC     "VA-API based elements"
48 #define PLUGIN_LICENSE  "LGPL"
49
50 static void
51 plugin_add_dependencies (GstPlugin * plugin)
52 {
53   const gchar *envvars[] = { "GST_VAAPI_ALL_DRIVERS", "LIBVA_DRIVER_NAME",
54     "DISPLAY", "WAYLAND_DISPLAY", NULL
55   };
56   const gchar *kernel_paths[] = { "/dev/dri", NULL };
57   const gchar *kernel_names[] = { "card", "render", NULL };
58
59   /* features get updated upon changes in /dev/dri/card* */
60   gst_plugin_add_dependency (plugin, NULL, kernel_paths, kernel_names,
61       GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX);
62
63   /* features get updated upon changes in VA environment variables */
64   gst_plugin_add_dependency (plugin, envvars, NULL, NULL,
65       GST_PLUGIN_DEPENDENCY_FLAG_NONE);
66
67   /* features get updated upon changes in default VA drivers
68    * directory */
69   gst_plugin_add_dependency_simple (plugin, "LIBVA_DRIVERS_PATH",
70       VA_DRIVERS_PATH, "_drv_video.so",
71       GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX |
72       GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY);
73 }
74
75 static GArray *
76 profiles_get_codecs (GArray * profiles)
77 {
78   guint i;
79   GArray *codecs;
80   GstVaapiProfile profile;
81   GstVaapiCodec codec;
82
83   codecs = g_array_new (FALSE, FALSE, sizeof (GstVaapiCodec));
84   if (!codecs)
85     return NULL;
86
87   for (i = 0; i < profiles->len; i++) {
88     profile = g_array_index (profiles, GstVaapiProfile, i);
89     codec = gst_vaapi_profile_get_codec (profile);
90     if (gst_vaapi_codecs_has_codec (codecs, codec))
91       continue;
92     g_array_append_val (codecs, codec);
93   }
94
95   return codecs;
96 }
97
98 static GArray *
99 display_get_decoder_codecs (GstVaapiDisplay * display)
100 {
101   GArray *profiles, *codecs;
102
103   profiles = gst_vaapi_display_get_decode_profiles (display);
104   if (!profiles)
105     return NULL;
106
107   codecs = profiles_get_codecs (profiles);
108   g_array_unref (profiles);
109   return codecs;
110 }
111
112 #if USE_ENCODERS
113 static GArray *
114 display_get_encoder_codecs (GstVaapiDisplay * display)
115 {
116   GArray *profiles, *codecs;
117
118   profiles = gst_vaapi_display_get_encode_profiles (display);
119   if (!profiles)
120     return NULL;
121
122   codecs = profiles_get_codecs (profiles);
123   g_array_unref (profiles);
124   return codecs;
125 }
126
127 typedef struct _GstVaapiEncoderMap GstVaapiEncoderMap;
128 struct _GstVaapiEncoderMap
129 {
130   GstVaapiCodec codec;
131   guint rank;
132   const gchar *name;
133     GType (*register_type) (GstVaapiDisplay * display);
134 };
135
136 #define DEF_ENC(CODEC,codec)          \
137   {GST_VAAPI_CODEC_##CODEC,           \
138    GST_RANK_PRIMARY,                  \
139    "vaapi" G_STRINGIFY (codec) "enc", \
140    gst_vaapiencode_##codec##_register_type}
141
142 static const GstVaapiEncoderMap vaapi_encode_map[] = {
143   DEF_ENC (H264, h264),
144   DEF_ENC (MPEG2, mpeg2),
145   DEF_ENC (JPEG, jpeg),
146   DEF_ENC (VP8, vp8),
147 #if USE_VP9_ENCODER
148   DEF_ENC (VP9, vp9),
149 #endif
150   DEF_ENC (H265, h265),
151 };
152
153 #undef DEF_ENC
154
155 static void
156 gst_vaapiencode_register (GstPlugin * plugin, GstVaapiDisplay * display)
157 {
158   guint i, j;
159   GArray *codecs;
160   GstVaapiCodec codec;
161
162   codecs = display_get_encoder_codecs (display);
163   if (!codecs)
164     return;
165
166   for (i = 0; i < codecs->len; i++) {
167     codec = g_array_index (codecs, GstVaapiCodec, i);
168     for (j = 0; j < G_N_ELEMENTS (vaapi_encode_map); j++) {
169       if (vaapi_encode_map[j].codec == codec) {
170         gst_element_register (plugin, vaapi_encode_map[j].name,
171             vaapi_encode_map[j].rank,
172             vaapi_encode_map[j].register_type (display));
173         break;
174       }
175     }
176   }
177
178   g_array_unref (codecs);
179 }
180 #endif
181
182 static gboolean
183 plugin_init (GstPlugin * plugin)
184 {
185   GstVaapiDisplay *display;
186   GArray *decoders;
187   guint rank;
188
189   plugin_add_dependencies (plugin);
190
191   display = gst_vaapi_create_test_display ();
192   if (!display)
193     goto error_no_display;
194   if (!gst_vaapi_driver_is_whitelisted (display))
195     goto unsupported_driver;
196
197   _gst_vaapi_has_video_processing =
198       gst_vaapi_display_has_video_processing (display);
199
200   decoders = display_get_decoder_codecs (display);
201   if (decoders) {
202     gst_vaapidecode_register (plugin, decoders);
203     g_array_unref (decoders);
204   }
205
206   if (_gst_vaapi_has_video_processing)
207     gst_vaapioverlay_register (plugin, display);
208
209   gst_element_register (plugin, "vaapipostproc",
210       GST_RANK_NONE, GST_TYPE_VAAPIPOSTPROC);
211
212   gst_element_register (plugin, "vaapidecodebin",
213       GST_RANK_PRIMARY + 2, GST_TYPE_VAAPI_DECODE_BIN);
214
215   rank = GST_RANK_SECONDARY;
216   if (g_getenv ("WAYLAND_DISPLAY"))
217     rank = GST_RANK_MARGINAL;
218   gst_element_register (plugin, "vaapisink", rank, GST_TYPE_VAAPISINK);
219
220 #if USE_ENCODERS
221   gst_vaapiencode_register (plugin, display);
222 #endif
223
224   gst_object_unref (display);
225
226   return TRUE;
227
228   /* ERRORS: */
229 error_no_display:
230   {
231     GST_WARNING ("Cannot create a VA display");
232     /* Avoid blacklisting: failure to create a display could be a
233      * transient condition */
234     return TRUE;
235   }
236 unsupported_driver:
237   {
238     gst_object_unref (display);
239     return TRUE;                /* return TRUE to avoid get blacklisted */
240   }
241 }
242
243 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
244     vaapi, PLUGIN_DESC, plugin_init,
245     PACKAGE_VERSION, PLUGIN_LICENSE, PACKAGE, PACKAGE_BUGREPORT)