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