enabling omx decoder
[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         GST_WARNING_OBJECT (pool, "GST_VIDEO_CAPS");
399       case GST_VIDEO_FORMAT_ABGR:
400       case GST_VIDEO_FORMAT_ARGB:
401       case GST_VIDEO_FORMAT_RGB16:
402       case GST_VIDEO_FORMAT_BGR16:
403       case GST_VIDEO_FORMAT_YUY2:
404       case GST_VIDEO_FORMAT_UYVY:
405       case GST_VIDEO_FORMAT_YVYU:
406       case GST_VIDEO_FORMAT_GRAY8:
407         break;
408       case GST_VIDEO_FORMAT_I420:
409         stride[1] = nstride / 2;
410         offset[1] = offset[0] + stride[0] * nslice;
411         stride[2] = nstride / 2;
412         offset[2] = offset[1] + (stride[1] * nslice / 2);
413         break;
414       case GST_VIDEO_FORMAT_NV12:
415       case GST_VIDEO_FORMAT_NV16:
416         stride[1] = nstride;
417         offset[1] = offset[0] + stride[0] * nslice;
418         break;
419       case GST_VIDEO_FORMAT_SN12:
420       case GST_VIDEO_FORMAT_ST12:
421         GST_WARNING_OBJECT (pool, "SN12SN12SN12SN12SN12");
422         offset[0] = 0;
423         stride[0] = pool->port->port_def.format.video.nStride;
424         offset[1] = stride[0] * pool->port->port_def.format.video.nSliceHeight;
425         stride[1] = pool->port->port_def.format.video.nStride;
426         break;
427       default:
428         g_assert_not_reached ();
429         break;
430     }
431
432     if (pool->add_videometa) {
433       pool->need_copy = FALSE;
434     } else {
435       GstVideoInfo info;
436       gboolean need_copy = FALSE;
437       gint i;
438
439       gst_video_info_init (&info);
440       gst_video_info_set_format (&info,
441           GST_VIDEO_INFO_FORMAT (&pool->video_info),
442           GST_VIDEO_INFO_WIDTH (&pool->video_info),
443           GST_VIDEO_INFO_HEIGHT (&pool->video_info));
444
445       for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&pool->video_info); i++) {
446         if (info.stride[i] != stride[i] || info.offset[i] != offset[i]) {
447           need_copy = TRUE;
448           break;
449         }
450       }
451
452       pool->need_copy = need_copy;
453     }
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->current_buffer_index++;
473
474   return GST_FLOW_OK;
475 }
476
477 static void
478 gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
479 {
480   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
481
482   /* If the buffers belong to another pool, restore them now */
483   GST_OBJECT_LOCK (pool);
484   if (pool->other_pool) {
485     gst_object_replace ((GstObject **) & buffer->pool,
486         (GstObject *) pool->other_pool);
487   }
488   GST_OBJECT_UNLOCK (pool);
489
490   gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
491       gst_omx_buffer_data_quark, NULL, NULL);
492
493   GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool,
494       buffer);
495 }
496
497 static GstFlowReturn
498 gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
499     GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
500 {
501   GstFlowReturn ret;
502   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
503
504   if (pool->port->port_def.eDir == OMX_DirOutput) {
505     GstBuffer *buf;
506
507     g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
508
509     buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
510     g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
511     *buffer = buf;
512     ret = GST_FLOW_OK;
513
514     /* If it's our own memory we have to set the sizes */
515     if (!pool->other_pool) {
516       GstMemory *mem = gst_buffer_peek_memory (*buffer, 0);
517
518       g_assert (mem
519           && g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
520       mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen;
521       mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset;
522     }
523   } else {
524     /* Acquire any buffer that is available to be filled by upstream */
525     ret =
526         GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer
527         (bpool, buffer, params);
528   }
529
530   return ret;
531 }
532
533 static void
534 gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
535 {
536   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
537   OMX_ERRORTYPE err;
538   GstOMXBuffer *omx_buf;
539
540   g_assert (pool->component && pool->port);
541
542   if (!pool->allocating && !pool->deactivated) {
543     omx_buf =
544         gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
545         gst_omx_buffer_data_quark);
546     if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) {
547       /* Release back to the port, can be filled again */
548       err = gst_omx_port_release_buffer (pool->port, omx_buf);
549       if (err != OMX_ErrorNone) {
550         GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL),
551             ("Failed to relase output buffer to component: %s (0x%08x)",
552                 gst_omx_error_to_string (err), err));
553       }
554     } else if (!omx_buf->used) {
555       /* TODO: Implement.
556        *
557        * If not used (i.e. was not passed to the component) this should do
558        * the same as EmptyBufferDone.
559        * If it is used (i.e. was passed to the component) this should do
560        * nothing until EmptyBufferDone.
561        *
562        * EmptyBufferDone should release the buffer to the pool so it can
563        * be allocated again
564        *
565        * Needs something to call back here in EmptyBufferDone, like keeping
566        * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which
567        * would ensure that the buffer is always unused when this is called.
568        */
569       g_assert_not_reached ();
570       GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
571           (bpool, buffer);
572     }
573   }
574 }
575
576 static void
577 gst_omx_buffer_pool_finalize (GObject * object)
578 {
579   GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object);
580
581   if (pool->element)
582     gst_object_unref (pool->element);
583   pool->element = NULL;
584
585   if (pool->buffers)
586     g_ptr_array_unref (pool->buffers);
587   pool->buffers = NULL;
588
589   if (pool->other_pool)
590     gst_object_unref (pool->other_pool);
591   pool->other_pool = NULL;
592
593   if (pool->allocator)
594     gst_object_unref (pool->allocator);
595   pool->allocator = NULL;
596
597   if (pool->caps)
598     gst_caps_unref (pool->caps);
599   pool->caps = NULL;
600
601   G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object);
602 }
603
604 static void
605 gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass)
606 {
607   GObjectClass *gobject_class = (GObjectClass *) klass;
608   GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
609
610   gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData");
611
612   gobject_class->finalize = gst_omx_buffer_pool_finalize;
613   gstbufferpool_class->start = gst_omx_buffer_pool_start;
614   gstbufferpool_class->stop = gst_omx_buffer_pool_stop;
615   gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options;
616   gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config;
617   gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer;
618   gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer;
619   gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer;
620   gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer;
621 }
622
623 static void
624 gst_omx_buffer_pool_init (GstOMXBufferPool * pool)
625 {
626   pool->buffers = g_ptr_array_new ();
627   pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL);
628 }
629
630 GstBufferPool *
631 gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
632     GstOMXPort * port)
633 {
634   GstOMXBufferPool *pool;
635
636   pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL);
637   pool->element = gst_object_ref (element);
638   pool->component = component;
639   pool->port = port;
640
641   return GST_BUFFER_POOL (pool);
642 }