plugins: cope with new GstVaapiMiniObject objects.
[platform/upstream/gstreamer-vaapi.git] / gst / vaapi / gstvaapivideobufferpool.c
1 /*
2  *  gstvaapivideobufferpool.c - Gstreamer/VA video buffer pool
3  *
4  *  Copyright (C) 2013 Intel Corporation
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public License
8  *  as published by the Free Software Foundation; either version 2.1
9  *  of the License, or (at your option) any later version.
10  *
11  *  This library 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 GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301 USA
20  */
21
22 #include "gst/vaapi/sysdeps.h"
23 #include "gstvaapivideobufferpool.h"
24 #include "gstvaapivideobuffer.h"
25 #include "gstvaapivideomemory.h"
26
27 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapivideopool);
28 #define GST_CAT_DEFAULT gst_debug_vaapivideopool
29
30 G_DEFINE_TYPE(GstVaapiVideoBufferPool,
31               gst_vaapi_video_buffer_pool,
32               GST_TYPE_BUFFER_POOL)
33
34 enum {
35     PROP_0,
36
37     PROP_DISPLAY,
38 };
39
40 struct _GstVaapiVideoBufferPoolPrivate {
41     GstAllocator       *allocator;
42     GstVaapiDisplay    *display;
43     guint               has_video_meta  : 1;
44 };
45
46 #define GST_VAAPI_VIDEO_BUFFER_POOL_GET_PRIVATE(obj)    \
47     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                 \
48         GST_VAAPI_TYPE_VIDEO_BUFFER_POOL,               \
49         GstVaapiVideoBufferPoolPrivate))
50
51 static void
52 gst_vaapi_video_buffer_pool_finalize(GObject *object)
53 {
54     GstVaapiVideoBufferPoolPrivate * const priv =
55         GST_VAAPI_VIDEO_BUFFER_POOL(object)->priv;
56
57     G_OBJECT_CLASS(gst_vaapi_video_buffer_pool_parent_class)->finalize(object);
58
59     gst_vaapi_display_replace(&priv->display, NULL);
60     g_clear_object(&priv->allocator);
61 }
62
63 static void
64 gst_vaapi_video_buffer_pool_set_property(GObject *object, guint prop_id,
65     const GValue *value, GParamSpec *pspec)
66 {
67     GstVaapiVideoBufferPoolPrivate * const priv =
68         GST_VAAPI_VIDEO_BUFFER_POOL(object)->priv;
69
70     switch (prop_id) {
71     case PROP_DISPLAY:
72         priv->display = gst_vaapi_display_ref(g_value_get_pointer(value));
73         break;
74     default:
75         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
76         break;
77     }
78 }
79
80 static void
81 gst_vaapi_video_buffer_pool_get_property(GObject *object, guint prop_id,
82     GValue *value, GParamSpec *pspec)
83 {
84     GstVaapiVideoBufferPoolPrivate * const priv =
85         GST_VAAPI_VIDEO_BUFFER_POOL(object)->priv;
86
87     switch (prop_id) {
88     case PROP_DISPLAY:
89         g_value_set_pointer(value, priv->display);
90         break;
91     default:
92         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
93         break;
94     }
95 }
96
97 static const gchar **
98 gst_vaapi_video_buffer_pool_get_options(GstBufferPool *pool)
99 {
100     static const gchar *g_options[] = {
101         GST_BUFFER_POOL_OPTION_VIDEO_META,
102         GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META,
103         NULL,
104     };
105     return g_options;
106 }
107
108 static gboolean
109 gst_vaapi_video_buffer_pool_set_config(GstBufferPool *pool,
110     GstStructure *config)
111 {
112     GstVaapiVideoBufferPoolPrivate * const priv =
113         GST_VAAPI_VIDEO_BUFFER_POOL(pool)->priv;
114     GstCaps *caps = NULL;
115
116     if (!gst_buffer_pool_config_get_params(config, &caps, NULL, NULL, NULL))
117         goto error_invalid_config;
118     if (!caps)
119         goto error_no_caps;
120
121     g_clear_object(&priv->allocator);
122     priv->allocator = gst_vaapi_video_allocator_new(priv->display, caps);
123     if (!priv->allocator)
124         goto error_create_allocator;
125
126     if (!gst_buffer_pool_config_has_option(config,
127             GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META))
128         goto error_no_vaapi_video_meta_option;
129
130     priv->has_video_meta = gst_buffer_pool_config_has_option(config,
131         GST_BUFFER_POOL_OPTION_VIDEO_META);
132
133     return GST_BUFFER_POOL_CLASS(gst_vaapi_video_buffer_pool_parent_class)->
134         set_config(pool, config);
135
136     /* ERRORS */
137 error_invalid_config:
138     {
139         GST_ERROR("invalid config");
140         return FALSE;
141     }
142 error_no_caps:
143     {
144         GST_ERROR("no caps in config");
145         return FALSE;
146     }
147 error_create_allocator:
148     {
149         GST_ERROR("failed to create GstVaapiVideoAllocator object");
150         return FALSE;
151     }
152 error_no_vaapi_video_meta_option:
153     {
154         GST_ERROR("no GstVaapiVideoMeta option");
155         return FALSE;
156     }
157 }
158
159 static GstFlowReturn
160 gst_vaapi_video_buffer_pool_alloc_buffer(GstBufferPool *pool,
161     GstBuffer **out_buffer_ptr, GstBufferPoolAcquireParams *params)
162 {
163     GstVaapiVideoBufferPoolPrivate * const priv =
164         GST_VAAPI_VIDEO_BUFFER_POOL(pool)->priv;
165     GstVaapiVideoMeta *meta;
166     GstMemory *mem;
167     GstBuffer *buffer;
168
169     if (!priv->allocator)
170         goto error_no_allocator;
171
172     meta = gst_vaapi_video_meta_new(priv->display);
173     if (!meta)
174         goto error_create_meta;
175
176     buffer = gst_vaapi_video_buffer_new(meta);
177     if (!buffer)
178         goto error_create_buffer;
179
180     mem = gst_vaapi_video_memory_new(priv->allocator, meta);
181     if (!mem)
182         goto error_create_memory;
183     gst_vaapi_video_meta_unref(meta);
184     gst_buffer_append_memory(buffer, mem);
185
186     if (priv->has_video_meta) {
187         GstVideoInfo * const vip =
188             &GST_VAAPI_VIDEO_ALLOCATOR_CAST(priv->allocator)->image_info;
189         GstVideoMeta *vmeta;
190
191         vmeta = gst_buffer_add_video_meta_full(buffer, 0,
192             GST_VIDEO_INFO_FORMAT(vip), GST_VIDEO_INFO_WIDTH(vip),
193             GST_VIDEO_INFO_HEIGHT(vip), GST_VIDEO_INFO_N_PLANES(vip),
194             &GST_VIDEO_INFO_PLANE_OFFSET(vip, 0),
195             &GST_VIDEO_INFO_PLANE_STRIDE(vip, 0));
196         vmeta->map = gst_video_meta_map_vaapi_memory;
197         vmeta->unmap = gst_video_meta_unmap_vaapi_memory;
198     }
199
200     *out_buffer_ptr = buffer;
201     return GST_FLOW_OK;
202
203     /* ERRORS */
204 error_no_allocator:
205     {
206         GST_ERROR("no GstAllocator in buffer pool");
207         return GST_FLOW_ERROR;
208     }
209 error_create_meta:
210     {
211         GST_ERROR("failed to allocate vaapi video meta");
212         return GST_FLOW_ERROR;
213     }
214 error_create_buffer:
215     {
216         GST_ERROR("failed to create video buffer");
217         gst_vaapi_video_meta_unref(meta);
218         return GST_FLOW_ERROR;
219     }
220 error_create_memory:
221     {
222         GST_ERROR("failed to create video memory");
223         gst_buffer_unref(buffer);
224         gst_vaapi_video_meta_unref(meta);
225         return GST_FLOW_ERROR;
226     }
227 }
228
229 static void
230 gst_vaapi_video_buffer_pool_reset_buffer(GstBufferPool *pool, GstBuffer *buffer)
231 {
232     GstVaapiVideoMeta * const meta = gst_buffer_get_vaapi_video_meta(buffer);
233
234     /* Release the underlying surface proxy */
235     gst_vaapi_video_meta_set_surface_proxy(meta, NULL);
236
237     GST_BUFFER_POOL_CLASS(gst_vaapi_video_buffer_pool_parent_class)->
238         reset_buffer(pool, buffer);
239 }
240
241 static void
242 gst_vaapi_video_buffer_pool_class_init(GstVaapiVideoBufferPoolClass *klass)
243 {
244     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
245     GstBufferPoolClass * const pool_class = GST_BUFFER_POOL_CLASS(klass);
246
247     GST_DEBUG_CATEGORY_INIT(gst_debug_vaapivideopool,
248         "vaapivideopool", 0, "VA-API video pool");
249
250     g_type_class_add_private(klass, sizeof(GstVaapiVideoBufferPoolPrivate));
251
252     object_class->finalize      = gst_vaapi_video_buffer_pool_finalize;
253     object_class->set_property  = gst_vaapi_video_buffer_pool_set_property;
254     object_class->get_property  = gst_vaapi_video_buffer_pool_get_property;
255     pool_class->get_options     = gst_vaapi_video_buffer_pool_get_options;
256     pool_class->set_config      = gst_vaapi_video_buffer_pool_set_config;
257     pool_class->alloc_buffer    = gst_vaapi_video_buffer_pool_alloc_buffer;
258     pool_class->reset_buffer    = gst_vaapi_video_buffer_pool_reset_buffer;
259
260     /**
261      * GstVaapiVideoBufferPool:display:
262      *
263      * The #GstVaapiDisplay this object is bound to.
264      */
265     g_object_class_install_property
266         (object_class,
267          PROP_DISPLAY,
268          g_param_spec_pointer("display",
269                              "Display",
270                              "The GstVaapiDisplay to use for this video pool",
271                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
272 }
273
274 static void
275 gst_vaapi_video_buffer_pool_init(GstVaapiVideoBufferPool *pool)
276 {
277     GstVaapiVideoBufferPoolPrivate * const priv =
278         GST_VAAPI_VIDEO_BUFFER_POOL_GET_PRIVATE(pool);
279
280     pool->priv = priv;
281 }
282
283 GstBufferPool *
284 gst_vaapi_video_buffer_pool_new(GstVaapiDisplay *display)
285 {
286     return g_object_new(GST_VAAPI_TYPE_VIDEO_BUFFER_POOL,
287         "display", display, NULL);
288 }