pluginutils: improve automatic display type selection.
[profile/ivi/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_X11
30 # include <gst/vaapi/gstvaapidisplay_x11.h>
31 #endif
32 #if USE_GLX
33 # include <gst/vaapi/gstvaapidisplay_glx.h>
34 #endif
35 #include "gstvaapipluginutil.h"
36
37 /* Preferred first */
38 static const char *display_types[] = {
39     "gst-vaapi-display",
40     "vaapi-display",
41     "x11-display",
42     "x11-display-name",
43     NULL
44 };
45
46 typedef struct {
47     const gchar        *type_str;
48     GstVaapiDisplayType type;
49     GstVaapiDisplay * (*create_display)(const gchar *);
50 } DisplayMap;
51
52 static const DisplayMap g_display_map[] = {
53 #if USE_GLX
54     { "glx",
55       GST_VAAPI_DISPLAY_TYPE_GLX,
56       gst_vaapi_display_glx_new },
57 #endif
58 #if USE_X11
59     { "x11",
60       GST_VAAPI_DISPLAY_TYPE_X11,
61       gst_vaapi_display_x11_new },
62 #endif
63     { NULL, }
64 };
65
66 gboolean
67 gst_vaapi_ensure_display(
68     gpointer             element,
69     GstVaapiDisplay    **display_ptr,
70     GstVaapiDisplayType *display_type_ptr
71 )
72 {
73     GstVaapiDisplayType display_type =
74         display_type_ptr ? *display_type_ptr : GST_VAAPI_DISPLAY_TYPE_AUTO;
75     GstVaapiDisplay *display;
76     GstVideoContext *context;
77     const DisplayMap *m;
78
79     g_return_val_if_fail(GST_IS_VIDEO_CONTEXT(element), FALSE);
80     g_return_val_if_fail(display_ptr != NULL, FALSE);
81
82     /* Already exist ? */
83     display = *display_ptr;
84     if (display)
85         return TRUE;
86
87     context = GST_VIDEO_CONTEXT(element);
88     gst_video_context_prepare(context, display_types);
89
90     /* If no neighboor, or application not interested, use system default */
91     for (m = g_display_map; m->type_str != NULL; m++) {
92         if (display_type != GST_VAAPI_DISPLAY_TYPE_AUTO &&
93             display_type != m->type)
94             continue;
95
96         display = m->create_display(NULL);
97         if (display) {
98             /* FIXME: allocator should return NULL if an error occurred */
99             if (gst_vaapi_display_get_display(display)) {
100                 display_type = m->type;
101                 break;
102             }
103             g_object_unref(display);
104             display = NULL;
105         }
106
107         if (display_type != GST_VAAPI_DISPLAY_TYPE_AUTO)
108             break;
109     }
110
111     if (display_ptr)
112         *display_ptr = display;
113     if (display_type_ptr)
114         *display_type_ptr = display_type;
115     return display != NULL;
116 }
117
118 void
119 gst_vaapi_set_display(
120     const gchar      *type,
121     const GValue     *value,
122     GstVaapiDisplay **display
123 )
124 {
125     GstVaapiDisplay *dpy = NULL;
126
127     if (!strcmp(type, "x11-display-name")) {
128         g_return_if_fail(G_VALUE_HOLDS_STRING(value));
129 #if USE_GLX
130         dpy = gst_vaapi_display_glx_new(g_value_get_string(value));
131 #endif
132         if (!dpy)
133             dpy = gst_vaapi_display_x11_new(g_value_get_string(value));
134     }
135     else if (!strcmp(type, "x11-display")) {
136         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
137 #if USE_GLX
138         dpy = gst_vaapi_display_glx_new_with_display(g_value_get_pointer(value));
139 #endif
140         if (!dpy)
141             dpy = gst_vaapi_display_x11_new_with_display(g_value_get_pointer(value));
142     }
143     else if (!strcmp(type, "vaapi-display")) {
144         g_return_if_fail(G_VALUE_HOLDS_POINTER(value));
145         dpy = gst_vaapi_display_new_with_display(g_value_get_pointer(value));
146     }
147     else if (!strcmp(type, "gst-vaapi-display")) {
148         g_return_if_fail(G_VALUE_HOLDS_OBJECT(value));
149         dpy = g_value_dup_object(value);
150     }
151
152     if (dpy) {
153         if (*display)
154             g_object_unref(*display);
155         *display = dpy;
156     }
157 }
158
159 gboolean
160 gst_vaapi_reply_to_query(GstQuery *query, GstVaapiDisplay *display)
161 {
162     const gchar **types;
163     const gchar *type;
164     gint i;
165     gboolean res = FALSE;
166
167     if (!display)
168         return FALSE;
169
170     types = gst_video_context_query_get_supported_types(query);
171
172     if (!types)
173         return FALSE;
174
175     for (i = 0; types[i]; i++) {
176         type = types[i];
177
178         if (!strcmp(type, "gst-vaapi-display")) {
179             gst_video_context_query_set_object(query, type, G_OBJECT(display));
180         }
181         else if (!strcmp(type, "vaapi-display")) {
182             VADisplay vadpy = gst_vaapi_display_get_display(display);
183             gst_video_context_query_set_pointer(query, type, vadpy);
184         }
185         else if (!strcmp(type, "x11-display") &&
186                  GST_VAAPI_IS_DISPLAY_X11(display)) {
187             GstVaapiDisplayX11 *xvadpy = GST_VAAPI_DISPLAY_X11(display);
188             Display *x11dpy = gst_vaapi_display_x11_get_display(xvadpy);
189             gst_video_context_query_set_pointer(query, type, x11dpy);
190             
191         }
192         else if (!strcmp(type, "x11-display-name") &&
193                  GST_VAAPI_IS_DISPLAY_X11(display)) {
194             GstVaapiDisplayX11 *xvadpy = GST_VAAPI_DISPLAY_X11(display);
195             Display *x11dpy = gst_vaapi_display_x11_get_display(xvadpy);
196             gst_video_context_query_set_string(query, type, DisplayString(x11dpy));
197         }
198         else {
199             continue;
200         }
201
202         res = TRUE;
203         break;
204     }
205     return res;
206 }
207
208 gboolean
209 gst_vaapi_append_surface_caps(GstCaps *out_caps, GstCaps *in_caps)
210 {
211     GstStructure *structure;
212     const GValue *v_width, *v_height, *v_framerate, *v_par;
213     guint i, n_structures;
214
215     structure   = gst_caps_get_structure(in_caps, 0);
216     v_width     = gst_structure_get_value(structure, "width");
217     v_height    = gst_structure_get_value(structure, "height");
218     v_framerate = gst_structure_get_value(structure, "framerate");
219     v_par       = gst_structure_get_value(structure, "pixel-aspect-ratio");
220     if (!v_width || !v_height)
221         return FALSE;
222
223     n_structures = gst_caps_get_size(out_caps);
224     for (i = 0; i < n_structures; i++) {
225         structure = gst_caps_get_structure(out_caps, i);
226         gst_structure_set_value(structure, "width", v_width);
227         gst_structure_set_value(structure, "height", v_height);
228         if (v_framerate)
229             gst_structure_set_value(structure, "framerate", v_framerate);
230         if (v_par)
231             gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
232     }
233     return TRUE;
234 }
235
236 GType
237 gst_vaapi_display_type_get_type(void)
238 {
239     static GType g_type = 0;
240
241     static const GEnumValue display_types[] = {
242         { GST_VAAPI_DISPLAY_TYPE_AUTO,
243           "Auto detection", "auto" },
244         { GST_VAAPI_DISPLAY_TYPE_X11,
245           "VA/X11 display", "x11" },
246 #if USE_GLX
247         { GST_VAAPI_DISPLAY_TYPE_GLX,
248           "VA/GLX display", "glx" },
249 #endif
250         { 0, NULL, NULL },
251     };
252
253     if (!g_type)
254         g_type = g_enum_register_static("GstVaapiDisplayType", display_types);
255     return g_type;
256 }