Tizen 2.1 base
[framework/multimedia/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 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 #include <string.h>
28 #include <gst/video/videocontext.h>
29 #if USE_DRM
30 # include <gst/vaapi/gstvaapidisplay_drm.h>
31 #endif
32 #if USE_X11
33 # include <gst/vaapi/gstvaapidisplay_x11.h>
34 #endif
35 #if USE_GLX
36 # include <gst/vaapi/gstvaapidisplay_glx.h>
37 #endif
38 #if USE_WAYLAND
39 # include <gst/vaapi/gstvaapidisplay_wayland.h>
40 #endif
41 #include "gstvaapipluginutil.h"
42
43 /* Preferred first */
44 static const char *display_types[] = {
45     "gst-vaapi-display",
46     "vaapi-display",
47 #if USE_WAYLAND
48     "wl-display",
49     "wl-display-name",
50 #endif
51 #if USE_X11
52     "x11-display",
53     "x11-display-name",
54 #endif
55 #if USE_DRM
56     "drm-device",
57     "drm-device-path",
58 #endif
59     NULL
60 };
61
62 typedef struct {
63     const gchar        *type_str;
64     GstVaapiDisplayType type;
65     GstVaapiDisplay * (*create_display)(const gchar *);
66 } DisplayMap;
67
68 static const DisplayMap g_display_map[] = {
69 #if USE_WAYLAND
70     { "wayland",
71       GST_VAAPI_DISPLAY_TYPE_WAYLAND,
72       gst_vaapi_display_wayland_new },
73 #endif
74 #if USE_X11
75     { "x11",
76       GST_VAAPI_DISPLAY_TYPE_X11,
77       gst_vaapi_display_x11_new },
78 #endif
79 #if USE_GLX
80     { "glx",
81       GST_VAAPI_DISPLAY_TYPE_GLX,
82       gst_vaapi_display_glx_new },
83 #endif
84 #if USE_DRM
85     { "drm",
86       GST_VAAPI_DISPLAY_TYPE_DRM,
87       gst_vaapi_display_drm_new },
88 #endif
89     { NULL, }
90 };
91
92 gboolean
93 gst_vaapi_ensure_display(
94     gpointer             element,
95     GstVaapiDisplayType  display_type,
96     GstVaapiDisplay    **display_ptr
97 )
98 {
99     GstVaapiDisplay *display;
100     GstVideoContext *context;
101     const DisplayMap *m;
102
103     g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE);
104     g_return_val_if_fail(display_ptr != NULL, FALSE);
105
106     /* Already exist ? */
107     display = *display_ptr;
108     if (display)
109         return TRUE;
110
111     context = GST_VIDEO_CONTEXT(element);
112     g_return_val_if_fail(context != NULL, FALSE);
113
114     gst_video_context_prepare(context, display_types);
115
116     /* Neighbour found and it updated the display */
117     if (*display_ptr)
118         return TRUE;
119
120     /* If no neighboor, or application not interested, use system default */
121     for (m = g_display_map; m->type_str != NULL; m++) {
122         if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY &&
123             display_type != m->type)
124             continue;
125
126         display = m->create_display(NULL);
127         if (display) {
128             /* FIXME: allocator should return NULL if an error occurred */
129             if (gst_vaapi_display_get_display(display)) {
130                 display_type = m->type;
131                 break;
132             }
133             g_object_unref(display);
134             display = NULL;
135         }
136
137         if (display_type != GST_VAAPI_DISPLAY_TYPE_ANY)
138             break;
139     }
140
141     if (display_ptr)
142         *display_ptr = display;
143     return display != NULL;
144 }
145
146 void
147 gst_vaapi_set_display(
148     const gchar      *type,
149     const GValue     *value,
150     GstVaapiDisplay **display
151 )
152 {
153     GstVaapiDisplay *dpy = NULL;
154
155     if (!strcmp(type, "vaapi-display")) {
156         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
157         dpy = gst_vaapi_display_new_with_display(g_value_get_pointer(value));
158     }
159     else if (!strcmp(type, "gst-vaapi-display")) {
160         g_return_if_fail(G_VALUE_HOLDS_OBJECT(value));
161         dpy = g_value_dup_object(value);
162     }
163 #if USE_DRM
164     else if (!strcmp(type, "drm-device")) {
165         gint device;
166         g_return_if_fail(G_VALUE_HOLDS_INT(value));
167         device = g_value_get_int(value);
168         dpy = gst_vaapi_display_drm_new_with_device(device);
169     }
170     else if (!strcmp(type, "drm-device-path")) {
171         const gchar *device_path;
172         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
173         device_path = g_value_get_string(value);
174         dpy = gst_vaapi_display_drm_new(device_path);
175     }
176 #endif
177 #if USE_X11
178     else if (!strcmp(type, "x11-display-name")) {
179         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
180 #if USE_GLX
181         dpy = gst_vaapi_display_glx_new(g_value_get_string(value));
182 #endif
183         if (!dpy)
184             dpy = gst_vaapi_display_x11_new(g_value_get_string(value));
185     }
186     else if (!strcmp(type, "x11-display")) {
187         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
188 #if USE_GLX
189         dpy = gst_vaapi_display_glx_new_with_display(g_value_get_pointer(value));
190 #endif
191         if (!dpy)
192             dpy = gst_vaapi_display_x11_new_with_display(g_value_get_pointer(value));
193     }
194 #endif
195 #if USE_WAYLAND
196     else if (!strcmp(type, "wl-display")) {
197         struct wl_display *wl_display;
198         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
199         wl_display = g_value_get_pointer(value);
200         dpy = gst_vaapi_display_wayland_new_with_display(wl_display);
201     }
202     else if (!strcmp(type, "wl-display-name")) {
203         const gchar *display_name;
204         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
205         display_name = g_value_get_string(value);
206         dpy = gst_vaapi_display_wayland_new(display_name);
207     }
208 #endif
209
210     if (dpy) {
211         if (*display)
212             g_object_unref(*display);
213         *display = 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 (!display)
227         return FALSE;
228
229     types = gst_video_context_query_get_supported_types(query);
230
231     if (!types)
232         return FALSE;
233
234     display_type = gst_vaapi_display_get_display_type(display);
235     for (i = 0; types[i] && !res; i++) {
236         type = types[i];
237
238         res = TRUE;
239         if (!strcmp(type, "gst-vaapi-display")) {
240             gst_video_context_query_set_object(query, type, G_OBJECT(display));
241         }
242         else if (!strcmp(type, "vaapi-display")) {
243             VADisplay vadpy = gst_vaapi_display_get_display(display);
244             gst_video_context_query_set_pointer(query, type, vadpy);
245         }
246         else {
247             switch (display_type) {
248 #if USE_DRM
249             case GST_VAAPI_DISPLAY_TYPE_DRM: {
250                 GstVaapiDisplayDRM * const drm_dpy =
251                     GST_VAAPI_DISPLAY_DRM(display);
252                 if (!strcmp(type, "drm-device-path"))
253                     gst_video_context_query_set_string(query, type,
254                         gst_vaapi_display_drm_get_device_path(drm_dpy));
255 #if 0
256                 /* XXX: gst_video_context_query_set_int() does not exist yet */
257                 else if (!strcmp(type, "drm-device"))
258                     gst_video_context_query_set_int(query, type,
259                         gst_vaapi_display_drm_get_device(drm_dpy));
260 #endif
261                 else
262                     res = FALSE;
263                 break;
264             }
265 #endif
266 #if USE_X11
267 #if USE_GLX
268             case GST_VAAPI_DISPLAY_TYPE_GLX:
269 #endif
270             case GST_VAAPI_DISPLAY_TYPE_X11: {
271                 GstVaapiDisplayX11 * const xvadpy =
272                     GST_VAAPI_DISPLAY_X11(display);
273                 Display * const x11dpy =
274                     gst_vaapi_display_x11_get_display(xvadpy);
275                 if (!strcmp(type, "x11-display"))
276                     gst_video_context_query_set_pointer(query, type, x11dpy);
277                 else if (!strcmp(type, "x11-display-name"))
278                     gst_video_context_query_set_string(query, type,
279                         DisplayString(x11dpy));
280                 else
281                     res = FALSE;
282                 break;
283             }
284 #endif
285 #if USE_WAYLAND
286             case GST_VAAPI_DISPLAY_TYPE_WAYLAND: {
287                 GstVaapiDisplayWayland * const wlvadpy =
288                     GST_VAAPI_DISPLAY_WAYLAND(display);
289                 struct wl_display * const wldpy =
290                     gst_vaapi_display_wayland_get_display(wlvadpy);
291                 if (!strcmp(type, "wl-display"))
292                     gst_video_context_query_set_pointer(query, type, wldpy);
293                 else
294                     res = FALSE;
295                 break;
296             }
297 #endif
298             default:
299                 res = FALSE;
300                 break;
301             }
302         }
303     }
304     return res;
305 }
306
307 gboolean
308 gst_vaapi_append_surface_caps(GstCaps *out_caps, GstCaps *in_caps)
309 {
310     GstStructure *structure;
311     const GValue *v_width, *v_height, *v_framerate, *v_par;
312     guint i, n_structures;
313
314     structure   = gst_caps_get_structure(in_caps, 0);
315     v_width     = gst_structure_get_value(structure, "width");
316     v_height    = gst_structure_get_value(structure, "height");
317     v_framerate = gst_structure_get_value(structure, "framerate");
318     v_par       = gst_structure_get_value(structure, "pixel-aspect-ratio");
319     if (!v_width || !v_height)
320         return FALSE;
321
322     n_structures = gst_caps_get_size(out_caps);
323     for (i = 0; i < n_structures; i++) {
324         structure = gst_caps_get_structure(out_caps, i);
325         gst_structure_set_value(structure, "width", v_width);
326         gst_structure_set_value(structure, "height", v_height);
327         if (v_framerate)
328             gst_structure_set_value(structure, "framerate", v_framerate);
329         if (v_par)
330             gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
331     }
332     return TRUE;
333 }