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"
26 #include <tbm_surface_internal.h>
28 GST_DEBUG_CATEGORY_STATIC (gst_tizen_vidbufpool_debug);
29 #define GST_CAT_DEFAULT gst_tizen_vidbufpool_debug
31 static GQuark gst_tizen_buffer_data_quark = 0;
33 static void gst_tizen_buffer_pool_finalize (GObject * object);
36 GST_DEBUG_CATEGORY_INIT (gst_tizen_vidbufpool_debug, "tizenvideopool", 0, \
39 #define gst_tizen_buffer_pool_parent_class parent_class
40 G_DEFINE_TYPE_WITH_CODE (GstTizenBufferPool, gst_tizen_buffer_pool,
41 GST_TYPE_BUFFER_POOL, DEBUG_INIT);
43 struct _GstTizenBufferPoolPrivate
45 GstAllocator *allocator;
49 gst_tizen_buffer_pool_get_options (GstBufferPool * pool)
51 static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META,
52 GST_BUFFER_POOL_OPTION_TIZEN_META, NULL
59 gst_tizen_buffer_pool_set_config (GstBufferPool * pool,
60 GstStructure * config)
62 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (pool);
66 tbm_surface_h surface;
67 guint min_buffers, max_buffers;
70 if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers, &max_buffers))
76 /* now parse the caps from the config */
77 if (!gst_video_info_from_caps (&info, caps))
80 if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_UNKNOWN)
85 format = gst_video_format_to_tbm_format (GST_VIDEO_INFO_FORMAT (&info));
87 surface = tbm_surface_create (GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), format);
88 size = tbm_surface_internal_get_size (surface);
90 tbm_surface_destroy (surface);
92 /* enable metadata based on config of the pool */
93 _tpool->add_videometa = gst_buffer_pool_config_has_option (config,
94 GST_BUFFER_POOL_OPTION_VIDEO_META);
96 /* parse extra alignment info */
97 _tpool->add_tizenmeta = gst_buffer_pool_config_has_option (config,
98 GST_BUFFER_POOL_OPTION_TIZEN_META);
100 gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
103 GST_DEBUG_OBJECT (_tpool, "min : %u, max : %u, size : %d", min_buffers, max_buffers, size);
104 return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
109 GST_WARNING_OBJECT (pool, "invalid config");
114 GST_WARNING_OBJECT (pool, "no caps in config");
119 GST_WARNING_OBJECT (pool,
120 "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
125 GST_WARNING_OBJECT (_tpool, "failed to get format from caps %"
126 GST_PTR_FORMAT, caps);
127 GST_ELEMENT_ERROR (_tpool, RESOURCE, WRITE,
128 ("Failed to create output image buffer of %dx%d pixels",
129 info.width, info.height),
131 ("Invalid input caps %" GST_PTR_FORMAT, caps));
137 _destroy_tbm_surface (tbm_surface_h surface)
139 GST_DEBUG ("destroy surface %p", surface);
140 tbm_surface_internal_destroy (surface);
143 /* This function handles GstBuffer creation */
145 gst_tizen_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
146 GstBufferPoolAcquireParams * params)
148 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (pool);
151 GstMemory *tizen_mem;
152 gsize offsets[4] = {0, };
154 GST_DEBUG_OBJECT (pool, "gst_tizen_buffer_pool_alloc");
155 info = &_tpool->info;
157 if (!(buf = gst_buffer_new ()))
160 GST_DEBUG_OBJECT (pool, "buffer new :%dx%d : %p", GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), buf);
161 if (!(tizen_mem = gst_tizen_allocator_alloc ((GstAllocator *)_tpool->allocator, info)))
162 goto mem_create_failed;
164 gst_buffer_append_memory (buf, tizen_mem);
166 GST_DEBUG_OBJECT (pool, "mem allocated : %p, %dx%d n_plane : %d",
167 buf, GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), GST_VIDEO_INFO_N_PLANES (info));
169 if (_tpool->add_videometa) {
172 GST_DEBUG_OBJECT (pool, "adding GstVideoMeta");
173 /* these are just the defaults for now */
175 vmeta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
176 GST_VIDEO_INFO_FORMAT (info),
177 GST_VIDEO_INFO_WIDTH (info),
178 GST_VIDEO_INFO_HEIGHT (info),
179 GST_VIDEO_INFO_N_PLANES (info), offsets, info->stride);
181 vmeta->map = gst_tizen_video_meta_map;
182 vmeta->unmap = gst_tizen_video_meta_unmap;
185 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
186 gst_tizen_buffer_data_quark, gst_tizen_memory_get_surface (tizen_mem), (GDestroyNotify) _destroy_tbm_surface);
189 g_ptr_array_add (_tpool->buffers, buf);
190 g_atomic_int_inc (&_tpool->current_buffer_index);
191 g_atomic_int_inc (&_tpool->outstandings);
198 GST_WARNING_OBJECT (pool, "Couldn't create buffer");
199 return GST_FLOW_ERROR;
204 GST_WARNING_OBJECT (pool, "Couldn't create GstTizen Memory");
205 return GST_FLOW_ERROR;
211 gst_tizen_buffer_pool_acquire_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
212 GstBufferPoolAcquireParams * params)
215 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
216 GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
219 ret = pclass->acquire_buffer (bpool, buffer, params);
220 if (ret != GST_FLOW_OK) {
221 GST_WARNING_OBJECT (_tpool, "Couldn't acquire buffer");
225 n = _tpool->buffers->len;
226 for (i = 0; i < n; i++) {
227 GstBuffer *tmp = g_ptr_array_index (_tpool->buffers, i);
233 g_atomic_int_set(&_tpool->current_buffer_index, i);
235 GST_BUFFER_TIMESTAMP (*buffer) = GST_CLOCK_TIME_NONE;
236 GST_BUFFER_OFFSET (*buffer) = GST_BUFFER_OFFSET_NONE;
237 GST_BUFFER_OFFSET_END (*buffer) = GST_BUFFER_OFFSET_NONE;
239 g_atomic_int_inc (&_tpool->outstandings);
241 g_mutex_lock (&_tpool->lock);
242 _tpool->empty = FALSE;
243 g_mutex_unlock (&_tpool->lock);
245 GST_DEBUG_OBJECT (_tpool, "acquire buffer %p, current index %d, num_live_buffer %d", *buffer, i, _tpool->outstandings);
251 gst_tizen_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
253 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
255 GST_BUFFER_POOL_CLASS (gst_tizen_buffer_pool_parent_class)->release_buffer (bpool, buffer);
257 if (g_atomic_int_dec_and_test(&_tpool->outstandings)) {
258 g_mutex_lock (&_tpool->lock);
259 _tpool->empty = TRUE;
260 g_mutex_unlock (&_tpool->lock);
262 GST_DEBUG_OBJECT (_tpool, "release buffer %p, outstandings %d", buffer, _tpool->outstandings);
266 gst_tizen_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
268 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (bpool);
269 GST_DEBUG_OBJECT (_tpool, "free buffer %p, %d", buffer, _tpool->outstandings);
271 gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
272 gst_tizen_buffer_data_quark, NULL, NULL);
274 GST_BUFFER_POOL_CLASS (gst_tizen_buffer_pool_parent_class)->free_buffer (bpool,
279 gst_tizen_buffer_pool_dispose (GObject * object)
281 GstTizenBufferPool *_tpool = GST_TIZEN_BUFFER_POOL_CAST (object);
283 if (_tpool->allocator) {
284 gst_object_unref (_tpool->allocator);
285 _tpool->allocator = NULL;
288 if (_tpool->buffers) {
289 g_ptr_array_unref (_tpool->buffers);
290 _tpool->buffers = NULL;
293 GST_DEBUG_OBJECT (_tpool, "dispose pool");
294 G_OBJECT_CLASS (parent_class)->dispose (object);
298 gst_tizen_buffer_pool_finalize (GObject * object)
300 GstTizenBufferPool *pool = GST_TIZEN_BUFFER_POOL_CAST (object);
303 g_mutex_clear (&pool->lock);
305 G_OBJECT_CLASS (gst_tizen_buffer_pool_parent_class)->finalize (object);
309 gst_tizen_buffer_pool_init (GstTizenBufferPool * pool)
311 g_mutex_init (&pool->lock);
312 pool->priv = gst_tizen_buffer_pool_get_instance_private (pool);
313 pool->buffers = g_ptr_array_new ();
314 pool->allocator = gst_tizen_allocator_new ();
315 g_atomic_int_set(&pool->outstandings, 0);
316 GST_LOG_OBJECT (pool, "Tizen buffer pool init %p", pool);
320 gst_tizen_buffer_pool_class_init (GstTizenBufferPoolClass * klass)
322 GObjectClass *gobject_class = (GObjectClass *) klass;
323 GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
325 gst_tizen_buffer_data_quark = g_quark_from_static_string ("GstTizenBufferData");
327 gobject_class->dispose = gst_tizen_buffer_pool_dispose;
328 gobject_class->finalize = gst_tizen_buffer_pool_finalize;
330 gstbufferpool_class->get_options = gst_tizen_buffer_pool_get_options;
331 gstbufferpool_class->set_config = gst_tizen_buffer_pool_set_config;
332 gstbufferpool_class->alloc_buffer = gst_tizen_buffer_pool_alloc;
333 gstbufferpool_class->free_buffer = gst_tizen_buffer_pool_free_buffer;
334 gstbufferpool_class->acquire_buffer = gst_tizen_buffer_pool_acquire_buffer;
335 gstbufferpool_class->release_buffer = gst_tizen_buffer_pool_release_buffer;
339 gst_tizen_buffer_pool_new (void)
341 return GST_BUFFER_POOL_CAST (g_object_new (GST_TYPE_TIZEN_BUFFER_POOL, NULL));