2 * GStreamer tizen buffer pool
3 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Author: Sejun Park <sejun79.park@samsung.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
25 #include "gsttizenbufferpool.h"
27 GST_DEBUG_CATEGORY_STATIC (gst_tizen_vidbufpool_debug);
28 #define GST_CAT_DEFAULT gst_tizen_vidbufpool_debug
30 static GQuark gst_tizen_buffer_data_quark = 0;
32 static void gst_tizen_buffer_pool_finalize (GObject * object);
35 GST_DEBUG_CATEGORY_INIT (gst_tizen_vidbufpool_debug, "tizenvideopool", 0, \
38 #define gst_tizen_buffer_pool_parent_class parent_class
39 G_DEFINE_TYPE_WITH_CODE (GstTizenBufferPool, gst_tizen_buffer_pool,
40 GST_TYPE_BUFFER_POOL, DEBUG_INIT);
42 struct _GstTizenBufferPoolPrivate
44 GstAllocator *allocator;
48 gst_tizen_buffer_pool_get_options (GstBufferPool * pool)
50 static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META,
51 GST_BUFFER_POOL_OPTION_TIZEN_META, NULL
58 gst_tizen_buffer_pool_set_config (GstBufferPool * pool,
59 GstStructure * config)
61 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (pool);
65 tbm_surface_h surface;
66 guint min_buffers, max_buffers;
69 if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers))
75 /* now parse the caps from the config */
76 if (!gst_video_info_from_caps (&info, caps))
79 if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_UNKNOWN)
84 format = gst_video_format_to_tbm_format (GST_VIDEO_INFO_FORMAT (&info));
86 surface = tbm_surface_create (GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), format);
87 size = tbm_surface_internal_get_size (surface);
89 tbm_surface_destroy (surface);
91 /* enable metadata based on config of the pool */
92 _tpool->add_videometa = gst_buffer_pool_config_has_option (config,
93 GST_BUFFER_POOL_OPTION_VIDEO_META);
95 /* parse extra alignment info */
96 _tpool->add_tizenmeta = gst_buffer_pool_config_has_option (config,
97 GST_BUFFER_POOL_OPTION_TIZEN_META);
99 gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
102 GST_DEBUG_OBJECT (_tpool, "min : %u, max : %u, size : %d", min_buffers, max_buffers, size);
103 return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
108 GST_WARNING_OBJECT (pool, "invalid config");
113 GST_WARNING_OBJECT (pool, "no caps in config");
118 GST_WARNING_OBJECT (pool,
119 "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
124 GST_WARNING_OBJECT (_tpool, "failed to get format from caps %"
125 GST_PTR_FORMAT, caps);
126 GST_ELEMENT_ERROR (_tpool, RESOURCE, WRITE,
127 ("Failed to create output image buffer of %dx%d pixels",
128 info.width, info.height),
130 ("Invalid input caps %" GST_PTR_FORMAT, caps));
136 _destroy_tbm_surface (struct UserPtrData *data)
138 GST_DEBUG ("destroy surface %p", data);
139 tbm_surface_internal_destroy ((tbm_surface_h)data);
142 /* This function handles GstBuffer creation */
144 gst_tizen_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
145 GstBufferPoolAcquireParams * params)
147 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (pool);
150 GstMemory *tizen_mem;
151 gint offsets[4] = {0, };
153 GST_DEBUG_OBJECT (pool, "gst_tizen_buffer_pool_alloc");
154 info = &_tpool->info;
156 if (!(buf = gst_buffer_new ()))
159 GST_DEBUG_OBJECT (pool, "buffer new :%dx%d : %p", GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), buf);
160 if (!(tizen_mem = gst_tizen_allocator_alloc ((GstAllocator *)_tpool->allocator, info)))
161 goto mem_create_failed;
163 gst_buffer_append_memory (buf, tizen_mem);
165 GST_DEBUG_OBJECT (pool, "mem allocated : %p, %dx%d n_plane : %d",
166 buf, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info));
168 if (_tpool->add_videometa) {
171 GST_DEBUG_OBJECT (pool, "adding GstVideoMeta");
172 /* these are just the defaults for now */
174 vmeta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
175 GST_VIDEO_INFO_FORMAT (info),
176 GST_VIDEO_INFO_WIDTH (info),
177 GST_VIDEO_INFO_HEIGHT (info),
178 GST_VIDEO_INFO_N_PLANES (info), offsets, info->stride);
180 vmeta->map = gst_tizen_video_memory_map;
181 vmeta->unmap = gst_tizen_video_memory_unmap;
184 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
185 gst_tizen_buffer_data_quark, gst_tizen_memory_get_surface (tizen_mem), (GDestroyNotify) _destroy_tbm_surface);
188 g_ptr_array_add (_tpool->buffers, buf);
189 g_atomic_int_inc (&_tpool->current_buffer_index);
190 g_atomic_int_inc (&_tpool->outstandings);
197 GST_WARNING_OBJECT (pool, "Couldn't create buffer");
198 return GST_FLOW_ERROR;
203 GST_WARNING_OBJECT (pool, "Couldn't create GstTizen Memory");
204 return GST_FLOW_ERROR;
210 gst_tizen_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
211 GstBufferPoolAcquireParams * params)
214 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
215 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
218 ret = pclass->acquire_buffer (bpool, buffer, params);
219 if (ret != GST_FLOW_OK) {
220 GST_WARNING_OBJECT (_tpool, "Couldn't acquire buffer");
224 n = _tpool->buffers->len;
225 for (i = 0; i < n; i++) {
226 GstBuffer *tmp = g_ptr_array_index (_tpool->buffers, i);
232 g_atomic_int_set(&_tpool->current_buffer_index, i);
234 GST_BUFFER_TIMESTAMP (*buffer) = GST_CLOCK_TIME_NONE;
235 GST_BUFFER_OFFSET (*buffer) = GST_BUFFER_OFFSET_NONE;
236 GST_BUFFER_OFFSET_END (*buffer) = GST_BUFFER_OFFSET_NONE;
238 g_atomic_int_inc (&_tpool->outstandings);
240 g_mutex_lock (&_tpool->lock);
241 _tpool->empty = FALSE;
242 g_mutex_unlock (&_tpool->lock);
244 GST_DEBUG_OBJECT (_tpool, "acquire buffer %p, current index %d, num_live_buffer %d", *buffer, i, _tpool->outstandings);
250 gst_tizen_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
252 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
254 GST_BUFFER_POOL_CLASS (gst_tizen_buffer_pool_parent_class)->release_buffer (bpool, buffer);
256 if (g_atomic_int_dec_and_test(&_tpool->outstandings)) {
257 g_mutex_lock (&_tpool->lock);
258 _tpool->empty = TRUE;
259 g_mutex_unlock (&_tpool->lock);
261 GST_DEBUG_OBJECT (_tpool, "release buffer %p, outstandings %d", buffer, _tpool->outstandings);
265 gst_tizen_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
267 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
268 GST_DEBUG_OBJECT (_tpool, "free buffer %p, %d", buffer, _tpool->outstandings);
270 gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
271 gst_tizen_buffer_data_quark, NULL, NULL);
273 GST_BUFFER_POOL_CLASS (gst_tizen_buffer_pool_parent_class)->free_buffer (bpool,
278 gst_tizen_buffer_pool_dispose (GObject * object)
280 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (object);
282 if (_tpool->allocator) {
283 gst_object_unref (_tpool->allocator);
284 _tpool->allocator = NULL;
287 if (_tpool->buffers) {
288 g_ptr_array_unref (_tpool->buffers);
289 _tpool->buffers = NULL;
292 GST_DEBUG_OBJECT (_tpool, "dispose pool");
293 G_OBJECT_CLASS (parent_class)->dispose (object);
297 gst_tizen_buffer_pool_finalize (GObject * object)
299 GstTizenBufferPool *pool = GST_TIZEN_BUFFER_POOL_CAST (object);
302 g_mutex_clear (&pool->lock);
304 G_OBJECT_CLASS (gst_tizen_buffer_pool_parent_class)->finalize (object);
308 gst_tizen_buffer_pool_new ()
310 return GST_BUFFER_POOL_CAST (g_object_new (GST_TYPE_TIZEN_BUFFER_POOL, NULL));
314 gst_tizen_buffer_pool_class_init (GstTizenBufferPoolClass * klass)
316 GObjectClass *gobject_class = (GObjectClass *) klass;
317 GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
319 gst_tizen_buffer_data_quark = g_quark_from_static_string ("GstTizenBufferData");
321 gobject_class->dispose = gst_tizen_buffer_pool_dispose;
322 gobject_class->finalize = gst_tizen_buffer_pool_finalize;
324 gstbufferpool_class->get_options = gst_tizen_buffer_pool_get_options;
325 gstbufferpool_class->set_config = gst_tizen_buffer_pool_set_config;
326 gstbufferpool_class->alloc_buffer = gst_tizen_buffer_pool_alloc;
327 gstbufferpool_class->free_buffer = gst_tizen_buffer_pool_free_buffer;
328 gstbufferpool_class->acquire_buffer = gst_tizen_buffer_pool_acquire_buffer;
329 gstbufferpool_class->release_buffer = gst_tizen_buffer_pool_release_buffer;
333 gst_tizen_buffer_pool_init (GstTizenBufferPool * pool)
335 g_mutex_init (&pool->lock);
336 pool->priv = gst_tizen_buffer_pool_get_instance_private (pool);
337 pool->buffers = g_ptr_array_new ();
338 pool->allocator = gst_tizen_allocator_new ();
339 g_atomic_int_set(&pool->outstandings, 0);
340 GST_LOG_OBJECT (pool, "Tizen buffer pool init %p", pool);