plugins: cope with new GstVaapiMiniObject objects.
[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_X11
72     { "x11",
73       GST_VAAPI_DISPLAY_TYPE_X11,
74       gst_vaapi_display_x11_new },
75 #endif
76 #if USE_GLX
77     { "glx",
78       GST_VAAPI_DISPLAY_TYPE_GLX,
79       gst_vaapi_display_glx_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 gboolean
90 gst_vaapi_ensure_display(
91     gpointer             element,
92     GstVaapiDisplayType  display_type,
93     GstVaapiDisplay    **display_ptr
94 )
95 {
96     GstVaapiDisplay *display;
97     GstVideoContext *context;
98     const DisplayMap *m;
99
100     g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE);
101     g_return_val_if_fail(display_ptr != NULL, FALSE);
102
103     /* Already exist ? */
104     display = *display_ptr;
105     if (display)
106         return TRUE;
107
108     context = GST_VIDEO_CONTEXT(element);
109     g_return_val_if_fail(context != NULL, FALSE);
110
111     gst_video_context_prepare(context, display_types);
112
113     /* Neighbour found and it updated the display */
114     if (*display_ptr)
115         return TRUE;
116
117     /* If no neighboor, or application not interested, use system default */
118     for (m = g_display_map; m->type_str != NULL; m++) {
119         if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY &&
120             display_type != m->type)
121             continue;
122
123         display = m->create_display(NULL);
124         if (display) {
125             /* FIXME: allocator should return NULL if an error occurred */
126             if (gst_vaapi_display_get_display(display)) {
127                 display_type = m->type;
128                 break;
129             }
130             gst_vaapi_display_unref(display);
131             display = NULL;
132         }
133
134         if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY)
135             break;
136     }
137
138     if (display_ptr)
139         *display_ptr = display;
140     return display != NULL;
141 }
142
143 void
144 gst_vaapi_set_display(
145     const gchar      *type,
146     const GValue     *value,
147     GstVaapiDisplay **display
148 )
149 {
150     GstVaapiDisplay *dpy = NULL;
151
152     if (!strcmp(type, "vaapi-display")) {
153         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
154         dpy = gst_vaapi_display_new_with_display(g_value_get_pointer(value));
155     }
156     else if (!strcmp(type, "gst-vaapi-display")) {
157         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
158         dpy = gst_vaapi_display_ref(g_value_get_pointer(value));
159     }
160 #if USE_DRM
161     else if (!strcmp(type, "drm-device")) {
162         gint device;
163         g_return_if_fail(G_VALUE_HOLDS_INT(value));
164         device = g_value_get_int(value);
165         dpy = gst_vaapi_display_drm_new_with_device(device);
166     }
167     else if (!strcmp(type, "drm-device-path")) {
168         const gchar *device_path;
169         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
170         device_path = g_value_get_string(value);
171         dpy = gst_vaapi_display_drm_new(device_path);
172     }
173 #endif
174 #if USE_X11
175     else if (!strcmp(type, "x11-display-name")) {
176         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
177 #if USE_GLX
178         dpy = gst_vaapi_display_glx_new(g_value_get_string(value));
179 #endif
180         if (!dpy)
181             dpy = gst_vaapi_display_x11_new(g_value_get_string(value));
182     }
183     else if (!strcmp(type, "x11-display")) {
184         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
185 #if USE_GLX
186         dpy = gst_vaapi_display_glx_new_with_display(g_value_get_pointer(value));
187 #endif
188         if (!dpy)
189             dpy = gst_vaapi_display_x11_new_with_display(g_value_get_pointer(value));
190     }
191 #endif
192 #if USE_WAYLAND
193     else if (!strcmp(type, "wl-display")) {
194         struct wl_display *wl_display;
195         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
196         wl_display = g_value_get_pointer(value);
197         dpy = gst_vaapi_display_wayland_new_with_display(wl_display);
198     }
199     else if (!strcmp(type, "wl-display-name")) {
200         const gchar *display_name;
201         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
202         display_name = g_value_get_string(value);
203         dpy = gst_vaapi_display_wayland_new(display_name);
204     }
205 #endif
206
207     if (dpy) {
208         gst_vaapi_display_replace(display, dpy);
209         gst_vaapi_display_unref(dpy);
210     }
211 }
212
213 gboolean
214 gst_vaapi_reply_to_query(GstQuery *query, GstVaapiDisplay *display)
215 {
216     GstVaapiDisplayType display_type;
217     const gchar **types;
218     const gchar *type;
219     gint i;
220     gboolean res = FALSE;
221
222     if (GST_QUERY_TYPE(query) != GST_QUERY_CUSTOM)
223         return FALSE;
224
225     if (!display)
226         return FALSE;
227
228     types = gst_video_context_query_get_supported_types(query);
229
230     if (!types)
231         return FALSE;
232
233     display_type = gst_vaapi_display_get_display_type(display);
234     for (i = 0; types[i] && !res; i++) {
235         type = types[i];
236
237         res = TRUE;
238         if (!strcmp(type, "gst-vaapi-display")) {
239             gst_video_context_query_set_pointer(query, type, display);
240         }
241         else if (!strcmp(type, "vaapi-display")) {
242             VADisplay vadpy = gst_vaapi_display_get_display(display);
243             gst_video_context_query_set_pointer(query, type, vadpy);
244         }
245         else {
246             switch (display_type) {
247 #if USE_DRM
248             case GST_VAAPI_DISPLAY_TYPE_DRM: {
249                 GstVaapiDisplayDRM * const drm_dpy =
250                     GST_VAAPI_DISPLAY_DRM(display);
251                 if (!strcmp(type, "drm-device-path"))
252                     gst_video_context_query_set_string(query, type,
253                         gst_vaapi_display_drm_get_device_path(drm_dpy));
254 #if 0
255                 /* XXX: gst_video_context_query_set_int() does not exist yet */
256                 else if (!strcmp(type, "drm-device"))
257                     gst_video_context_query_set_int(query, type,
258                         gst_vaapi_display_drm_get_device(drm_dpy));
259 #endif
260                 else
261                     res = FALSE;
262                 break;
263             }
264 #endif
265 #if USE_X11
266 #if USE_GLX
267             case GST_VAAPI_DISPLAY_TYPE_GLX:
268 #endif
269             case GST_VAAPI_DISPLAY_TYPE_X11: {
270                 GstVaapiDisplayX11 * const xvadpy =
271                     GST_VAAPI_DISPLAY_X11(display);
272                 Display * const x11dpy =
273                     gst_vaapi_display_x11_get_display(xvadpy);
274                 if (!strcmp(type, "x11-display"))
275                     gst_video_context_query_set_pointer(query, type, x11dpy);
276                 else if (!strcmp(type, "x11-display-name"))
277                     gst_video_context_query_set_string(query, type,
278                         DisplayString(x11dpy));
279                 else
280                     res = FALSE;
281                 break;
282             }
283 #endif
284 #if USE_WAYLAND
285             case GST_VAAPI_DISPLAY_TYPE_WAYLAND: {
286                 GstVaapiDisplayWayland * const wlvadpy =
287                     GST_VAAPI_DISPLAY_WAYLAND(display);
288                 struct wl_display * const wldpy =
289                     gst_vaapi_display_wayland_get_display(wlvadpy);
290                 if (!strcmp(type, "wl-display"))
291                     gst_video_context_query_set_pointer(query, type, wldpy);
292                 else
293                     res = FALSE;
294                 break;
295             }
296 #endif
297             default:
298                 res = FALSE;
299                 break;
300             }
301         }
302     }
303     return res;
304 }
305
306 gboolean
307 gst_vaapi_append_surface_caps(GstCaps *out_caps, GstCaps *in_caps)
308 {
309     GstStructure *structure;
310     const GValue *v_width, *v_height, *v_framerate, *v_par;
311     guint i, n_structures;
312
313     structure   = gst_caps_get_structure(in_caps, 0);
314     v_width     = gst_structure_get_value(structure, "width");
315     v_height    = gst_structure_get_value(structure, "height");
316     v_framerate = gst_structure_get_value(structure, "framerate");
317     v_par       = gst_structure_get_value(structure, "pixel-aspect-ratio");
318     if (!v_width || !v_height)
319         return FALSE;
320
321     n_structures = gst_caps_get_size(out_caps);
322     for (i = 0; i < n_structures; i++) {
323         structure = gst_caps_get_structure(out_caps, i);
324         gst_structure_set_value(structure, "width", v_width);
325         gst_structure_set_value(structure, "height", v_height);
326         if (v_framerate)
327             gst_structure_set_value(structure, "framerate", v_framerate);
328         if (v_par)
329             gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
330     }
331     return TRUE;
332 }
333
334 gboolean
335 gst_vaapi_apply_composition(GstVaapiSurface *surface, GstBuffer *buffer)
336 {
337 #if GST_CHECK_VERSION(1,0,0)
338     GstVideoOverlayCompositionMeta * const cmeta =
339         gst_buffer_get_video_overlay_composition_meta(buffer);
340     GstVideoOverlayComposition *composition;
341
342     if (!cmeta)
343         return TRUE;
344     composition = cmeta->overlay;
345 #else
346     GstVideoOverlayComposition * const composition =
347         gst_video_buffer_get_overlay_composition(buffer);
348 #endif
349     if (!composition)
350         return TRUE;
351     return gst_vaapi_surface_set_subpictures_from_composition(surface,
352             composition, TRUE);
353 }