ac48d01701aebeeafb395e5198061eb9a3ed5259
[platform/upstream/gstreamer-vaapi.git] / gst / vaapi / gstvaapipluginutil.c
1 /*
2  *  gstvaapipluginutil.h - VA-API plugin helpers
3  *
4  *  Copyright (C) 2011-2012 Intel Corporation
5  *  Copyright (C) 2011 Collabora
6  *    Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public License
10  *  as published by the Free Software Foundation; either version 2.1
11  *  of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free
20  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  *  Boston, MA 02110-1301 USA
22  */
23
24 #include "gst/vaapi/sysdeps.h"
25 #include <gst/video/videocontext.h>
26 #if USE_DRM
27 # include <gst/vaapi/gstvaapidisplay_drm.h>
28 #endif
29 #if USE_X11
30 # include <gst/vaapi/gstvaapidisplay_x11.h>
31 #endif
32 #if USE_GLX
33 # include <gst/vaapi/gstvaapidisplay_glx.h>
34 #endif
35 #if USE_WAYLAND
36 # include <gst/vaapi/gstvaapidisplay_wayland.h>
37 #endif
38 #include "gstvaapipluginutil.h"
39
40 /* Preferred first */
41 static const char *display_types[] = {
42     "gst-vaapi-display",
43     "vaapi-display",
44 #if USE_WAYLAND
45     "wl-display",
46     "wl-display-name",
47 #endif
48 #if USE_X11
49     "x11-display",
50     "x11-display-name",
51 #endif
52 #if USE_DRM
53     "drm-device",
54     "drm-device-path",
55 #endif
56     NULL
57 };
58
59 typedef struct {
60     const gchar        *type_str;
61     GstVaapiDisplayType type;
62     GstVaapiDisplay * (*create_display)(const gchar *);
63 } DisplayMap;
64
65 static const DisplayMap g_display_map[] = {
66 #if USE_WAYLAND
67     { "wayland",
68       GST_VAAPI_DISPLAY_TYPE_WAYLAND,
69       gst_vaapi_display_wayland_new },
70 #endif
71 #if USE_GLX
72     { "glx",
73       GST_VAAPI_DISPLAY_TYPE_GLX,
74       gst_vaapi_display_glx_new },
75 #endif
76 #if USE_X11
77     { "x11",
78       GST_VAAPI_DISPLAY_TYPE_X11,
79       gst_vaapi_display_x11_new },
80 #endif
81 #if USE_DRM
82     { "drm",
83       GST_VAAPI_DISPLAY_TYPE_DRM,
84       gst_vaapi_display_drm_new },
85 #endif
86     { NULL, }
87 };
88
89 static GstVaapiDisplay *
90 gst_vaapi_create_display(GstVaapiDisplayType *display_type)
91 {
92     GstVaapiDisplay *display = NULL;
93     const DisplayMap *m;
94
95     for (m = g_display_map; m->type_str != NULL; m++) {
96         if (*display_type != GST_VAAPI_DISPLAY_TYPE_ANY &&
97             *display_type != m->type)
98             continue;
99
100         display = m->create_display(NULL);
101         if (display) {
102             *display_type = m->type;
103             break;
104         }
105
106         if (*display_type != GST_VAAPI_DISPLAY_TYPE_ANY)
107             break;
108     }
109     return display;
110 }
111
112 gboolean
113 gst_vaapi_ensure_display(
114     gpointer             element,
115     GstVaapiDisplayType  display_type,
116     GstVaapiDisplay    **display_ptr
117 )
118 {
119     GstVaapiDisplay *display;
120     GstVideoContext *context;
121
122     g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE);
123     g_return_val_if_fail(display_ptr != NULL, FALSE);
124
125     /* Already exist ? */
126     display = *display_ptr;
127     if (display)
128         return TRUE;
129
130     context = GST_VIDEO_CONTEXT(element);
131     g_return_val_if_fail(context != NULL, FALSE);
132
133     gst_video_context_prepare(context, display_types);
134
135     /* Neighbour found and it updated the display */
136     if (*display_ptr)
137         return TRUE;
138
139     /* If no neighboor, or application not interested, use system default */
140     display = gst_vaapi_create_display(&display_type);
141
142     if (display_ptr)
143         *display_ptr = display;
144     return display != NULL;
145 }
146
147 void
148 gst_vaapi_set_display(
149     const gchar      *type,
150     const GValue     *value,
151     GstVaapiDisplay **display
152 )
153 {
154     GstVaapiDisplay *dpy = NULL;
155
156     if (!strcmp(type, "vaapi-display")) {
157         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
158         dpy = gst_vaapi_display_new_with_display(g_value_get_pointer(value));
159     }
160     else if (!strcmp(type, "gst-vaapi-display")) {
161         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
162         dpy = gst_vaapi_display_ref(g_value_get_pointer(value));
163     }
164 #if USE_DRM
165     else if (!strcmp(type, "drm-device")) {
166         gint device;
167         g_return_if_fail(G_VALUE_HOLDS_INT(value));
168         device = g_value_get_int(value);
169         dpy = gst_vaapi_display_drm_new_with_device(device);
170     }
171     else if (!strcmp(type, "drm-device-path")) {
172         const gchar *device_path;
173         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
174         device_path = g_value_get_string(value);
175         dpy = gst_vaapi_display_drm_new(device_path);
176     }
177 #endif
178 #if USE_X11
179     else if (!strcmp(type, "x11-display-name")) {
180         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
181 #if USE_GLX
182         dpy = gst_vaapi_display_glx_new(g_value_get_string(value));
183 #endif
184         if (!dpy)
185             dpy = gst_vaapi_display_x11_new(g_value_get_string(value));
186     }
187     else if (!strcmp(type, "x11-display")) {
188         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
189 #if USE_GLX
190         dpy = gst_vaapi_display_glx_new_with_display(g_value_get_pointer(value));
191 #endif
192         if (!dpy)
193             dpy = gst_vaapi_display_x11_new_with_display(g_value_get_pointer(value));
194     }
195 #endif
196 #if USE_WAYLAND
197     else if (!strcmp(type, "wl-display")) {
198         struct wl_display *wl_display;
199         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
200         wl_display = g_value_get_pointer(value);
201         dpy = gst_vaapi_display_wayland_new_with_display(wl_display);
202     }
203     else if (!strcmp(type, "wl-display-name")) {
204         const gchar *display_name;
205         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
206         display_name = g_value_get_string(value);
207         dpy = gst_vaapi_display_wayland_new(display_name);
208     }
209 #endif
210
211     if (dpy) {
212         gst_vaapi_display_replace(display, dpy);
213         gst_vaapi_display_unref(dpy);
214     }
215 }
216
217 gboolean
218 gst_vaapi_reply_to_query(GstQuery *query, GstVaapiDisplay *display)
219 {
220     GstVaapiDisplayType display_type;
221     const gchar **types;
222     const gchar *type;
223     gint i;
224     gboolean res = FALSE;
225
226     if (GST_QUERY_TYPE(query) != GST_QUERY_CUSTOM)
227         return FALSE;
228
229     if (!display)
230         return FALSE;
231
232     types = gst_video_context_query_get_supported_types(query);
233
234     if (!types)
235         return FALSE;
236
237     display_type = gst_vaapi_display_get_display_type(display);
238     for (i = 0; types[i] && !res; i++) {
239         type = types[i];
240
241         res = TRUE;
242         if (!strcmp(type, "gst-vaapi-display")) {
243             gst_video_context_query_set_pointer(query, type, display);
244         }
245         else if (!strcmp(type, "vaapi-display")) {
246             VADisplay vadpy = gst_vaapi_display_get_display(display);
247             gst_video_context_query_set_pointer(query, type, vadpy);
248         }
249         else {
250             switch (display_type) {
251 #if USE_DRM
252             case GST_VAAPI_DISPLAY_TYPE_DRM: {
253                 GstVaapiDisplayDRM * const drm_dpy =
254                     GST_VAAPI_DISPLAY_DRM(display);
255                 if (!strcmp(type, "drm-device-path"))
256                     gst_video_context_query_set_string(query, type,
257                         gst_vaapi_display_drm_get_device_path(drm_dpy));
258 #if 0
259                 /* XXX: gst_video_context_query_set_int() does not exist yet */
260                 else if (!strcmp(type, "drm-device"))
261                     gst_video_context_query_set_int(query, type,
262                         gst_vaapi_display_drm_get_device(drm_dpy));
263 #endif
264                 else
265                     res = FALSE;
266                 break;
267             }
268 #endif
269 #if USE_X11
270 #if USE_GLX
271             case GST_VAAPI_DISPLAY_TYPE_GLX:
272 #endif
273             case GST_VAAPI_DISPLAY_TYPE_X11: {
274                 GstVaapiDisplayX11 * const xvadpy =
275                     GST_VAAPI_DISPLAY_X11(display);
276                 Display * const x11dpy =
277                     gst_vaapi_display_x11_get_display(xvadpy);
278                 if (!strcmp(type, "x11-display"))
279                     gst_video_context_query_set_pointer(query, type, x11dpy);
280                 else if (!strcmp(type, "x11-display-name"))
281                     gst_video_context_query_set_string(query, type,
282                         DisplayString(x11dpy));
283                 else
284                     res = FALSE;
285                 break;
286             }
287 #endif
288 #if USE_WAYLAND
289             case GST_VAAPI_DISPLAY_TYPE_WAYLAND: {
290                 GstVaapiDisplayWayland * const wlvadpy =
291                     GST_VAAPI_DISPLAY_WAYLAND(display);
292                 struct wl_display * const wldpy =
293                     gst_vaapi_display_wayland_get_display(wlvadpy);
294                 if (!strcmp(type, "wl-display"))
295                     gst_video_context_query_set_pointer(query, type, wldpy);
296                 else
297                     res = FALSE;
298                 break;
299             }
300 #endif
301             default:
302                 res = FALSE;
303                 break;
304             }
305         }
306     }
307     return res;
308 }
309
310 gboolean
311 gst_vaapi_append_surface_caps(GstCaps *out_caps, GstCaps *in_caps)
312 {
313     GstStructure *structure;
314     const GValue *v_width, *v_height, *v_framerate, *v_par;
315     guint i, n_structures;
316
317     structure   = gst_caps_get_structure(in_caps, 0);
318     v_width     = gst_structure_get_value(structure, "width");
319     v_height    = gst_structure_get_value(structure, "height");
320     v_framerate = gst_structure_get_value(structure, "framerate");
321     v_par       = gst_structure_get_value(structure, "pixel-aspect-ratio");
322     if (!v_width || !v_height)
323         return FALSE;
324
325     n_structures = gst_caps_get_size(out_caps);
326     for (i = 0; i < n_structures; i++) {
327         structure = gst_caps_get_structure(out_caps, i);
328         gst_structure_set_value(structure, "width", v_width);
329         gst_structure_set_value(structure, "height", v_height);
330         if (v_framerate)
331             gst_structure_set_value(structure, "framerate", v_framerate);
332         if (v_par)
333             gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
334     }
335     return TRUE;
336 }
337
338 gboolean
339 gst_vaapi_apply_composition(GstVaapiSurface *surface, GstBuffer *buffer)
340 {
341 #if GST_CHECK_VERSION(1,0,0)
342     GstVideoOverlayCompositionMeta * const cmeta =
343         gst_buffer_get_video_overlay_composition_meta(buffer);
344     GstVideoOverlayComposition *composition;
345
346     if (!cmeta)
347         return TRUE;
348     composition = cmeta->overlay;
349 #else
350     GstVideoOverlayComposition * const composition =
351         gst_video_buffer_get_overlay_composition(buffer);
352 #endif
353     if (!composition)
354         return TRUE;
355     return gst_vaapi_surface_set_subpictures_from_composition(surface,
356             composition, TRUE);
357 }