texture: move to core libgstvaapi base library.
[platform/upstream/gstreamer.git] / gst / vaapi / gstvaapivideobuffer.c
1 /*
2  *  gstvaapivideobuffer.c - Gstreamer/VA video buffer
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2011-2013 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:gstvaapivideobuffer
27  * @short_description: VA video buffer for GStreamer
28  */
29
30 #include "gst/vaapi/sysdeps.h"
31 #include "gstvaapivideobuffer.h"
32 #if USE_X11 && !GST_CHECK_VERSION(1,1,0)
33 # include "gstvaapivideoconverter_x11.h"
34 #endif
35 #if USE_GLX && !GST_CHECK_VERSION(1,1,0)
36 # include "gstvaapivideoconverter_glx.h"
37 #endif
38
39 #if GST_CHECK_VERSION(1,1,0)
40 static inline GstBuffer *
41 gst_surface_buffer_new (void)
42 {
43   return gst_buffer_new ();
44 }
45 #elif GST_CHECK_VERSION(1,0,0)
46 #include <gst/video/gstsurfacemeta.h>
47
48 #define GST_VAAPI_SURFACE_META_CAST(obj) \
49   ((GstVaapiSurfaceMeta *) (obj))
50
51 typedef struct _GstVaapiSurfaceMeta GstVaapiSurfaceMeta;
52 struct _GstVaapiSurfaceMeta
53 {
54   GstSurfaceMeta base;
55   GstBuffer *buffer;
56 };
57
58 #define GST_VAAPI_SURFACE_META_INFO \
59   gst_vaapi_surface_meta_get_info ()
60
61 static const GstMetaInfo *
62 gst_vaapi_surface_meta_get_info (void);
63
64 typedef GstSurfaceConverter *(*GstSurfaceConverterCreateFunc) (GstSurfaceMeta *
65     meta, const gchar * type, GValue * dest);
66
67 #if USE_X11
68 static GstSurfaceConverter *
69 gst_vaapi_surface_create_converter_x11 (GstSurfaceMeta * base_meta,
70     const gchar * type, GValue * dest)
71 {
72   GstVaapiSurfaceMeta *const meta = GST_VAAPI_SURFACE_META_CAST (base_meta);
73
74   return gst_vaapi_video_converter_x11_new (meta->buffer, type, dest);
75 }
76
77 #undef  gst_vaapi_video_converter_x11_new
78 #define gst_vaapi_video_converter_x11_new \
79   gst_vaapi_surface_create_converter_x11
80 #endif
81
82 #if USE_GLX
83 static GstSurfaceConverter *
84 gst_vaapi_surface_create_converter_glx (GstSurfaceMeta * base_meta,
85     const gchar * type, GValue * dest)
86 {
87   GstVaapiSurfaceMeta *const meta = GST_VAAPI_SURFACE_META_CAST (base_meta);
88
89   return gst_vaapi_video_converter_glx_new (meta->buffer, type, dest);
90 }
91
92 #undef  gst_vaapi_video_converter_glx_new
93 #define gst_vaapi_video_converter_glx_new \
94   gst_vaapi_surface_create_converter_glx
95 #endif
96
97 static GstSurfaceConverter *
98 gst_vaapi_surface_create_converter (GstSurfaceMeta * base_meta,
99     const gchar * type, GValue * dest)
100 {
101   GstVaapiSurfaceMeta *const meta = GST_VAAPI_SURFACE_META_CAST (base_meta);
102   GstVaapiVideoMeta *const vmeta =
103       gst_buffer_get_vaapi_video_meta (meta->buffer);
104   GstSurfaceConverterCreateFunc func;
105
106   if (G_UNLIKELY (!vmeta))
107     return NULL;
108
109   func = (GstSurfaceConverterCreateFunc)
110       gst_vaapi_video_meta_get_surface_converter (vmeta);
111
112   return func ? func (base_meta, type, dest) : NULL;
113 }
114
115 static gboolean
116 gst_vaapi_surface_meta_init (GstVaapiSurfaceMeta * meta, gpointer params,
117     GstBuffer * buffer)
118 {
119   meta->base.create_converter = gst_vaapi_surface_create_converter;
120   meta->buffer = buffer;
121   return TRUE;
122 }
123
124 static void
125 gst_vaapi_surface_meta_free (GstVaapiSurfaceMeta * meta, GstBuffer * buffer)
126 {
127 }
128
129 static gboolean
130 gst_vaapi_surface_meta_transform (GstBuffer * dst_buffer, GstMeta * meta,
131     GstBuffer * src_buffer, GQuark type, gpointer data)
132 {
133   GstVaapiVideoMeta *const src_vmeta =
134       gst_buffer_get_vaapi_video_meta (src_buffer);
135
136   if (GST_META_TRANSFORM_IS_COPY (type)) {
137     GstVaapiSurfaceMeta *const dst_smeta =
138         GST_VAAPI_SURFACE_META_CAST (gst_buffer_add_meta (dst_buffer,
139             GST_VAAPI_SURFACE_META_INFO, NULL));
140
141     /* Note: avoid meta lookups in gst_vaapi_surface_create_converter()
142        by directly calling the GstVaapiVideoMeta::surface_converter hook */
143     dst_smeta->base.create_converter = (GstSurfaceConverterCreateFunc)
144         gst_vaapi_video_meta_get_surface_converter (src_vmeta);
145     return TRUE;
146   }
147   return FALSE;
148 }
149
150 const GstMetaInfo *
151 gst_vaapi_surface_meta_get_info (void)
152 {
153   static gsize g_meta_info;
154
155   if (g_once_init_enter (&g_meta_info)) {
156     gsize meta_info =
157         GPOINTER_TO_SIZE (gst_meta_register (GST_SURFACE_META_API_TYPE,
158             "GstVaapiSurfaceMeta", sizeof (GstVaapiSurfaceMeta),
159             (GstMetaInitFunction) gst_vaapi_surface_meta_init,
160             (GstMetaFreeFunction) gst_vaapi_surface_meta_free,
161             (GstMetaTransformFunction) gst_vaapi_surface_meta_transform));
162     g_once_init_leave (&g_meta_info, meta_info);
163   }
164   return GSIZE_TO_POINTER (g_meta_info);
165 }
166
167 static GstBuffer *
168 gst_surface_buffer_new (void)
169 {
170   GstBuffer *const buffer = gst_buffer_new ();
171
172   if (buffer)
173     gst_buffer_add_meta (buffer, GST_VAAPI_SURFACE_META_INFO, NULL);
174   return buffer;
175 }
176 #else
177 #include <gst/video/gstsurfacebuffer.h>
178
179 #define GST_VAAPI_TYPE_VIDEO_BUFFER \
180   (gst_vaapi_video_buffer_get_type ())
181 #define GST_VAAPI_VIDEO_BUFFER(obj) \
182   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_VAAPI_TYPE_VIDEO_BUFFER, \
183       GstVaapiVideoBuffer))
184 #define GST_VAAPI_VIDEO_BUFFER_CLASS(klass) \
185   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_VAAPI_TYPE_VIDEO_BUFFER, \
186       GstVaapiVideoBufferClass))
187 #define GST_VAAPI_IS_VIDEO_BUFFER(obj) \
188   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_VAAPI_TYPE_VIDEO_BUFFER))
189 #define GST_VAAPI_IS_VIDEO_BUFFER_CLASS(klass) \
190   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_VAAPI_TYPE_VIDEO_BUFFER))
191 #define GST_VAAPI_VIDEO_BUFFER_GET_CLASS(obj) \
192   (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_VAAPI_TYPE_VIDEO_BUFFER, \
193       GstVaapiVideoBufferClass))
194
195 typedef struct _GstVaapiVideoBufferClass GstVaapiVideoBufferClass;
196
197 /**
198  * GstVaapiVideoBuffer:
199  *
200  * A #GstBuffer holding video objects (#GstVaapiSurface and #GstVaapiImage).
201  */
202 struct _GstVaapiVideoBuffer
203 {
204   /*< private >*/
205   GstSurfaceBuffer parent_instance;
206 };
207
208 /**
209  * GstVaapiVideoBufferClass:
210  *
211  * A #GstBuffer holding video objects
212  */
213 struct _GstVaapiVideoBufferClass
214 {
215   /*< private >*/
216   GstSurfaceBufferClass parent_class;
217 };
218
219 GType
220 gst_vaapi_video_buffer_get_type (void) G_GNUC_CONST;
221
222 G_DEFINE_TYPE (GstVaapiVideoBuffer,
223     gst_vaapi_video_buffer, GST_TYPE_SURFACE_BUFFER);
224
225 typedef GstSurfaceConverter *
226 (*GstSurfaceConverterCreateFunc) (GstSurfaceBuffer * surface,
227     const gchar * type, GValue * dest);
228
229 static GstSurfaceConverter *
230 gst_vaapi_video_buffer_create_converter (GstSurfaceBuffer * surface,
231     const gchar * type, GValue * dest)
232 {
233   GstVaapiVideoMeta *const meta =
234       gst_buffer_get_vaapi_video_meta (GST_BUFFER (surface));
235   GstSurfaceConverterCreateFunc func;
236
237   g_return_val_if_fail (meta != NULL, NULL);
238
239   func = (GstSurfaceConverterCreateFunc)
240       gst_vaapi_video_meta_get_surface_converter (meta);
241
242   return func ? func (surface, type, dest) : NULL;
243 }
244
245 static void
246 gst_vaapi_video_buffer_class_init (GstVaapiVideoBufferClass * klass)
247 {
248   GstSurfaceBufferClass *const surface_class = GST_SURFACE_BUFFER_CLASS (klass);
249
250   surface_class->create_converter = gst_vaapi_video_buffer_create_converter;
251 }
252
253 static void
254 gst_vaapi_video_buffer_init (GstVaapiVideoBuffer * buffer)
255 {
256 }
257
258 static inline GstBuffer *
259 gst_surface_buffer_new (void)
260 {
261   return GST_BUFFER_CAST (gst_mini_object_new (GST_VAAPI_TYPE_VIDEO_BUFFER));
262 }
263 #endif
264
265 static GFunc
266 get_surface_converter (GstVaapiDisplay * display)
267 {
268   GFunc func;
269
270   switch (gst_vaapi_display_get_display_type (display)) {
271 #if USE_X11 && !GST_CHECK_VERSION(1,1,0)
272     case GST_VAAPI_DISPLAY_TYPE_X11:
273       func = (GFunc) gst_vaapi_video_converter_x11_new;
274       break;
275 #endif
276 #if USE_GLX && !GST_CHECK_VERSION(1,1,0)
277     case GST_VAAPI_DISPLAY_TYPE_GLX:
278       func = (GFunc) gst_vaapi_video_converter_glx_new;
279       break;
280 #endif
281     default:
282       func = NULL;
283       break;
284   }
285   return func;
286 }
287
288 static GstBuffer *
289 new_vbuffer (GstVaapiVideoMeta * meta)
290 {
291   GstBuffer *buffer;
292
293   g_return_val_if_fail (meta != NULL, NULL);
294
295   gst_vaapi_video_meta_set_surface_converter (meta,
296       get_surface_converter (gst_vaapi_video_meta_get_display (meta)));
297
298   buffer = gst_surface_buffer_new ();
299   if (buffer)
300     gst_buffer_set_vaapi_video_meta (buffer, meta);
301   gst_vaapi_video_meta_unref (meta);
302   return buffer;
303 }
304
305 GstBuffer *
306 gst_vaapi_video_buffer_new (GstVaapiVideoMeta * meta)
307 {
308   g_return_val_if_fail (meta != NULL, NULL);
309
310   return new_vbuffer (gst_vaapi_video_meta_ref (meta));
311 }
312
313 GstBuffer *
314 gst_vaapi_video_buffer_new_empty (void)
315 {
316   return gst_surface_buffer_new ();
317 }
318
319 GstBuffer *
320 gst_vaapi_video_buffer_new_from_pool (GstVaapiVideoPool * pool)
321 {
322   return new_vbuffer (gst_vaapi_video_meta_new_from_pool (pool));
323 }
324
325 GstBuffer *
326 gst_vaapi_video_buffer_new_from_buffer (GstBuffer * buffer)
327 {
328   GstVaapiVideoMeta *const meta = gst_buffer_get_vaapi_video_meta (buffer);
329
330   return meta ? new_vbuffer (gst_vaapi_video_meta_ref (meta)) : NULL;
331 }
332
333 GstBuffer *
334 gst_vaapi_video_buffer_new_with_image (GstVaapiImage * image)
335 {
336   return new_vbuffer (gst_vaapi_video_meta_new_with_image (image));
337 }
338
339 GstBuffer *
340 gst_vaapi_video_buffer_new_with_surface_proxy (GstVaapiSurfaceProxy * proxy)
341 {
342   return new_vbuffer (gst_vaapi_video_meta_new_with_surface_proxy (proxy));
343 }