bufferpool: use GstStructure to configure the pool
[platform/upstream/gstreamer.git] / gst / gstbufferpool.c
1 /* GStreamer
2  * Copyright (C) 2010 Wim Taymans <wim.taymans@gmail.com>
3  *
4  * gstbufferpool.c: GstBufferPool baseclass
5  *
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.
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  * Library General Public License for more details.
15  *
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.
20  */
21
22 /**
23  * SECTION:gstbufferpool
24  * @short_description: Pool for buffers
25  * @see_also: #GstBuffer
26  *
27  */
28
29 #include "gst_private.h"
30
31 #include <errno.h>
32 #ifdef HAVE_UNISTD_H
33 #  include <unistd.h>
34 #endif
35 #include <sys/types.h>
36
37 #include "gstinfo.h"
38
39 #include "gstbufferpool.h"
40
41
42 #define GST_BUFFER_POOL_GET_PRIVATE(obj)  \
43    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BUFFER_POOL, GstBufferPoolPrivate))
44
45 struct _GstBufferPoolPrivate
46 {
47   guint min_buffers;
48   guint max_buffers;
49   guint size;
50   guint prefix;
51   guint postfix;
52   guint align;
53 };
54
55 enum
56 {
57   /* add more above */
58   LAST_SIGNAL
59 };
60
61 static void gst_buffer_pool_finalize (GObject * object);
62
63 G_DEFINE_TYPE (GstBufferPool, gst_buffer_pool, GST_TYPE_OBJECT);
64
65 static void default_set_flushing (GstBufferPool * pool, gboolean flushing);
66 static gboolean default_set_config (GstBufferPool * pool,
67     GstStructure * config);
68 static GstFlowReturn default_alloc_buffer (GstBufferPool * pool,
69     GstBuffer ** buffer, GstBufferPoolParams * params);
70 static GstFlowReturn default_acquire_buffer (GstBufferPool * pool,
71     GstBuffer ** buffer, GstBufferPoolParams * params);
72 static void default_free_buffer (GstBufferPool * pool, GstBuffer * buffer);
73 static void default_release_buffer (GstBufferPool * pool, GstBuffer * buffer);
74
75 static void
76 gst_buffer_pool_class_init (GstBufferPoolClass * klass)
77 {
78   GObjectClass *gobject_class = (GObjectClass *) klass;
79
80   gobject_class->finalize = gst_buffer_pool_finalize;
81
82   klass->set_flushing = default_set_flushing;
83   klass->set_config = default_set_config;
84   klass->acquire_buffer = default_acquire_buffer;
85   klass->alloc_buffer = default_alloc_buffer;
86   klass->release_buffer = default_release_buffer;
87   klass->free_buffer = default_free_buffer;
88 }
89
90 static void
91 gst_buffer_pool_init (GstBufferPool * pool)
92 {
93   pool->priv = GST_BUFFER_POOL_GET_PRIVATE (pool);
94
95   pool->config = gst_structure_new ("GstBufferPoolConfig",
96       "size", G_TYPE_UINT, 0,
97       "min-buffers", G_TYPE_UINT, 0,
98       "max-buffers", G_TYPE_UINT, 0,
99       "prefix", G_TYPE_UINT, 0,
100       "postfix", G_TYPE_UINT, 0, "align", G_TYPE_UINT, 1, NULL);
101   pool->poll = gst_poll_new_timer ();
102   pool->queue = gst_atomic_queue_new (10);
103   default_set_flushing (pool, TRUE);
104
105   GST_DEBUG_OBJECT (pool, "created");
106 }
107
108 static void
109 gst_buffer_pool_finalize (GObject * object)
110 {
111   G_OBJECT_CLASS (gst_buffer_pool_parent_class)->finalize (object);
112 }
113
114 /**
115  * gst_buffer_pool_new:
116  *
117  * Creates a new #GstBufferPool instance.
118  *
119  * Returns: a new #GstBufferPool instance
120  */
121 GstBufferPool *
122 gst_buffer_pool_new (void)
123 {
124   GstBufferPool *result;
125
126   result = g_object_newv (GST_TYPE_BUFFER_POOL, 0, NULL);
127   GST_DEBUG_OBJECT (result, "created new buffer pool");
128
129   return result;
130 }
131
132 static void
133 flush_buffers (GstBufferPool * pool)
134 {
135   GstBuffer *buffer;
136   GstBufferPoolClass *pclass;
137
138   pclass = GST_BUFFER_POOL_GET_CLASS (pool);
139
140   while ((buffer = gst_atomic_queue_pop (pool->queue))) {
141     gst_poll_read_control (pool->poll);
142     if (G_LIKELY (pclass->free_buffer))
143       pclass->free_buffer (pool, buffer);
144   }
145 }
146
147 static void
148 default_set_flushing (GstBufferPool * pool, gboolean flushing)
149 {
150   g_atomic_int_set (&pool->flushing, flushing);
151
152   if (flushing) {
153     /* write the control socket so that waiters get woken up and can check the
154      * flushing flag we set above */
155     gst_poll_write_control (pool->poll);
156     flush_buffers (pool);
157   } else {
158     gst_poll_read_control (pool->poll);
159   }
160 }
161
162 /**
163  * gst_buffer_pool_set_flushing:
164  * @pool: a #GstBufferPool
165  * @flushing: the new flushing state
166  *
167  * Control the flushing state of @pool. When the pool is flushing, new calls to
168  * gst_buffer_pool_acquire_buffer() will return with GST_FLOW_WRONG_STATE.
169  */
170 void
171 gst_buffer_pool_set_flushing (GstBufferPool * pool, gboolean flushing)
172 {
173   GstBufferPoolClass *pclass;
174
175   g_return_if_fail (GST_IS_BUFFER_POOL (pool));
176
177   pclass = GST_BUFFER_POOL_GET_CLASS (pool);
178
179   if (G_LIKELY (pclass->set_flushing))
180     pclass->set_flushing (pool, flushing);
181 }
182
183 static gboolean
184 default_set_config (GstBufferPool * pool, GstStructure * config)
185 {
186   guint i;
187   GstBufferPoolClass *pclass;
188   GstBufferPoolPrivate *priv = pool->priv;
189
190   pclass = GST_BUFFER_POOL_GET_CLASS (pool);
191
192   /* parse the config and keep around */
193   gst_buffer_pool_config_get (config, &priv->size, &priv->min_buffers,
194       &priv->max_buffers, &priv->prefix, &priv->postfix, &priv->align);
195
196   /* we need to prealloc buffers */
197   for (i = priv->min_buffers; i > 0; i--) {
198     GstBuffer *buffer;
199
200     if (G_LIKELY (pclass->alloc_buffer)) {
201       if (!pclass->alloc_buffer (pool, &buffer, NULL))
202         return FALSE;
203     } else
204       return FALSE;
205
206     /* store in the queue */
207     gst_atomic_queue_push (pool->queue, buffer);
208     gst_poll_write_control (pool->poll);
209   }
210
211   return TRUE;
212 }
213
214 /**
215  * gst_buffer_pool_set_config:
216  * @pool: a #GstBufferPool
217  * @config: a #GstStructure
218  *
219  * Set the configuration of the pool. The pool must be flushing or else this
220  * function will do nothing and return FALSE.
221  *
222  * @condfig is a #GstStructure that contains the configuration parameters for
223  * the pool. A default and mandatory set of parameters can be configured with
224  * gst_buffer_pool_config_set().
225  *
226  * Returns: TRUE when the configuration could be set.
227  */
228 gboolean
229 gst_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
230 {
231   gboolean result;
232   GstBufferPoolClass *pclass;
233
234   g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), FALSE);
235   g_return_val_if_fail (config != NULL, FALSE);
236
237   if (!g_atomic_int_get (&pool->flushing))
238     return FALSE;
239
240   pclass = GST_BUFFER_POOL_GET_CLASS (pool);
241
242   /* free the buffer when we are flushing */
243   if (G_LIKELY (pclass->set_config))
244     result = pclass->set_config (pool, config);
245   else
246     result = FALSE;
247
248   if (result) {
249     if (pool->config)
250       gst_structure_free (pool->config);
251     pool->config = config;
252   }
253
254   return result;
255 }
256
257 /**
258  * gst_buffer_pool_get_config:
259  * @pool: a #GstBufferPool
260  *
261  * Get the current configuration of the pool. This configuration is read-only,
262  * use gst_structure_copy() to make a writable copy.
263  */
264 const GstStructure *
265 gst_buffer_pool_get_config (GstBufferPool * pool)
266 {
267   g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), NULL);
268
269   return pool->config;
270 }
271
272
273 /**
274  * gst_buffer_pool_config_set:
275  * @pool: a #GstBufferPool
276  * @size: the size of each buffer, not including pre and post fix
277  * @min_buffers: the minimum amount of buffers to allocate.
278  * @max_buffers: the maximum amount of buffers to allocate or 0 for unlimited.
279  * @prefix: prefix each buffer with this many bytes
280  * @postfix: postfix each buffer with this many bytes
281  * @align: alignment of the buffer data.
282  *
283  * Configure @config with the given parameters.
284  */
285 void
286 gst_buffer_pool_config_set (GstStructure * config, guint size,
287     guint min_buffers, guint max_buffers, guint prefix, guint postfix,
288     guint align)
289 {
290   g_return_if_fail (config != NULL);
291
292   gst_structure_set (config,
293       "size", G_TYPE_UINT, size,
294       "min-buffers", G_TYPE_UINT, min_buffers,
295       "max-buffers", G_TYPE_UINT, max_buffers,
296       "prefix", G_TYPE_UINT, prefix,
297       "postfix", G_TYPE_UINT, postfix, "align", G_TYPE_UINT, align, NULL);
298 }
299
300 /**
301  * gst_buffer_pool_config_get:
302  * @pool: a #GstBufferPool
303  * @size: the size of each buffer, not including pre and post fix
304  * @min_buffers: the minimum amount of buffers to allocate.
305  * @max_buffers: the maximum amount of buffers to allocate or 0 for unlimited.
306  * @prefix: prefix each buffer with this many bytes
307  * @postfix: postfix each buffer with this many bytes
308  * @align: alignment of the buffer data.
309  *
310  * Get the configuration values from @config.
311  */
312 gboolean
313 gst_buffer_pool_config_get (GstStructure * config, guint * size,
314     guint * min_buffers, guint * max_buffers, guint * prefix, guint * postfix,
315     guint * align)
316 {
317   g_return_val_if_fail (config != NULL, FALSE);
318
319   return gst_structure_get (config,
320       "size", G_TYPE_UINT, size,
321       "min-buffers", G_TYPE_UINT, min_buffers,
322       "max-buffers", G_TYPE_UINT, max_buffers,
323       "prefix", G_TYPE_UINT, prefix,
324       "postfix", G_TYPE_UINT, postfix, "align", G_TYPE_UINT, align, NULL);
325 }
326
327 static GstFlowReturn
328 default_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
329     GstBufferPoolParams * params)
330 {
331   guint size, align;
332   GstBufferPoolPrivate *priv = pool->priv;
333
334   *buffer = gst_buffer_new ();
335
336   align = priv->align - 1;
337   size = priv->prefix + priv->postfix + priv->size + align;
338   if (size > 0) {
339     guint8 *memptr;
340
341     memptr = g_malloc (size);
342     GST_BUFFER_MALLOCDATA (*buffer) = memptr;
343     memptr = (guint8 *) ((guintptr) (memptr + align) & ~align);
344     GST_BUFFER_DATA (*buffer) = memptr + priv->prefix;
345     GST_BUFFER_SIZE (*buffer) = priv->size;
346   }
347
348   return GST_FLOW_OK;
349 }
350
351 static GstFlowReturn
352 default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
353     GstBufferPoolParams * params)
354 {
355   GstFlowReturn result;
356   GstBufferPoolClass *pclass;
357   GstBufferPoolPrivate *priv = pool->priv;
358
359   pclass = GST_BUFFER_POOL_GET_CLASS (pool);
360
361   while (TRUE) {
362     if (g_atomic_int_get (&pool->flushing))
363       return GST_FLOW_WRONG_STATE;
364
365     /* try to get a buffer from the queue */
366     *buffer = gst_atomic_queue_pop (pool->queue);
367     if (*buffer) {
368       /* FIXME check the size of the buffer */
369       gst_poll_read_control (pool->poll);
370       result = GST_FLOW_OK;
371       break;
372     }
373
374     /* no buffer */
375     if (priv->max_buffers == 0) {
376       /* no max_buffers, we allocate some more */
377       if (G_LIKELY (pclass->alloc_buffer))
378         result = pclass->alloc_buffer (pool, buffer, params);
379       else
380         result = GST_FLOW_NOT_SUPPORTED;
381       break;
382     }
383
384     /* check if we need to wait */
385     if (!(params->flags & GST_BUFFER_POOL_FLAG_WAIT)) {
386       result = GST_FLOW_UNEXPECTED;
387       break;
388     }
389
390     /* now wait */
391     gst_poll_wait (pool->poll, GST_CLOCK_TIME_NONE);
392   }
393   return result;
394 }
395
396 /**
397  * gst_buffer_pool_acquire_buffer:
398  * @pool: a #GstBufferPool
399  * @buffer: a location for a #GstBuffer
400  * @params: parameters.
401  *
402  * Acquire a buffer from @pool. @buffer should point to a memory location that
403  * can hold a pointer to the new buffer.
404  *
405  * @params can be NULL or contain optional parameters to influence the allocation.
406  *
407  * Returns: a #GstFlowReturn such as GST_FLOW_WRONG_STATE when the pool is
408  * flushing.
409  */
410 GstFlowReturn
411 gst_buffer_pool_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
412     GstBufferPoolParams * params)
413 {
414   GstBufferPoolClass *pclass;
415   GstFlowReturn result;
416
417   g_return_val_if_fail (GST_IS_BUFFER_POOL (pool), GST_FLOW_ERROR);
418   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
419
420   pclass = GST_BUFFER_POOL_GET_CLASS (pool);
421
422   if (G_LIKELY (pclass->acquire_buffer))
423     result = pclass->acquire_buffer (pool, buffer, params);
424   else
425     result = GST_FLOW_NOT_SUPPORTED;
426
427   return result;
428 }
429
430 static void
431 default_free_buffer (GstBufferPool * pool, GstBuffer * buffer)
432 {
433   gst_buffer_unref (buffer);
434 }
435
436 static void
437 default_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
438 {
439   /* keep it around in our queue, we might be flushing but that's ok because we
440    * handle that unlikely case below. */
441   gst_atomic_queue_push (pool->queue, buffer);
442   gst_poll_write_control (pool->poll);
443
444   if (G_UNLIKELY (g_atomic_int_get (&pool->flushing))) {
445     /* we are flushing, remove the buffers again */
446     flush_buffers (pool);
447   }
448 }
449
450 /**
451  * gst_buffer_pool_release_buffer:
452  * @pool: a #GstBufferPool
453  * @buffer: a #GstBuffer
454  *
455  * Release @buffer to @pool. @buffer should have previously been allocated from
456  * @pool with gst_buffer_pool_acquire_buffer().
457  *
458  * This function is usually called automatically when the last ref on @buffer
459  * disappears.
460  */
461 void
462 gst_buffer_pool_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
463 {
464   GstBufferPoolClass *pclass;
465
466   g_return_if_fail (GST_IS_BUFFER_POOL (pool));
467   g_return_if_fail (buffer != NULL);
468
469   pclass = GST_BUFFER_POOL_GET_CLASS (pool);
470
471   if (G_LIKELY (pclass->release_buffer))
472     pclass->release_buffer (pool, buffer);
473 }