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