Add support for GstVaapiSurfaceProxy to GstVaapiVideoBuffer.
[vaapi:gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapivideobuffer.c
1 /*
2  *  gstvaapivideobuffer.c - Gst VA video buffer
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:gstvaapivideobuffer
23  * @short_description: VA video buffer for GStreamer
24  */
25
26 #include "config.h"
27 #include "gstvaapivideobuffer.h"
28 #include <gst/vaapi/gstvaapiimagepool.h>
29 #include <gst/vaapi/gstvaapisurfacepool.h>
30
31 #define DEBUG 1
32 #include "gstvaapidebug.h"
33
34 G_DEFINE_TYPE(GstVaapiVideoBuffer, gst_vaapi_video_buffer, GST_TYPE_BUFFER);
35
36 #define GST_VAAPI_VIDEO_BUFFER_GET_PRIVATE(obj)                 \
37     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
38                                  GST_VAAPI_TYPE_VIDEO_BUFFER,   \
39                                  GstVaapiVideoBufferPrivate))
40
41 struct _GstVaapiVideoBufferPrivate {
42     GstVaapiVideoPool          *image_pool;
43     GstVaapiImage              *image;
44     GstVaapiVideoPool          *surface_pool;
45     GstVaapiSurface            *surface;
46     GstVaapiSurfaceProxy       *proxy;
47     guint                       flags;
48 };
49
50 static void
51 gst_vaapi_video_buffer_destroy_image(GstVaapiVideoBuffer *buffer)
52 {
53     GstVaapiVideoBufferPrivate * const priv = buffer->priv;
54
55     if (priv->image) {
56         if (priv->image_pool)
57             gst_vaapi_video_pool_put_object(priv->image_pool, priv->image);
58         else
59             g_object_unref(priv->image);
60         priv->image = NULL;
61     }
62
63     if (priv->image_pool) {
64         g_object_unref(priv->image_pool);
65         priv->image_pool = NULL;
66     }
67 }
68
69 static void
70 gst_vaapi_video_buffer_destroy_surface(GstVaapiVideoBuffer *buffer)
71 {
72     GstVaapiVideoBufferPrivate * const priv = buffer->priv;
73
74     if (priv->proxy) {
75         g_object_unref(priv->proxy);
76         priv->proxy = NULL;
77     }
78
79     if (priv->surface) {
80         if (priv->surface_pool)
81             gst_vaapi_video_pool_put_object(priv->surface_pool, priv->surface);
82         else
83             g_object_unref(priv->surface);
84         priv->surface = NULL;
85     }
86
87     if (priv->surface_pool) {
88         g_object_unref(priv->surface_pool);
89         priv->surface_pool = NULL;
90     }
91 }
92
93 static void
94 gst_vaapi_video_buffer_finalize(GstMiniObject *object)
95 {
96     GstVaapiVideoBuffer * const buffer = GST_VAAPI_VIDEO_BUFFER(object);
97     GstMiniObjectClass *parent_class;
98
99     gst_vaapi_video_buffer_destroy_image(buffer);
100     gst_vaapi_video_buffer_destroy_surface(buffer);
101
102     parent_class = GST_MINI_OBJECT_CLASS(gst_vaapi_video_buffer_parent_class);
103     if (parent_class->finalize)
104         parent_class->finalize(object);
105 }
106
107 static void
108 gst_vaapi_video_buffer_class_init(GstVaapiVideoBufferClass *klass)
109 {
110     GstMiniObjectClass * const object_class = GST_MINI_OBJECT_CLASS(klass);
111
112     g_type_class_add_private(klass, sizeof(GstVaapiVideoBufferPrivate));
113
114     object_class->finalize = gst_vaapi_video_buffer_finalize;
115 }
116
117 static void
118 gst_vaapi_video_buffer_init(GstVaapiVideoBuffer *buffer)
119 {
120     GstVaapiVideoBufferPrivate *priv;
121
122     priv                = GST_VAAPI_VIDEO_BUFFER_GET_PRIVATE(buffer);
123     buffer->priv        = priv;
124     priv->image_pool    = NULL;
125     priv->image         = NULL;
126     priv->surface_pool  = NULL;
127     priv->surface       = NULL;
128     priv->proxy         = NULL;
129 }
130
131 static inline GstVaapiVideoBuffer *
132 gst_vaapi_video_buffer_new(void)
133 {
134     GstMiniObject *object;
135
136     object = gst_mini_object_new(GST_VAAPI_TYPE_VIDEO_BUFFER);
137     if (!object)
138         return NULL;
139
140     return GST_VAAPI_VIDEO_BUFFER(object);
141 }
142
143 /**
144  * gst_vaapi_video_buffer_new_from_pool:
145  * @pool: a #GstVaapiVideoPool
146  *
147  * Creates a #GstBuffer with a video object allocated from a @pool.
148  * Only #GstVaapiSurfacePool and #GstVaapiImagePool pools are supported.
149  *
150  * The buffer is destroyed through the last call to gst_buffer_unref()
151  * and the video objects are pushed back to their respective pools.
152  *
153  * Return value: the newly allocated #GstBuffer, or %NULL on error
154  */
155 GstBuffer *
156 gst_vaapi_video_buffer_new_from_pool(GstVaapiVideoPool *pool)
157 {
158     GstVaapiVideoBuffer *buffer;
159     gboolean is_image_pool, is_surface_pool;
160
161     g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), NULL);
162
163     is_image_pool   = GST_VAAPI_IS_IMAGE_POOL(pool);
164     is_surface_pool = GST_VAAPI_IS_SURFACE_POOL(pool);
165
166     if (!is_image_pool && !is_surface_pool)
167         return NULL;
168
169     buffer = gst_vaapi_video_buffer_new();
170     if (buffer &&
171         ((is_image_pool &&
172           gst_vaapi_video_buffer_set_image_from_pool(buffer, pool)) ||
173          (is_surface_pool &&
174           gst_vaapi_video_buffer_set_surface_from_pool(buffer, pool))))
175         return GST_BUFFER(buffer);
176
177     gst_mini_object_unref(GST_MINI_OBJECT(buffer));
178     return NULL;
179 }
180
181 /**
182  * gst_vaapi_video_buffer_new_with_image:
183  * @image: a #GstVaapiImage
184  *
185  * Creates a #GstBuffer with the specified @image. The resulting
186  * buffer holds an additional reference to the @image.
187  *
188  * Return value: the newly allocated #GstBuffer, or %NULL on error
189  */
190 GstBuffer *
191 gst_vaapi_video_buffer_new_with_image(GstVaapiImage *image)
192 {
193     GstVaapiVideoBuffer *buffer;
194
195     g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL);
196
197     buffer = gst_vaapi_video_buffer_new();
198     if (buffer)
199         gst_vaapi_video_buffer_set_image(buffer, image);
200     return GST_BUFFER(buffer);
201 }
202
203 /**
204  * gst_vaapi_video_buffer_new_with_surface:
205  * @surface: a #GstVaapiSurface
206  *
207  * Creates a #GstBuffer with the specified @surface. The resulting
208  * buffer holds an additional reference to the @surface.
209  *
210  * Return value: the newly allocated #GstBuffer, or %NULL on error
211  */
212 GstBuffer *
213 gst_vaapi_video_buffer_new_with_surface(GstVaapiSurface *surface)
214 {
215     GstVaapiVideoBuffer *buffer;
216
217     g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
218
219     buffer = gst_vaapi_video_buffer_new();
220     if (buffer)
221         gst_vaapi_video_buffer_set_surface(buffer, surface);
222     return GST_BUFFER(buffer);
223 }
224
225 /**
226  * gst_vaapi_video_buffer_new_with_surface_proxy:
227  * @proxy: a #GstVaapiSurfaceProxy
228  *
229  * Creates a #GstBuffer with the specified surface @proxy. The
230  * resulting buffer holds an additional reference to the @proxy.
231  *
232  * Return value: the newly allocated #GstBuffer, or %NULL on error
233  */
234 GstBuffer *
235 gst_vaapi_video_buffer_new_with_surface_proxy(GstVaapiSurfaceProxy *proxy)
236 {
237     GstVaapiVideoBuffer *buffer;
238
239     g_return_val_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy), NULL);
240
241     buffer = gst_vaapi_video_buffer_new();
242     if (buffer)
243         gst_vaapi_video_buffer_set_surface_proxy(buffer, proxy);
244     return GST_BUFFER(buffer);
245 }
246
247 /**
248  * gst_vaapi_video_buffer_get_image:
249  * @buffer: a #GstVaapiVideoBuffer
250  *
251  * Retrieves the #GstVaapiImage bound to the @buffer. The @buffer owns
252  * the #GstVaapiImage so the caller is responsible for calling
253  * g_object_ref() when needed.
254  *
255  * Return value: the #GstVaapiImage bound to the @buffer, or %NULL if
256  *   there is none
257  */
258 GstVaapiImage *
259 gst_vaapi_video_buffer_get_image(GstVaapiVideoBuffer *buffer)
260 {
261     g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
262
263     return buffer->priv->image;
264 }
265
266 /**
267  * gst_vaapi_video_buffer_set_image:
268  * @buffer: a #GstVaapiVideoBuffer
269  * @image: a #GstVaapiImage
270  *
271  * Binds @image to the @buffer. If the @buffer contains another image
272  * previously allocated from a pool, it's pushed back to its parent
273  * pool and the pool is also released.
274  */
275 void
276 gst_vaapi_video_buffer_set_image(
277     GstVaapiVideoBuffer *buffer,
278     GstVaapiImage       *image
279 )
280 {
281     g_return_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer));
282     g_return_if_fail(GST_VAAPI_IS_IMAGE(image));
283
284     gst_vaapi_video_buffer_destroy_image(buffer);
285
286     if (image)
287         buffer->priv->image = g_object_ref(image);
288 }
289
290 /**
291  * gst_vaapi_video_buffer_set_image_from_pool
292  * @buffer: a #GstVaapiVideoBuffer
293  * @pool: a #GstVaapiVideoPool
294  *
295  * Binds a newly allocated video object from the @pool. The @pool
296  * shall be of type #GstVaapiImagePool. Previously allocated objects
297  * are released and returned to their parent pools, if any.
298  *
299  * Return value: %TRUE on success
300  */
301 gboolean
302 gst_vaapi_video_buffer_set_image_from_pool(
303     GstVaapiVideoBuffer *buffer,
304     GstVaapiVideoPool   *pool
305 )
306 {
307     g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), FALSE);
308     g_return_val_if_fail(GST_VAAPI_IS_IMAGE_POOL(pool), FALSE);
309
310     gst_vaapi_video_buffer_destroy_image(buffer);
311
312     if (pool) {
313         buffer->priv->image = gst_vaapi_video_pool_get_object(pool);
314         if (!buffer->priv->image)
315             return FALSE;
316         buffer->priv->image_pool = g_object_ref(pool);
317     }
318     return TRUE;
319 }
320
321 /**
322  * gst_vaapi_video_buffer_get_surface:
323  * @buffer: a #GstVaapiVideoBuffer
324  *
325  * Retrieves the #GstVaapiSurface bound to the @buffer. The @buffer
326  * owns the #GstVaapiSurface so the caller is responsible for calling
327  * g_object_ref() when needed.
328  *
329  * Return value: the #GstVaapiSurface bound to the @buffer, or %NULL if
330  *   there is none
331  */
332 GstVaapiSurface *
333 gst_vaapi_video_buffer_get_surface(GstVaapiVideoBuffer *buffer)
334 {
335     g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
336
337     return buffer->priv->surface;
338 }
339
340 /**
341  * gst_vaapi_video_buffer_set_surface:
342  * @buffer: a #GstVaapiVideoBuffer
343  * @surface: a #GstVaapiSurface
344  *
345  * Binds @surface to the @buffer. If the @buffer contains another
346  * surface previously allocated from a pool, it's pushed back to its
347  * parent pool and the pool is also released.
348  */
349 void
350 gst_vaapi_video_buffer_set_surface(
351     GstVaapiVideoBuffer *buffer,
352     GstVaapiSurface     *surface
353 )
354 {
355     g_return_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer));
356     g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
357
358     gst_vaapi_video_buffer_destroy_surface(buffer);
359
360     if (surface)
361         buffer->priv->surface = g_object_ref(surface);
362 }
363
364 /**
365  * gst_vaapi_video_buffer_set_surface_from_pool
366  * @buffer: a #GstVaapiVideoBuffer
367  * @pool: a #GstVaapiVideoPool
368  *
369  * Binds a newly allocated video object from the @pool. The @pool
370  * shall be of type #GstVaapiSurfacePool. Previously allocated objects
371  * are released and returned to their parent pools, if any.
372  *
373  * Return value: %TRUE on success
374  */
375 gboolean
376 gst_vaapi_video_buffer_set_surface_from_pool(
377     GstVaapiVideoBuffer *buffer,
378     GstVaapiVideoPool   *pool
379 )
380 {
381     g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), FALSE);
382     g_return_val_if_fail(GST_VAAPI_IS_SURFACE_POOL(pool), FALSE);
383
384     gst_vaapi_video_buffer_destroy_surface(buffer);
385
386     if (pool) {
387         buffer->priv->surface = gst_vaapi_video_pool_get_object(pool);
388         if (!buffer->priv->surface)
389             return FALSE;
390         buffer->priv->surface_pool = g_object_ref(pool);
391     }
392     return TRUE;
393 }
394
395 /**
396  * gst_vaapi_video_buffer_get_surface_proxy:
397  * @buffer: a #GstVaapiVideoBuffer
398  *
399  * Retrieves the #GstVaapiSurfaceProxy bound to the @buffer. The @buffer
400  * owns the #GstVaapiSurfaceProxy so the caller is responsible for calling
401  * g_object_ref() when needed.
402  *
403  * Return value: the #GstVaapiSurfaceProxy bound to the @buffer, or
404  *   %NULL if there is none
405  */
406 GstVaapiSurfaceProxy *
407 gst_vaapi_video_buffer_get_surface_proxy(GstVaapiVideoBuffer *buffer)
408 {
409     g_return_val_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer), NULL);
410
411     return buffer->priv->proxy;
412 }
413
414 /**
415  * gst_vaapi_video_buffer_set_surface_proxy:
416  * @buffer: a #GstVaapiVideoBuffer
417  * @proxy: a #GstVaapiSurfaceProxy
418  *
419  * Binds surface @proxy to the @buffer. If the @buffer contains another
420  * surface previously allocated from a pool, it's pushed back to its
421  * parent pool and the pool is also released.
422  */
423 void
424 gst_vaapi_video_buffer_set_surface_proxy(
425     GstVaapiVideoBuffer  *buffer,
426     GstVaapiSurfaceProxy *proxy
427 )
428 {
429     g_return_if_fail(GST_VAAPI_IS_VIDEO_BUFFER(buffer));
430     g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
431
432     gst_vaapi_video_buffer_destroy_surface(buffer);
433
434     if (proxy) {
435         GstVaapiVideoBufferPrivate * const priv = buffer->priv;
436         priv->proxy   = g_object_ref(proxy);
437         priv->surface = g_object_ref(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
438     }
439 }