Add gst_vaapi_window_set_fullscreen() API.
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapiwindow.c
1 /*
2  *  gstvaapiwindow.c - VA window abstraction
3  *
4  *  gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
19  */
20
21 /**
22  * SECTION:gst-vaapi-window
23  * @short_description:
24  */
25
26 #include "config.h"
27 #include "gstvaapiwindow.h"
28
29 #define DEBUG 1
30 #include "gstvaapidebug.h"
31
32 G_DEFINE_TYPE(GstVaapiWindow, gst_vaapi_window, G_TYPE_OBJECT);
33
34 #define GST_VAAPI_WINDOW_GET_PRIVATE(obj)                       \
35     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
36                                  GST_VAAPI_TYPE_WINDOW,         \
37                                  GstVaapiWindowPrivate))
38
39 struct _GstVaapiWindowPrivate {
40     guint       width;
41     guint       height;
42     gboolean    is_constructed  : 1;
43     guint       is_fullscreen   : 1;
44 };
45
46 enum {
47     PROP_0,
48
49     PROP_WIDTH,
50     PROP_HEIGHT
51 };
52
53 static void
54 gst_vaapi_window_destroy(GstVaapiWindow *window)
55 {
56     GST_VAAPI_WINDOW_GET_CLASS(window)->destroy(window);
57 }
58
59 static gboolean
60 gst_vaapi_window_create(GstVaapiWindow *window)
61 {
62     GstVaapiWindowPrivate * const priv = window->priv;
63     guint width, height;
64
65     width  = priv->width;
66     height = priv->height;
67
68     if (!GST_VAAPI_WINDOW_GET_CLASS(window)->create(window, &width, &height))
69         return FALSE;
70
71     if (width != priv->width || height != priv->height) {
72         GST_DEBUG("backend resized window to %ux%u", width, height);
73         priv->width  = width;
74         priv->height = height;
75     }
76     return TRUE;
77 }
78
79 static void
80 gst_vaapi_window_finalize(GObject *object)
81 {
82     gst_vaapi_window_destroy(GST_VAAPI_WINDOW(object));
83
84     G_OBJECT_CLASS(gst_vaapi_window_parent_class)->finalize(object);
85 }
86
87 static void
88 gst_vaapi_window_set_property(
89     GObject      *object,
90     guint         prop_id,
91     const GValue *value,
92     GParamSpec   *pspec
93 )
94 {
95     GstVaapiWindow * const window = GST_VAAPI_WINDOW(object);
96
97     switch (prop_id) {
98     case PROP_WIDTH:
99         gst_vaapi_window_set_width(window, g_value_get_uint(value));
100         break;
101     case PROP_HEIGHT:
102         gst_vaapi_window_set_height(window, g_value_get_uint(value));
103         break;
104     default:
105         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
106         break;
107     }
108 }
109
110 static void
111 gst_vaapi_window_get_property(
112     GObject    *object,
113     guint       prop_id,
114     GValue     *value,
115     GParamSpec *pspec
116 )
117 {
118     GstVaapiWindow * const window = GST_VAAPI_WINDOW(object);
119
120     switch (prop_id) {
121     case PROP_WIDTH:
122         g_value_set_uint(value, gst_vaapi_window_get_width(window));
123         break;
124     case PROP_HEIGHT:
125         g_value_set_uint(value, gst_vaapi_window_get_height(window));
126         break;
127     default:
128         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
129         break;
130     }
131 }
132
133 static void
134 gst_vaapi_window_constructed(GObject *object)
135 {
136     GstVaapiWindow * const window = GST_VAAPI_WINDOW(object);
137     GObjectClass *parent_class;
138
139     window->priv->is_constructed = gst_vaapi_window_create(window);
140
141     parent_class = G_OBJECT_CLASS(gst_vaapi_window_parent_class);
142     if (parent_class->constructed)
143         parent_class->constructed(object);
144 }
145
146 static void
147 gst_vaapi_window_class_init(GstVaapiWindowClass *klass)
148 {
149     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
150
151     g_type_class_add_private(klass, sizeof(GstVaapiWindowPrivate));
152
153     object_class->finalize     = gst_vaapi_window_finalize;
154     object_class->set_property = gst_vaapi_window_set_property;
155     object_class->get_property = gst_vaapi_window_get_property;
156     object_class->constructed  = gst_vaapi_window_constructed;
157
158     g_object_class_install_property
159         (object_class,
160          PROP_WIDTH,
161          g_param_spec_uint("width",
162                            "Width",
163                            "The window width",
164                            1, G_MAXUINT32, 1,
165                            G_PARAM_READWRITE));
166
167     g_object_class_install_property
168         (object_class,
169          PROP_HEIGHT,
170          g_param_spec_uint("height",
171                            "height",
172                            "The window height",
173                            1, G_MAXUINT32, 1,
174                            G_PARAM_READWRITE));
175 }
176
177 static void
178 gst_vaapi_window_init(GstVaapiWindow *window)
179 {
180     GstVaapiWindowPrivate *priv = GST_VAAPI_WINDOW_GET_PRIVATE(window);
181
182     window->priv                = priv;
183     priv->width                 = 1;
184     priv->height                = 1;
185     priv->is_constructed        = FALSE;
186     priv->is_fullscreen         = FALSE;
187 }
188
189 /**
190  * gst_vaapi_window_show:
191  * @window: a #GstVaapiWindow
192  *
193  * Flags a window to be displayed. Any window that is not shown will
194  * not appear on the screen.
195  */
196 void
197 gst_vaapi_window_show(GstVaapiWindow *window)
198 {
199     g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
200     g_return_if_fail(window->priv->is_constructed);
201
202     GST_VAAPI_WINDOW_GET_CLASS(window)->show(window);
203 }
204
205 /**
206  * gst_vaapi_window_hide:
207  * @window: a #GstVaapiWindow
208  *
209  * Reverses the effects of gst_vaapi_window_show(), causing the window
210  * to be hidden (invisible to the user).
211  */
212 void
213 gst_vaapi_window_hide(GstVaapiWindow *window)
214 {
215     g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
216     g_return_if_fail(window->priv->is_constructed);
217
218     GST_VAAPI_WINDOW_GET_CLASS(window)->hide(window);
219 }
220
221 /**
222  * gst_vaapi_window_set_fullscreen:
223  * @window: a #GstVaapiWindow
224  * @fullscreen: %TRUE to request window to get fullscreen
225  *
226  * Requests to place the @window in fullscreen or unfullscreen states.
227  */
228 void
229 gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
230 {
231     GstVaapiWindowClass *klass;
232
233     g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
234
235     klass = GST_VAAPI_WINDOW_GET_CLASS(window);
236
237     if (window->priv->is_fullscreen != fullscreen && klass->set_fullscreen) {
238         klass->set_fullscreen(window, fullscreen);
239         window->priv->is_fullscreen = fullscreen;
240     }
241 }
242
243 /**
244  * gst_vaapi_window_get_width:
245  * @window: a #GstVaapiWindow
246  *
247  * Retrieves the width of a #GstVaapiWindow.
248  *
249  * Return value: the width of the @window, in pixels
250  */
251 guint
252 gst_vaapi_window_get_width(GstVaapiWindow *window)
253 {
254     g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), 0);
255     g_return_val_if_fail(window->priv->is_constructed, 0);
256
257     return window->priv->width;
258 }
259
260 /**
261  * gst_vaapi_window_get_height:
262  * @window: a #GstVaapiWindow
263  *
264  * Retrieves the height of a #GstVaapiWindow
265  *
266  * Return value: the height of the @window, in pixels
267  */
268 guint
269 gst_vaapi_window_get_height(GstVaapiWindow *window)
270 {
271     g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), 0);
272     g_return_val_if_fail(window->priv->is_constructed, 0);
273
274     return window->priv->height;
275 }
276
277 /**
278  * gst_vaapi_window_get_size:
279  * @window: a #GstVaapiWindow
280  * @pwidth: (out) (allow-none): return location for the width, or %NULL
281  * @pheight: (out) (allow-none): return location for the height, or %NULL
282  *
283  * Retrieves the dimensions of a #GstVaapiWindow.
284  */
285 void
286 gst_vaapi_window_get_size(GstVaapiWindow *window, guint *pwidth, guint *pheight)
287 {
288     g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
289     g_return_if_fail(window->priv->is_constructed);
290
291     if (pwidth)
292         *pwidth = window->priv->width;
293
294     if (pheight)
295         *pheight = window->priv->height;
296 }
297
298 /**
299  * gst_vaapi_window_set_width:
300  * @window: a #GstVaapiWindow
301  * @width: requested new width for the window, in pixels
302  *
303  * Resizes the @window to match the specified @width.
304  */
305 void
306 gst_vaapi_window_set_width(GstVaapiWindow *window, guint width)
307 {
308     g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
309
310     gst_vaapi_window_set_size(window, width, window->priv->height);
311 }
312
313 /**
314  * gst_vaapi_window_set_height:
315  * @window: a #GstVaapiWindow
316  * @height: requested new height for the window, in pixels
317  *
318  * Resizes the @window to match the specified @height.
319  */
320 void
321 gst_vaapi_window_set_height(GstVaapiWindow *window, guint height)
322 {
323     g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
324
325     gst_vaapi_window_set_size(window, window->priv->width, height);
326 }
327
328 /**
329  * gst_vaapi_window_set_size:
330  * @window: a #GstVaapiWindow
331  * @width: requested new width for the window, in pixels
332  * @height: requested new height for the window, in pixels
333  *
334  * Resizes the @window to match the specified @width and @height.
335  */
336 void
337 gst_vaapi_window_set_size(GstVaapiWindow *window, guint width, guint height)
338 {
339     g_return_if_fail(GST_VAAPI_IS_WINDOW(window));
340
341     if (width == window->priv->width && height == window->priv->height)
342         return;
343
344     window->priv->width  = width;
345     window->priv->height = height;
346
347     if (window->priv->is_constructed)
348         GST_VAAPI_WINDOW_GET_CLASS(window)->resize(window, width, height);
349 }
350
351 static inline void
352 get_surface_rect(GstVaapiSurface *surface, GstVideoRectangle *rect)
353 {
354     guint width, height;
355
356     gst_vaapi_surface_get_size(surface, &width, &height);
357     rect->x = 0;
358     rect->y = 0;
359     rect->w = width;
360     rect->h = height;
361 }
362
363 static inline void
364 get_window_rect(GstVaapiWindow *window, GstVideoRectangle *rect)
365 {
366     guint width, height;
367
368     gst_vaapi_window_get_size(window, &width, &height);
369     rect->x = 0;
370     rect->y = 0;
371     rect->w = width;
372     rect->h = height;
373 }
374
375 /**
376  * gst_vaapi_window_put_surface:
377  * @window: a #GstVaapiWindow
378  * @surface: a #GstVaapiSurface
379  * @src_rect: (allow-none): the sub-rectangle of the source surface to
380  *   extract and process. If %NULL, the entire surface will be used.
381  * @dst_rect: (allow-none): the sub-rectangle of the destination
382  *   window into which the surface is rendered. If %NULL, the entire
383  *   window will be used.
384  * @flags: postprocessing flags. See #GstVaapiSurfaceRenderFlags
385  *
386  * Renders the @surface region specified by @src_rect into the @window
387  * region specified by @dst_rect. The @flags specify how de-interlacing
388  * (if needed), color space conversion, scaling and other postprocessing
389  * transformations are performed.
390  *
391  * Return value: %TRUE on success
392  */
393 gboolean
394 gst_vaapi_window_put_surface(
395     GstVaapiWindow          *window,
396     GstVaapiSurface         *surface,
397     const GstVideoRectangle *src_rect,
398     const GstVideoRectangle *dst_rect,
399     guint                    flags
400 )
401 {
402     GstVideoRectangle src_rect_default, dst_rect_default;
403
404     g_return_val_if_fail(GST_VAAPI_IS_WINDOW(window), FALSE);
405     g_return_val_if_fail(window->priv->is_constructed, FALSE);
406     g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
407
408     if (!src_rect) {
409         src_rect = &src_rect_default;
410         get_surface_rect(surface, &src_rect_default);
411     }
412
413     if (!dst_rect) {
414         dst_rect = &dst_rect_default;
415         get_window_rect(window, &dst_rect_default);
416     }
417
418     return GST_VAAPI_WINDOW_GET_CLASS(window)->render(window,
419                                                       surface,
420                                                       src_rect,
421                                                       dst_rect,
422                                                       flags);
423 }