cb014dae680bae2f1c3007491064af8195a138f4
[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  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2011-2014 Intel Corporation
7  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation; either version 2.1
12  *  of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free
21  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301 USA
23  */
24
25 /**
26  * SECTION:gstvaapisurfaceproxy
27  * @short_description: VA surface proxy
28  */
29
30 #include "sysdeps.h"
31 #include "gstvaapisurfaceproxy.h"
32 #include "gstvaapisurfaceproxy_priv.h"
33 #include "gstvaapivideopool_priv.h"
34
35 #define DEBUG 1
36 #include "gstvaapidebug.h"
37
38 static void
39 gst_vaapi_surface_proxy_finalize(GstVaapiSurfaceProxy *proxy)
40 {
41     if (proxy->surface) {
42         if (proxy->pool && !proxy->parent)
43             gst_vaapi_video_pool_put_object(proxy->pool, proxy->surface);
44         gst_vaapi_object_unref(proxy->surface);
45         proxy->surface = NULL;
46     }
47     gst_vaapi_video_pool_replace(&proxy->pool, NULL);
48     gst_vaapi_surface_proxy_replace(&proxy->parent, NULL);
49
50     /* Notify the user function that the object is now destroyed */
51     if (proxy->destroy_func)
52         proxy->destroy_func(proxy->destroy_data);
53 }
54
55 static inline const GstVaapiMiniObjectClass *
56 gst_vaapi_surface_proxy_class(void)
57 {
58     static const GstVaapiMiniObjectClass GstVaapiSurfaceProxyClass = {
59         sizeof(GstVaapiSurfaceProxy),
60         (GDestroyNotify)gst_vaapi_surface_proxy_finalize
61     };
62     return &GstVaapiSurfaceProxyClass;
63 }
64
65 /**
66  * gst_vaapi_surface_proxy_new_from_pool:
67  * @pool: a #GstVaapiSurfacePool
68  *
69  * Allocates a new surface from the supplied surface @pool and creates
70  * the wrapped surface proxy object from it. When the last reference
71  * to the proxy object is released, then the underlying VA surface is
72  * pushed back to its parent pool.
73  *
74  * Returns: The same newly allocated @proxy object, or %NULL on error
75  */
76 GstVaapiSurfaceProxy *
77 gst_vaapi_surface_proxy_new_from_pool(GstVaapiSurfacePool *pool)
78 {
79     GstVaapiSurfaceProxy *proxy;
80
81     g_return_val_if_fail(pool != NULL, NULL);
82
83     proxy = (GstVaapiSurfaceProxy *)
84         gst_vaapi_mini_object_new(gst_vaapi_surface_proxy_class());
85     if (!proxy)
86         return NULL;
87
88     proxy->parent = NULL;
89     proxy->destroy_func = NULL;
90     proxy->pool = gst_vaapi_video_pool_ref(pool);
91     proxy->surface = gst_vaapi_video_pool_get_object(proxy->pool);
92     if (!proxy->surface)
93         goto error;
94     proxy->timestamp = GST_CLOCK_TIME_NONE;
95     proxy->duration = GST_CLOCK_TIME_NONE;
96     proxy->has_crop_rect = FALSE;
97     gst_vaapi_object_ref(proxy->surface);
98     return proxy;
99
100 error:
101     gst_vaapi_surface_proxy_unref(proxy);
102     return NULL;
103 }
104
105
106 /**
107  * gst_vaapi_surface_proxy_copy:
108  * @proxy: the parent #GstVaapiSurfaceProxy
109  *
110  * Creates are new VA surface proxy object from the supplied parent
111  * @proxy object with the same initial information, e.g. timestamp,
112  * duration.
113  *
114  * Note: the destroy notify function is not copied into the new
115  * surface proxy object.
116  *
117  * Returns: The same newly allocated @proxy object, or %NULL on error
118  */
119 GstVaapiSurfaceProxy *
120 gst_vaapi_surface_proxy_copy(GstVaapiSurfaceProxy *proxy)
121 {
122     GstVaapiSurfaceProxy *copy;
123
124     g_return_val_if_fail(proxy != NULL, NULL);
125
126     copy = (GstVaapiSurfaceProxy *)
127         gst_vaapi_mini_object_new(gst_vaapi_surface_proxy_class());
128     if (!copy)
129         return NULL;
130
131     GST_VAAPI_SURFACE_PROXY_FLAGS(copy) =
132         GST_VAAPI_SURFACE_PROXY_FLAGS(proxy);
133
134     copy->parent = gst_vaapi_surface_proxy_ref(proxy->parent ?
135         proxy->parent : proxy);
136     copy->pool = gst_vaapi_video_pool_ref(proxy->pool);
137     copy->surface = gst_vaapi_object_ref(proxy->surface);
138     copy->timestamp = proxy->timestamp;
139     copy->duration = proxy->duration;
140     copy->destroy_func = NULL;
141     copy->has_crop_rect = proxy->has_crop_rect;
142     if (copy->has_crop_rect)
143         copy->crop_rect = proxy->crop_rect;
144     return copy;
145 }
146
147 /**
148  * gst_vaapi_surface_proxy_ref:
149  * @proxy: a #GstVaapiSurfaceProxy
150  *
151  * Atomically increases the reference count of the given @proxy by one.
152  *
153  * Returns: The same @proxy argument
154  */
155 GstVaapiSurfaceProxy *
156 gst_vaapi_surface_proxy_ref(GstVaapiSurfaceProxy *proxy)
157 {
158     g_return_val_if_fail(proxy != NULL, NULL);
159
160     return GST_VAAPI_SURFACE_PROXY(gst_vaapi_mini_object_ref(
161                                        GST_VAAPI_MINI_OBJECT(proxy)));
162 }
163
164 /**
165  * gst_vaapi_surface_proxy_unref:
166  * @proxy: a #GstVaapiSurfaceProxy
167  *
168  * Atomically decreases the reference count of the @proxy by one. If
169  * the reference count reaches zero, the object will be free'd.
170  */
171 void
172 gst_vaapi_surface_proxy_unref(GstVaapiSurfaceProxy *proxy)
173 {
174     g_return_if_fail(proxy != NULL);
175
176     gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(proxy));
177 }
178
179 /**
180  * gst_vaapi_surface_proxy_replace:
181  * @old_proxy_ptr: a pointer to a #GstVaapiSurfaceProxy
182  * @new_proxy: a #GstVaapiSurfaceProxy
183  *
184  * Atomically replaces the proxy object held in @old_proxy_ptr with
185  * @new_proxy. This means that @old_proxy_ptr shall reference a valid
186  * object. However, @new_proxy can be NULL.
187  */
188 void
189 gst_vaapi_surface_proxy_replace(GstVaapiSurfaceProxy **old_proxy_ptr,
190     GstVaapiSurfaceProxy *new_proxy)
191 {
192     g_return_if_fail(old_proxy_ptr != NULL);
193
194     gst_vaapi_mini_object_replace((GstVaapiMiniObject **)old_proxy_ptr,
195         GST_VAAPI_MINI_OBJECT(new_proxy));
196 }
197
198 /**
199  * gst_vaapi_surface_proxy_get_surface:
200  * @proxy: a #GstVaapiSurfaceProxy
201  *
202  * Returns the #GstVaapiSurface stored in the @proxy.
203  *
204  * Return value: the #GstVaapiSurface
205  */
206 GstVaapiSurface *
207 gst_vaapi_surface_proxy_get_surface(GstVaapiSurfaceProxy *proxy)
208 {
209     g_return_val_if_fail(proxy != NULL, NULL);
210
211     return GST_VAAPI_SURFACE_PROXY_SURFACE(proxy);
212 }
213
214 /**
215  * gst_vaapi_surface_proxy_get_flags:
216  * @proxy: a #GstVaapiSurfaceProxy
217  *
218  * Returns the #GstVaapiSurfaceProxyFlags associated with this surface
219  * @proxy.
220  *
221  * Return value: the set of #GstVaapiSurfaceProxyFlags
222  */
223 guint
224 gst_vaapi_surface_proxy_get_flags(GstVaapiSurfaceProxy *proxy)
225 {
226     g_return_val_if_fail(proxy != NULL, 0);
227     
228     return GST_VAAPI_SURFACE_PROXY_FLAGS(proxy);
229 }
230
231 /**
232  * gst_vaapi_surface_proxy_get_surface_id:
233  * @proxy: a #GstVaapiSurfaceProxy
234  *
235  * Returns the VA surface ID stored in the @proxy.
236  *
237  * Return value: the #GstVaapiID
238  */
239 GstVaapiID
240 gst_vaapi_surface_proxy_get_surface_id(GstVaapiSurfaceProxy *proxy)
241 {
242     g_return_val_if_fail(proxy != NULL, VA_INVALID_ID);
243     g_return_val_if_fail(proxy->surface != NULL, VA_INVALID_ID);
244
245     return GST_VAAPI_SURFACE_PROXY_SURFACE_ID(proxy);
246 }
247
248 /**
249  * gst_vaapi_surface_proxy_get_timestamp:
250  * @proxy: a #GstVaapiSurfaceProxy
251  *
252  * Returns the presentation timestamp for this surface @proxy.
253  *
254  * Return value: the presentation timestamp
255  */
256 GstClockTime
257 gst_vaapi_surface_proxy_get_timestamp(GstVaapiSurfaceProxy *proxy)
258 {
259     g_return_val_if_fail(proxy != NULL, 0);
260     
261     return GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
262 }
263
264 /**
265  * gst_vaapi_surface_proxy_get_duration:
266  * @proxy: a #GstVaapiSurfaceProxy
267  *
268  * Returns the presentation duration for this surface @proxy.
269  *
270  * Return value: the presentation duration
271  */
272 GstClockTime
273 gst_vaapi_surface_proxy_get_duration(GstVaapiSurfaceProxy *proxy)
274 {
275     g_return_val_if_fail(proxy != NULL, 0);
276     
277     return GST_VAAPI_SURFACE_PROXY_DURATION(proxy);
278 }
279
280 /**
281  * gst_vaapi_surface_proxy_set_destroy_notify:
282  * @proxy: a @GstVaapiSurfaceProxy
283  * @destroy_func: a #GDestroyNotify function
284  * @user_data: some extra data to pass to the @destroy_func function
285  *
286  * Sets @destroy_func as the function to call when the surface @proxy
287  * was released. At this point, the proxy object is considered
288  * released, i.e. the underlying data storage is no longer valid and
289  * the callback function shall not expect anything from that.
290  */
291 void
292 gst_vaapi_surface_proxy_set_destroy_notify(GstVaapiSurfaceProxy *proxy,
293     GDestroyNotify destroy_func, gpointer user_data)
294 {
295     g_return_if_fail(proxy != NULL);
296
297     proxy->destroy_func = destroy_func;
298     proxy->destroy_data = user_data;
299 }
300
301 /**
302  * gst_vaapi_surface_proxy_get_crop_rect:
303  * @proxy: a #GstVaapiSurfaceProxy
304  *
305  * Returns the #GstVaapiRectangle stored in the @proxy and that
306  * represents the cropping rectangle for the underlying surface to be
307  * used for rendering.
308  *
309  * If no cropping rectangle was associated with the @proxy, then this
310  * function returns %NULL.
311  *
312  * Return value: the #GstVaapiRectangle, or %NULL if none was
313  *   associated with the surface proxy
314  */
315 const GstVaapiRectangle *
316 gst_vaapi_surface_proxy_get_crop_rect(GstVaapiSurfaceProxy *proxy)
317 {
318     g_return_val_if_fail(proxy != NULL, NULL);
319
320     return GST_VAAPI_SURFACE_PROXY_CROP_RECT(proxy);
321 }
322
323 /**
324  * gst_vaapi_surface_proxy_set_crop_rect:
325  * @proxy: #GstVaapiSurfaceProxy
326  * @crop_rect: the #GstVaapiRectangle to be stored in @proxy
327  *
328  * Associates the @crop_rect with the @proxy
329  */
330 void
331 gst_vaapi_surface_proxy_set_crop_rect(GstVaapiSurfaceProxy *proxy,
332     const GstVaapiRectangle *crop_rect)
333 {
334     g_return_if_fail(proxy != NULL);
335
336     proxy->has_crop_rect = crop_rect != NULL;
337     if (proxy->has_crop_rect)
338         proxy->crop_rect = *crop_rect;
339 }