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