decoder: add support for video cropping.
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapisurfaceproxy.c
1 /*
2  *  gstvaapisurfaceproxy.c - VA surface proxy
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:gstvaapisurfaceproxy
25  * @short_description: VA surface proxy
26  */
27
28 #include "sysdeps.h"
29 #include "gstvaapisurfaceproxy.h"
30 #include "gstvaapisurfaceproxy_priv.h"
31 #include "gstvaapivideopool_priv.h"
32
33 #define DEBUG 1
34 #include "gstvaapidebug.h"
35
36 static void
37 set_crop_rect_from_surface(GstVaapiSurfaceProxy *proxy)
38 {
39     guint width, height;
40
41     gst_vaapi_surface_get_size(proxy->surface, &width, &height);
42     proxy->crop_rect.x = 0;
43     proxy->crop_rect.y = 0;
44     proxy->crop_rect.width = width;
45     proxy->crop_rect.height = height;
46 }
47
48 static inline void
49 set_crop_rect(GstVaapiSurfaceProxy *proxy, const GstVaapiRectangle *crop_rect)
50 {
51     if (crop_rect)
52         proxy->crop_rect = *crop_rect;
53     else
54         set_crop_rect_from_surface(proxy);
55 }
56
57 static void
58 gst_vaapi_surface_proxy_finalize(GstVaapiSurfaceProxy *proxy)
59 {
60     if (proxy->destroy_func)
61         proxy->destroy_func(proxy->destroy_data);
62
63     if (proxy->surface) {
64         if (proxy->pool)
65             gst_vaapi_video_pool_put_object(proxy->pool, proxy->surface);
66         gst_vaapi_object_unref(proxy->surface);
67         proxy->surface = NULL;
68     }
69     gst_vaapi_video_pool_replace(&proxy->pool, NULL);
70 }
71
72 static inline const GstVaapiMiniObjectClass *
73 gst_vaapi_surface_proxy_class(void)
74 {
75     static const GstVaapiMiniObjectClass GstVaapiSurfaceProxyClass = {
76         sizeof(GstVaapiSurfaceProxy),
77         (GDestroyNotify)gst_vaapi_surface_proxy_finalize
78     };
79     return &GstVaapiSurfaceProxyClass;
80 }
81
82 GstVaapiSurfaceProxy *
83 gst_vaapi_surface_proxy_new_from_pool(GstVaapiSurfacePool *pool)
84 {
85     GstVaapiSurfaceProxy *proxy;
86
87     g_return_val_if_fail(pool != NULL, NULL);
88
89     proxy = (GstVaapiSurfaceProxy *)
90         gst_vaapi_mini_object_new(gst_vaapi_surface_proxy_class());
91     if (!proxy)
92         return NULL;
93
94     proxy->pool = gst_vaapi_video_pool_ref(pool);
95     proxy->surface = gst_vaapi_video_pool_get_object(proxy->pool);
96     if (!proxy->surface)
97         goto error;
98     set_crop_rect_from_surface(proxy);
99
100     proxy->timestamp = GST_CLOCK_TIME_NONE;
101     proxy->duration = GST_CLOCK_TIME_NONE;
102     proxy->destroy_func = NULL;
103     gst_vaapi_object_ref(proxy->surface);
104     return proxy;
105
106 error:
107     gst_vaapi_surface_proxy_unref(proxy);
108     return NULL;
109 }
110
111 /**
112  * gst_vaapi_surface_proxy_ref:
113  * @proxy: a #GstVaapiSurfaceProxy
114  *
115  * Atomically increases the reference count of the given @proxy by one.
116  *
117  * Returns: The same @proxy argument
118  */
119 GstVaapiSurfaceProxy *
120 gst_vaapi_surface_proxy_ref(GstVaapiSurfaceProxy *proxy)
121 {
122     g_return_val_if_fail(proxy != NULL, NULL);
123
124     return GST_VAAPI_SURFACE_PROXY(gst_vaapi_mini_object_ref(
125                                        GST_VAAPI_MINI_OBJECT(proxy)));
126 }
127
128 /**
129  * gst_vaapi_surface_proxy_unref:
130  * @proxy: a #GstVaapiSurfaceProxy
131  *
132  * Atomically decreases the reference count of the @proxy by one. If
133  * the reference count reaches zero, the object will be free'd.
134  */
135 void
136 gst_vaapi_surface_proxy_unref(GstVaapiSurfaceProxy *proxy)
137 {
138     g_return_if_fail(proxy != NULL);
139
140     gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(proxy));
141 }
142
143 /**
144  * gst_vaapi_surface_proxy_replace:
145  * @old_proxy_ptr: a pointer to a #GstVaapiSurfaceProxy
146  * @new_proxy: a #GstVaapiSurfaceProxy
147  *
148  * Atomically replaces the proxy object held in @old_proxy_ptr with
149  * @new_proxy. This means that @old_proxy_ptr shall reference a valid
150  * object. However, @new_proxy can be NULL.
151  */
152 void
153 gst_vaapi_surface_proxy_replace(GstVaapiSurfaceProxy **old_proxy_ptr,
154     GstVaapiSurfaceProxy *new_proxy)
155 {
156     g_return_if_fail(old_proxy_ptr != NULL);
157
158     gst_vaapi_mini_object_replace((GstVaapiMiniObject **)old_proxy_ptr,
159         GST_VAAPI_MINI_OBJECT(new_proxy));
160 }
161
162 /**
163  * gst_vaapi_surface_proxy_get_surface:
164  * @proxy: a #GstVaapiSurfaceProxy
165  *
166  * Returns the #GstVaapiSurface stored in the @proxy.
167  *
168  * Return value: the #GstVaapiSurface
169  */
170 GstVaapiSurface *
171 gst_vaapi_surface_proxy_get_surface(GstVaapiSurfaceProxy *proxy)
172 {
173     g_return_val_if_fail(proxy != NULL, NULL);
174
175     return GST_VAAPI_SURFACE_PROXY_SURFACE(proxy);
176 }
177
178 /**
179  * gst_vaapi_surface_proxy_get_flags:
180  * @proxy: a #GstVaapiSurfaceProxy
181  *
182  * Returns the #GstVaapiSurfaceProxyFlags associated with this surface
183  * @proxy.
184  *
185  * Return value: the set of #GstVaapiSurfaceProxyFlags
186  */
187 guint
188 gst_vaapi_surface_proxy_get_flags(GstVaapiSurfaceProxy *proxy)
189 {
190     g_return_val_if_fail(proxy != NULL, 0);
191     
192     return GST_VAAPI_SURFACE_PROXY_FLAGS(proxy);
193 }
194
195 /**
196  * gst_vaapi_surface_proxy_get_surface_id:
197  * @proxy: a #GstVaapiSurfaceProxy
198  *
199  * Returns the VA surface ID stored in the @proxy.
200  *
201  * Return value: the #GstVaapiID
202  */
203 GstVaapiID
204 gst_vaapi_surface_proxy_get_surface_id(GstVaapiSurfaceProxy *proxy)
205 {
206     g_return_val_if_fail(proxy != NULL, 0);
207     g_return_val_if_fail(proxy->surface != NULL, 0);
208
209     return GST_VAAPI_SURFACE_PROXY_SURFACE_ID(proxy);
210 }
211
212 /**
213  * gst_vaapi_surface_proxy_get_timestamp:
214  * @proxy: a #GstVaapiSurfaceProxy
215  *
216  * Returns the presentation timestamp for this surface @proxy.
217  *
218  * Return value: the presentation timestamp
219  */
220 GstClockTime
221 gst_vaapi_surface_proxy_get_timestamp(GstVaapiSurfaceProxy *proxy)
222 {
223     g_return_val_if_fail(proxy != NULL, 0);
224     
225     return GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
226 }
227
228 /**
229  * gst_vaapi_surface_proxy_get_duration:
230  * @proxy: a #GstVaapiSurfaceProxy
231  *
232  * Returns the presentation duration for this surface @proxy.
233  *
234  * Return value: the presentation duration
235  */
236 GstClockTime
237 gst_vaapi_surface_proxy_get_duration(GstVaapiSurfaceProxy *proxy)
238 {
239     g_return_val_if_fail(proxy != NULL, 0);
240     
241     return GST_VAAPI_SURFACE_PROXY_DURATION(proxy);
242 }
243
244 /**
245  * gst_vaapi_surface_proxy_set_destroy_notify:
246  * @proxy: a @GstVaapiSurfaceProxy
247  * @destroy_func: a #GDestroyNotify function
248  * @user_data: some extra data to pass to the @destroy_func function
249  *
250  * Sets @destroy_func as the function to call when the surface @proxy
251  * was released. At this point, the proxy object is considered
252  * released, i.e. the underlying data storage is no longer valid and
253  * the callback function shall not expect anything from that.
254  */
255 void
256 gst_vaapi_surface_proxy_set_destroy_notify(GstVaapiSurfaceProxy *proxy,
257     GDestroyNotify destroy_func, gpointer user_data)
258 {
259     g_return_if_fail(proxy != NULL);
260
261     proxy->destroy_func = destroy_func;
262     proxy->destroy_data = user_data;
263 }
264
265 /**
266  * gst_vaapi_surface_proxy_get_crop_rect:
267  * @proxy: a #GstVaapiSurfaceProxy
268  *
269  * Returns the #GstVaapiRectangle stored in the @proxy and that
270  * represents the cropping rectangle for the underlying surface to be
271  * used for rendering.
272  *
273  * Return value: the #GstVaapiRectangle
274  */
275 const GstVaapiRectangle *
276 gst_vaapi_surface_proxy_get_crop_rect(GstVaapiSurfaceProxy *proxy)
277 {
278     g_return_val_if_fail(proxy != NULL, NULL);
279
280     return GST_VAAPI_SURFACE_PROXY_CROP_RECT(proxy);
281 }
282
283 /**
284  * gst_vaapi_surface_proxy_set_crop_rect:
285  * @proxy: #GstVaapiSurfaceProxy
286  * @crop_rect: the #GstVaapiRectangle to be stored in @proxy
287  *
288  * Associates the @crop_rect with the @proxy
289  */
290 void
291 gst_vaapi_surface_proxy_set_crop_rect(GstVaapiSurfaceProxy *proxy,
292     const GstVaapiRectangle *crop_rect)
293 {
294     g_return_if_fail(proxy != NULL);
295
296     set_crop_rect(proxy, crop_rect);
297 }