7 #include <gst/video/gstvideometa.h>
8 #include <gst/video/gstvideopool.h>
12 #include <mmf/mm_types.h>
14 #include <tbm_surface.h>
15 #include <tbm_bufmgr.h>
18 typedef struct _GstMMVideoMemory GstMMVideoMemory;
19 typedef struct _GstMMVideoMemoryAllocator GstMMVideoMemoryAllocator;
20 typedef struct _GstMMVideoMemoryAllocatorClass GstMMVideoMemoryAllocatorClass;
21 typedef struct _GstMMBuffer GstMMBuffer;
24 struct _GstMMVideoMemory
27 GstMMBuffer *mm_video_buffer;
30 struct _GstMMVideoMemoryAllocator
35 struct _GstMMVideoMemoryAllocatorClass
37 GstAllocatorClass parent_class;
42 MMVideoBuffer mm_buffer;
48 #define GST_MM_VIDEO_MEMORY_TYPE "mmvideobuffer"
49 #define GST_TYPE_MM_BUFFER_POOL \
50 (gst_mm_buffer_pool_get_type()
51 #define GST_MM_BUFFER_POOL(obj) \
52 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MM_POOL,GstMMBufferPool))
53 typedef struct _GstMMBufferPool GstMMBufferPool;
54 typedef struct _GstMMBufferPoolClass GstMMBufferPoolClass;
56 struct _GstMMBufferPool
58 GstVideoBufferPool parent;
63 gboolean add_videometa;
64 GstVideoInfo video_info;
66 GstAllocator *allocator;
68 /* Set from outside this pool */
69 /* TRUE if we're currently allocating all our buffers */
72 /* TRUE if the pool is not used anymore */
75 /* For populating the pool from another one */
76 GstBufferPool *other_pool;
80 /* Used during acquire for output ports to
81 * specify which buffer has to be retrieved
82 * and during alloc, which buffer has to be
85 gint current_buffer_index;
88 tbm_bufmgr hTBMBufMgr;
93 struct _GstMMBufferPoolClass
95 GstVideoBufferPoolClass parent_class;
99 gst_mm_buffer_pool_new (GstElement * element );
101 GType gst_mm_buffer_pool_get_type (void);
103 int new_calc_plane(int width, int height);
104 int gst_calculate_y_size(int width, int height);
105 int gst_calculate_uv_size(int width, int height);
107 #ifdef USE_TBM_BUFFER
109 /*MFC Buffer alignment macros*/
110 #define S5P_FIMV_DEC_BUF_ALIGN (8 * 1024)
111 #define S5P_FIMV_ENC_BUF_ALIGN (8 * 1024)
112 #define S5P_FIMV_NV12M_HALIGN 16
113 #define S5P_FIMV_NV12M_LVALIGN 16
114 #define S5P_FIMV_NV12M_CVALIGN 8
115 #define S5P_FIMV_NV12MT_HALIGN 128
116 #define S5P_FIMV_NV12MT_VALIGN 64
117 #define S5P_FIMV_NV12M_SALIGN 2048
118 #define S5P_FIMV_NV12MT_SALIGN 8192
120 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
122 /* Buffer alignment defines */
123 #define SZ_1M 0x00100000
124 #define S5P_FIMV_D_ALIGN_PLANE_SIZE 64
126 #define S5P_FIMV_MAX_FRAME_SIZE (2 * SZ_1M)
127 #define S5P_FIMV_NUM_PIXELS_IN_MB_ROW 16
128 #define S5P_FIMV_NUM_PIXELS_IN_MB_COL 16
131 #define ALIGN_TO_4KB(x) ((((x) + (1 << 12) - 1) >> 12) << 12)
132 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
133 #define CHOOSE_MAX_SIZE(a,b) ((a) > (b) ? (a) : (b))
139 static GQuark gst_tbm_buffer_data_quark = 0;
142 typedef struct _GstTBMBuffer GstTBMBuffer;
149 #define GST_TBM_BUFFER_POOL(pool) ((GstTBMBufferPool *) pool)
150 typedef struct _GstTBMBufferPool GstTBMBufferPool;
151 typedef struct _GstTBMBufferPoolClass GstTBMBufferPoolClass;
153 struct _GstTBMBufferPool
155 GstVideoBufferPool parent;
160 gboolean add_videometa;
161 GstVideoInfo video_info;
163 /* Owned by element, element has to stop this pool before
164 * it destroys component or port */
165 GstElement *component;
167 GstAllocator *allocator;
169 /* Set from outside this pool */
170 /* TRUE if we're currently allocating all our buffers */
173 /* TRUE if the pool is not used anymore */
174 gboolean deactivated;
176 /* For populating the pool from another one */
177 GstBufferPool *other_pool;
180 /* Used during acquire for output buffer to
181 * specify which buffer has to be retrieved
182 * and during alloc, which buffer has to be
185 gint current_buffer_index;
188 struct _GstTBMBufferPoolClass
190 GstVideoBufferPoolClass parent_class;
193 GType gst_tbm_buffer_pool_get_type (void);
195 G_DEFINE_TYPE (GstTBMBufferPool, gst_tbm_buffer_pool, GST_TYPE_BUFFER_POOL);
198 gst_tbm_buffer_pool_start (GstBufferPool * bpool)
200 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
202 /* Only allow to start the pool if we still are attached
203 * to a component and port */
204 GST_OBJECT_LOCK (pool);
205 if (!pool->component ) {
206 GST_OBJECT_UNLOCK (pool);
209 GST_OBJECT_UNLOCK (pool);
212 GST_BUFFER_POOL_CLASS (gst_tbm_buffer_pool_parent_class)->start (bpool);
216 gst_tbm_buffer_pool_stop (GstBufferPool * bpool)
218 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
220 /* Remove any buffers that are there */
221 g_ptr_array_set_size (pool->buffers, 0);
224 gst_caps_unref (pool->caps);
227 pool->add_videometa = FALSE;
229 return GST_BUFFER_POOL_CLASS (gst_tbm_buffer_pool_parent_class)->stop (bpool);
232 static const gchar **
233 gst_tbm_buffer_pool_get_options (GstBufferPool * bpool)
235 static const gchar *raw_video_options[] =
236 { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
237 static const gchar *options[] = { NULL };
238 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
244 gst_tbm_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
246 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
249 GST_OBJECT_LOCK (pool);
251 if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
258 gst_caps_unref (pool->caps);
259 pool->caps = gst_caps_ref (caps);
261 GST_OBJECT_UNLOCK (pool);
263 return GST_BUFFER_POOL_CLASS (gst_tbm_buffer_pool_parent_class)->set_config
269 GST_OBJECT_UNLOCK (pool);
270 GST_WARNING_OBJECT (pool, "invalid config");
275 GST_OBJECT_UNLOCK (pool);
276 GST_WARNING_OBJECT (pool, "no caps in config");
281 GST_OBJECT_UNLOCK (pool);
282 GST_WARNING_OBJECT (pool,
283 "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
289 gst_tbm_buffer_pool_alloc_buffer (GstBufferPool * bpool,
290 GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
292 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
294 GstTBMBuffer *tbm_buf;
297 g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR);
299 tbm_buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
300 g_return_val_if_fail (tbm_buf != NULL, GST_FLOW_ERROR);
302 mem = gst_tbm_memory_allocator_alloc (pool->allocator, 0, tbm_buf);
303 buf = gst_buffer_new ();
304 gst_buffer_append_memory (buf, mem);
305 g_ptr_array_add (pool->buffers, buf);
307 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
308 gst_tbm_buffer_data_quark, tbm_buf, NULL);
312 pool->current_buffer_index++;
318 gst_tbm_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
320 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
322 /* If the buffers belong to another pool, restore them now */
323 GST_OBJECT_LOCK (pool);
324 if (pool->other_pool) {
325 gst_object_replace ((GstObject **) & buffer->pool,
326 (GstObject *) pool->other_pool);
328 GST_OBJECT_UNLOCK (pool);
330 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
331 gst_tbm_buffer_data_quark, NULL, NULL);
333 GST_BUFFER_POOL_CLASS (gst_tbm_buffer_pool_parent_class)->free_buffer (bpool,
338 gst_tbm_buffer_pool_acquire_buffer (GstBufferPool * bpool,
339 GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
342 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
344 if (pool->port->port_def.eDir == OMX_DirOutput) {
347 g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
349 buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
350 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
354 /* If it's our own memory we have to set the sizes */
355 if (!pool->other_pool) {
356 GstMemory *mem = gst_buffer_peek_memory (*buffer, 0);
359 && g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
360 mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen;
361 mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset;
364 /* Acquire any buffer that is available to be filled by upstream */
366 GST_BUFFER_POOL_CLASS (gst_tbm_buffer_pool_parent_class)->acquire_buffer
367 (bpool, buffer, params);
374 gst_tbm_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
376 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (bpool);
378 GstOMXBuffer *omx_buf;
380 g_assert (pool->component && pool->port);
382 if (!pool->allocating && !pool->deactivated) {
384 gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
385 gst_omx_buffer_data_quark);
386 if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) {
387 /* Release back to the port, can be filled again */
388 err = gst_omx_port_release_buffer (pool->port, omx_buf);
389 if (err != OMX_ErrorNone) {
390 GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL),
391 ("Failed to relase output buffer to component: %s (0x%08x)",
392 gst_omx_error_to_string (err), err));
394 } else if (!omx_buf->used) {
397 * If not used (i.e. was not passed to the component) this should do
398 * the same as EmptyBufferDone.
399 * If it is used (i.e. was passed to the component) this should do
400 * nothing until EmptyBufferDone.
402 * EmptyBufferDone should release the buffer to the pool so it can
405 * Needs something to call back here in EmptyBufferDone, like keeping
406 * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which
407 * would ensure that the buffer is always unused when this is called.
409 g_assert_not_reached ();
410 GST_BUFFER_POOL_CLASS (gst_tbm_buffer_pool_parent_class)->release_buffer
417 gst_tbm_buffer_pool_finalize (GObject * object)
419 GstTBMBufferPool *pool = GST_TBM_BUFFER_POOL (object);
422 gst_object_unref (pool->element);
423 pool->element = NULL;
426 g_ptr_array_unref (pool->buffers);
427 pool->buffers = NULL;
429 if (pool->other_pool)
430 gst_object_unref (pool->other_pool);
431 pool->other_pool = NULL;
434 gst_object_unref (pool->allocator);
435 pool->allocator = NULL;
438 gst_caps_unref (pool->caps);
441 G_OBJECT_CLASS (gst_tbm_buffer_pool_parent_class)->finalize (object);
445 gst_tbm_buffer_pool_class_init (GstTBMBufferPoolClass * klass)
447 GObjectClass *gobject_class = (GObjectClass *) klass;
448 GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
450 gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData");
452 gobject_class->finalize = gst_tbm_buffer_pool_finalize;
453 gstbufferpool_class->start = gst_tbm_buffer_pool_start;
454 gstbufferpool_class->stop = gst_tbm_buffer_pool_stop;
455 gstbufferpool_class->get_options = gst_tbm_buffer_pool_get_options;
456 gstbufferpool_class->set_config = gst_tbm_buffer_pool_set_config;
457 gstbufferpool_class->alloc_buffer = gst_tbm_buffer_pool_alloc_buffer;
458 gstbufferpool_class->free_buffer = gst_tbm_buffer_pool_free_buffer;
459 gstbufferpool_class->acquire_buffer = gst_tbm_buffer_pool_acquire_buffer;
460 gstbufferpool_class->release_buffer = gst_tbm_buffer_pool_release_buffer;
464 gst_tbm_buffer_pool_init (GstTBMBufferPool * pool)
466 pool->buffers = g_ptr_array_new ();
467 pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL);
470 static GstBufferPool *
471 gst_tbm_buffer_pool_new (GstElement * element, GstOMXComponent * component,
474 GstTBMBufferPool *pool;
476 pool = g_object_new (gst_tbm_buffer_pool_get_type (), NULL);
477 pool->element = gst_object_ref (element);
478 pool->component = component;
481 return GST_BUFFER_POOL (pool);