Merge tizen patch based on 1.12.2
[platform/upstream/gstreamer.git] / omx / gstomxbufferpool.c
1 /*
2  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
3  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
4  * Copyright (C) 2013, Collabora Ltd.
5  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
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
9  * License as published by the Free Software Foundation
10  * version 2.1 of the License.
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 Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "gstomxbufferpool.h"
28
29 GST_DEBUG_CATEGORY_STATIC (gst_omx_buffer_pool_debug_category);
30 #define GST_CAT_DEFAULT gst_omx_buffer_pool_debug_category
31
32 typedef struct _GstOMXMemory GstOMXMemory;
33 typedef struct _GstOMXMemoryAllocator GstOMXMemoryAllocator;
34 typedef struct _GstOMXMemoryAllocatorClass GstOMXMemoryAllocatorClass;
35
36 struct _GstOMXMemory
37 {
38   GstMemory mem;
39
40   GstOMXBuffer *buf;
41 };
42
43 struct _GstOMXMemoryAllocator
44 {
45   GstAllocator parent;
46 };
47
48 struct _GstOMXMemoryAllocatorClass
49 {
50   GstAllocatorClass parent_class;
51 };
52
53 #define GST_OMX_MEMORY_TYPE "openmax"
54
55 static GstMemory *
56 gst_omx_memory_allocator_alloc_dummy (GstAllocator * allocator, gsize size,
57     GstAllocationParams * params)
58 {
59   g_assert_not_reached ();
60   return NULL;
61 }
62
63 static void
64 gst_omx_memory_allocator_free (GstAllocator * allocator, GstMemory * mem)
65 {
66   GstOMXMemory *omem = (GstOMXMemory *) mem;
67
68   /* TODO: We need to remember which memories are still used
69    * so we can wait until everything is released before allocating
70    * new memory
71    */
72
73   g_slice_free (GstOMXMemory, omem);
74 }
75
76 static gpointer
77 gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
78 {
79   GstOMXMemory *omem = (GstOMXMemory *) mem;
80
81   return omem->buf->omx_buf->pBuffer + omem->mem.offset;
82 }
83
84 static void
85 gst_omx_memory_unmap (GstMemory * mem)
86 {
87 }
88
89 static GstMemory *
90 gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size)
91 {
92   g_assert_not_reached ();
93   return NULL;
94 }
95
96 GType gst_omx_memory_allocator_get_type (void);
97 G_DEFINE_TYPE (GstOMXMemoryAllocator, gst_omx_memory_allocator,
98     GST_TYPE_ALLOCATOR);
99
100 #define GST_TYPE_OMX_MEMORY_ALLOCATOR   (gst_omx_memory_allocator_get_type())
101 #define GST_IS_OMX_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_MEMORY_ALLOCATOR))
102
103 static void
104 gst_omx_memory_allocator_class_init (GstOMXMemoryAllocatorClass * klass)
105 {
106   GstAllocatorClass *allocator_class;
107
108   allocator_class = (GstAllocatorClass *) klass;
109
110   allocator_class->alloc = gst_omx_memory_allocator_alloc_dummy;
111   allocator_class->free = gst_omx_memory_allocator_free;
112 }
113
114 static void
115 gst_omx_memory_allocator_init (GstOMXMemoryAllocator * allocator)
116 {
117   GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
118
119   alloc->mem_type = GST_OMX_MEMORY_TYPE;
120   alloc->mem_map = gst_omx_memory_map;
121   alloc->mem_unmap = gst_omx_memory_unmap;
122   alloc->mem_share = gst_omx_memory_share;
123
124   /* default copy & is_span */
125
126   GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
127 }
128
129 static GstMemory *
130 gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
131     GstOMXBuffer * buf)
132 {
133   GstOMXMemory *mem;
134   gint align;
135
136   /* FIXME: We don't allow sharing because we need to know
137    * when the memory becomes unused and can only then put
138    * it back to the pool. Which is done in the pool's release
139    * function
140    */
141   flags |= GST_MEMORY_FLAG_NO_SHARE;
142
143   /* GStreamer uses a bitmask for the alignment while
144    * OMX uses the alignment itself. So we have to convert
145    * here */
146   align = buf->port->port_def.nBufferAlignment;
147   if (align > 0)
148     align -= 1;
149   if (((align + 1) & align) != 0) {
150     GST_WARNING ("Invalid alignment that is not a power of two: %u",
151         (guint) buf->port->port_def.nBufferAlignment);
152     align = 0;
153   }
154
155   mem = g_slice_new (GstOMXMemory);
156   /* the shared memory is always readonly */
157   gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL,
158       buf->omx_buf->nAllocLen, align, 0, buf->omx_buf->nAllocLen);
159
160   mem->buf = buf;
161
162   return GST_MEMORY_CAST (mem);
163 }
164
165 /* Buffer pool for the buffers of an OpenMAX port.
166  *
167  * This pool is only used if we either passed buffers from another
168  * pool to the OMX port or provide the OMX buffers directly to other
169  * elements.
170  *
171  *
172  * A buffer is in the pool if it is currently owned by the port,
173  * i.e. after OMX_{Fill,Empty}ThisBuffer(). A buffer is outside
174  * the pool after it was taken from the port after it was handled
175  * by the port, i.e. {Empty,Fill}BufferDone.
176  *
177  * Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated
178  * by someone else and (temporarily) passed to this pool
179  * (OMX_UseBuffer(), OMX_UseEGLImage()). In the latter case the pool of
180  * the buffer will be overriden, and restored in free_buffer(). Other
181  * buffers are just freed there.
182  *
183  * The pool always has a fixed number of minimum and maximum buffers
184  * and these are allocated while starting the pool and released afterwards.
185  * They correspond 1:1 to the OMX buffers of the port, which are allocated
186  * before the pool is started.
187  *
188  * Acquiring a buffer from this pool happens after the OMX buffer has
189  * been acquired from the port. gst_buffer_pool_acquire_buffer() is
190  * supposed to return the buffer that corresponds to the OMX buffer.
191  *
192  * For buffers provided to upstream, the buffer will be passed to
193  * the component manually when it arrives and then unreffed. If the
194  * buffer is released before reaching the component it will be just put
195  * back into the pool as if EmptyBufferDone has happened. If it was
196  * passed to the component, it will be back into the pool when it was
197  * released and EmptyBufferDone has happened.
198  *
199  * For buffers provided to downstream, the buffer will be returned
200  * back to the component (OMX_FillThisBuffer()) when it is released.
201  */
202
203 static GQuark gst_omx_buffer_data_quark = 0;
204
205 #define DEBUG_INIT \
206   GST_DEBUG_CATEGORY_INIT (gst_omx_buffer_pool_debug_category, "omxbufferpool", 0, \
207       "debug category for gst-omx buffer pool base class");
208
209 G_DEFINE_TYPE_WITH_CODE (GstOMXBufferPool, gst_omx_buffer_pool,
210     GST_TYPE_BUFFER_POOL, DEBUG_INIT);
211
212 static void gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool,
213     GstBuffer * buffer);
214
215 static gboolean
216 gst_omx_buffer_pool_start (GstBufferPool * bpool)
217 {
218   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
219
220   /* Only allow to start the pool if we still are attached
221    * to a component and port */
222   GST_OBJECT_LOCK (pool);
223   if (!pool->component || !pool->port) {
224     GST_OBJECT_UNLOCK (pool);
225     return FALSE;
226   }
227   GST_OBJECT_UNLOCK (pool);
228
229   return
230       GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool);
231 }
232
233 static gboolean
234 gst_omx_buffer_pool_stop (GstBufferPool * bpool)
235 {
236   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
237   gint i = 0;
238
239   /* When not using the default GstBufferPool::GstAtomicQueue then
240    * GstBufferPool::free_buffer is not called while stopping the pool
241    * (because the queue is empty) */
242   for (i = 0; i < pool->buffers->len; i++)
243     GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
244         (bpool, g_ptr_array_index (pool->buffers, i));
245
246   /* Remove any buffers that are there */
247   g_ptr_array_set_size (pool->buffers, 0);
248
249   if (pool->caps)
250     gst_caps_unref (pool->caps);
251   pool->caps = NULL;
252
253   pool->add_videometa = FALSE;
254
255   return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool);
256 }
257
258 static const gchar **
259 gst_omx_buffer_pool_get_options (GstBufferPool * bpool)
260 {
261   static const gchar *raw_video_options[] =
262       { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
263   static const gchar *options[] = { NULL };
264   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
265
266   GST_OBJECT_LOCK (pool);
267   if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
268       && pool->port->port_def.format.video.eCompressionFormat ==
269       OMX_VIDEO_CodingUnused) {
270     GST_OBJECT_UNLOCK (pool);
271     return raw_video_options;
272   }
273   GST_OBJECT_UNLOCK (pool);
274
275   return options;
276 }
277
278 static gboolean
279 gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
280 {
281   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
282   GstCaps *caps;
283
284   GST_OBJECT_LOCK (pool);
285
286   if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
287     goto wrong_config;
288
289   if (caps == NULL)
290     goto no_caps;
291
292   if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo
293       && pool->port->port_def.format.video.eCompressionFormat ==
294       OMX_VIDEO_CodingUnused) {
295     GstVideoInfo info;
296
297     /* now parse the caps from the config */
298     if (!gst_video_info_from_caps (&info, caps))
299       goto wrong_video_caps;
300
301     /* enable metadata based on config of the pool */
302     pool->add_videometa =
303         gst_buffer_pool_config_has_option (config,
304         GST_BUFFER_POOL_OPTION_VIDEO_META);
305
306     pool->video_info = info;
307   }
308
309   if (pool->caps)
310     gst_caps_unref (pool->caps);
311   pool->caps = gst_caps_ref (caps);
312
313   GST_OBJECT_UNLOCK (pool);
314
315   return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config
316       (bpool, config);
317
318   /* ERRORS */
319 wrong_config:
320   {
321     GST_OBJECT_UNLOCK (pool);
322     GST_WARNING_OBJECT (pool, "invalid config");
323     return FALSE;
324   }
325 no_caps:
326   {
327     GST_OBJECT_UNLOCK (pool);
328     GST_WARNING_OBJECT (pool, "no caps in config");
329     return FALSE;
330   }
331 wrong_video_caps:
332   {
333     GST_OBJECT_UNLOCK (pool);
334     GST_WARNING_OBJECT (pool,
335         "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
336     return FALSE;
337   }
338 }
339
340 static GstFlowReturn
341 gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
342     GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
343 {
344   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
345   GstBuffer *buf;
346   GstOMXBuffer *omx_buf;
347
348   g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR);
349
350   omx_buf = g_ptr_array_index (pool->port->buffers, pool->current_buffer_index);
351   g_return_val_if_fail (omx_buf != NULL, GST_FLOW_ERROR);
352
353   if (pool->other_pool) {
354     guint i, n;
355
356     buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
357     g_assert (pool->other_pool == buf->pool);
358     gst_object_replace ((GstObject **) & buf->pool, NULL);
359
360     n = gst_buffer_n_memory (buf);
361     for (i = 0; i < n; i++) {
362       GstMemory *mem = gst_buffer_peek_memory (buf, i);
363
364       /* FIXME: We don't allow sharing because we need to know
365        * when the memory becomes unused and can only then put
366        * it back to the pool. Which is done in the pool's release
367        * function
368        */
369       GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_NO_SHARE);
370     }
371
372     if (pool->add_videometa) {
373       GstVideoMeta *meta;
374
375       meta = gst_buffer_get_video_meta (buf);
376       if (!meta) {
377         gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE,
378             GST_VIDEO_INFO_FORMAT (&pool->video_info),
379             GST_VIDEO_INFO_WIDTH (&pool->video_info),
380             GST_VIDEO_INFO_HEIGHT (&pool->video_info));
381       }
382     }
383
384     pool->need_copy = FALSE;
385   } else {
386     GstMemory *mem;
387     const guint nstride = pool->port->port_def.format.video.nStride;
388     const guint nslice = pool->port->port_def.format.video.nSliceHeight;
389     gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
390     gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
391
392     mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
393     buf = gst_buffer_new ();
394     gst_buffer_append_memory (buf, mem);
395     g_ptr_array_add (pool->buffers, buf);
396
397     switch (GST_VIDEO_INFO_FORMAT (&pool->video_info)) {
398       case GST_VIDEO_FORMAT_ABGR:
399       case GST_VIDEO_FORMAT_ARGB:
400       case GST_VIDEO_FORMAT_RGB16:
401       case GST_VIDEO_FORMAT_BGR16:
402       case GST_VIDEO_FORMAT_YUY2:
403       case GST_VIDEO_FORMAT_UYVY:
404       case GST_VIDEO_FORMAT_YVYU:
405       case GST_VIDEO_FORMAT_GRAY8:
406         break;
407       case GST_VIDEO_FORMAT_I420:
408         stride[1] = nstride / 2;
409         offset[1] = offset[0] + stride[0] * nslice;
410         stride[2] = nstride / 2;
411         offset[2] = offset[1] + (stride[1] * nslice / 2);
412         break;
413       case GST_VIDEO_FORMAT_NV12:
414       case GST_VIDEO_FORMAT_NV16:
415         stride[1] = nstride;
416         offset[1] = offset[0] + stride[0] * nslice;
417         break;
418       case GST_VIDEO_FORMAT_SN12:
419       case GST_VIDEO_FORMAT_ST12:
420         offset[0] = 0;
421         stride[0] = pool->port->port_def.format.video.nStride;
422         offset[1] = stride[0] * pool->port->port_def.format.video.nSliceHeight;
423         stride[1] = pool->port->port_def.format.video.nStride;
424         break;
425       default:
426         g_assert_not_reached ();
427         break;
428     }
429
430     if (pool->add_videometa) {
431       pool->need_copy = FALSE;
432     } else {
433       GstVideoInfo info;
434       gboolean need_copy = FALSE;
435       gint i;
436
437       gst_video_info_init (&info);
438       gst_video_info_set_format (&info,
439           GST_VIDEO_INFO_FORMAT (&pool->video_info),
440           GST_VIDEO_INFO_WIDTH (&pool->video_info),
441           GST_VIDEO_INFO_HEIGHT (&pool->video_info));
442
443       for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&pool->video_info); i++) {
444         if (info.stride[i] != stride[i] || info.offset[i] != offset[i]) {
445           need_copy = TRUE;
446           break;
447         }
448       }
449       pool->need_copy = need_copy;
450     }
451 #ifdef TIZEN_FEATURE_OMX
452     pool->need_copy = FALSE;
453 #endif
454
455     if (pool->need_copy || pool->add_videometa) {
456       /* We always add the videometa. It's the job of the user
457        * to copy the buffer if pool->need_copy is TRUE
458        */
459       gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
460           GST_VIDEO_INFO_FORMAT (&pool->video_info),
461           GST_VIDEO_INFO_WIDTH (&pool->video_info),
462           GST_VIDEO_INFO_HEIGHT (&pool->video_info),
463           GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride);
464     }
465   }
466
467   gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
468       gst_omx_buffer_data_quark, omx_buf, NULL);
469
470   *buffer = buf;
471
472   pool->num_buffers++;
473   GST_DEBUG_OBJECT (pool, "alloc buffers : %d %d", pool->num_buffers, pool->current_buffer_index);
474   pool->current_buffer_index++;
475
476   return GST_FLOW_OK;
477 }
478
479 static void
480 gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
481 {
482   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
483
484   /* If the buffers belong to another pool, restore them now */
485   GST_OBJECT_LOCK (pool);
486   if (pool->other_pool) {
487     gst_object_replace ((GstObject **) & buffer->pool,
488         (GstObject *) pool->other_pool);
489   }
490   GST_OBJECT_UNLOCK (pool);
491
492   gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
493       gst_omx_buffer_data_quark, NULL, NULL);
494
495   GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool,
496       buffer);
497   GST_DEBUG_OBJECT (pool, "free buffers : %d %d", pool->num_buffers, pool->current_buffer_index);
498   pool->num_buffers--;
499 }
500
501 static GstFlowReturn
502 gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
503     GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
504 {
505   GstFlowReturn ret;
506   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
507
508   if (pool->port->port_def.eDir == OMX_DirOutput) {
509     GstBuffer *buf;
510
511     g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
512
513     buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
514     g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
515     *buffer = buf;
516     pool->num_buffers--;
517     GST_DEBUG_OBJECT (pool, "acquire buffers : %d %d", pool->num_buffers, pool->current_buffer_index);
518     ret = GST_FLOW_OK;
519
520     /* If it's our own memory we have to set the sizes */
521     if (!pool->other_pool) {
522       GstMemory *mem = gst_buffer_peek_memory (*buffer, 0);
523
524       g_assert (mem
525           && g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
526       mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen;
527       mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset;
528     }
529   } else {
530     /* Acquire any buffer that is available to be filled by upstream */
531     ret =
532         GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer
533         (bpool, buffer, params);
534   }
535
536   return ret;
537 }
538
539 static void
540 gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
541 {
542   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
543   OMX_ERRORTYPE err;
544   GstOMXBuffer *omx_buf;
545
546   g_assert (pool->component && pool->port);
547
548   if (!pool->allocating && !pool->deactivated) {
549     omx_buf =
550         gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
551         gst_omx_buffer_data_quark);
552     if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) {
553       /* Release back to the port, can be filled again */
554       pool->num_buffers++;
555       GST_DEBUG_OBJECT (pool, "release buffers : %d %d", pool->num_buffers, pool->current_buffer_index);
556       err = gst_omx_port_release_buffer (pool->port, omx_buf);
557       if (err != OMX_ErrorNone) {
558         GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL),
559             ("Failed to relase output buffer to component: %s (0x%08x)",
560                 gst_omx_error_to_string (err), err));
561       }
562     } else if (!omx_buf->used) {
563       /* TODO: Implement.
564        *
565        * If not used (i.e. was not passed to the component) this should do
566        * the same as EmptyBufferDone.
567        * If it is used (i.e. was passed to the component) this should do
568        * nothing until EmptyBufferDone.
569        *
570        * EmptyBufferDone should release the buffer to the pool so it can
571        * be allocated again
572        *
573        * Needs something to call back here in EmptyBufferDone, like keeping
574        * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which
575        * would ensure that the buffer is always unused when this is called.
576        */
577       g_assert_not_reached ();
578       GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
579           (bpool, buffer);
580     }
581   }
582 }
583
584 static void
585 gst_omx_buffer_pool_finalize (GObject * object)
586 {
587   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object);
588
589   if (pool->element)
590     gst_object_unref (pool->element);
591   pool->element = NULL;
592
593   if (pool->buffers)
594     g_ptr_array_unref (pool->buffers);
595   pool->buffers = NULL;
596
597   if (pool->other_pool)
598     gst_object_unref (pool->other_pool);
599   pool->other_pool = NULL;
600
601   if (pool->allocator)
602     gst_object_unref (pool->allocator);
603   pool->allocator = NULL;
604
605   if (pool->caps)
606     gst_caps_unref (pool->caps);
607   pool->caps = NULL;
608
609   G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object);
610 }
611
612 static void
613 gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass)
614 {
615   GObjectClass *gobject_class = (GObjectClass *) klass;
616   GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
617
618   gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData");
619
620   gobject_class->finalize = gst_omx_buffer_pool_finalize;
621   gstbufferpool_class->start = gst_omx_buffer_pool_start;
622   gstbufferpool_class->stop = gst_omx_buffer_pool_stop;
623   gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options;
624   gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config;
625   gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer;
626   gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer;
627   gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer;
628   gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer;
629 }
630
631 static void
632 gst_omx_buffer_pool_init (GstOMXBufferPool * pool)
633 {
634   pool->buffers = g_ptr_array_new ();
635   pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL);
636 }
637
638 GstBufferPool *
639 gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
640     GstOMXPort * port)
641 {
642   GstOMXBufferPool *pool;
643
644   pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL);
645   pool->element = gst_object_ref (element);
646   pool->component = component;
647   pool->port = port;
648
649   return GST_BUFFER_POOL (pool);
650 }