2 #include "gsttbmbufferpool.h"
3 #include <gst/video/gstvideofilter.h>
5 int new_calc_plane(int width, int height)
9 mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW);
10 mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL);
12 if (width * height < S5P_FIMV_MAX_FRAME_SIZE)
13 mbY = (mbY + 1) / 2 * 2;
15 return ((mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL) *
16 (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW));
19 int new_calc_yplane(int width, int height)
21 return (ALIGN_TO_4KB(new_calc_plane(width, height) +
22 S5P_FIMV_D_ALIGN_PLANE_SIZE));
25 int new_calc_uvplane(int width, int height)
27 return (ALIGN_TO_4KB((new_calc_plane(width, height) >> 1) +
28 S5P_FIMV_D_ALIGN_PLANE_SIZE));
32 calc_plane(int width, int height)
36 mbX = ALIGN(width, S5P_FIMV_NV12MT_HALIGN);
37 mbY = ALIGN(height, S5P_FIMV_NV12MT_VALIGN);
39 return ALIGN(mbX * mbY, S5P_FIMV_DEC_BUF_ALIGN);
43 calc_yplane(int width, int height)
47 mbX = ALIGN(width + 24, S5P_FIMV_NV12MT_HALIGN);
48 mbY = ALIGN(height + 16, S5P_FIMV_NV12MT_VALIGN);
50 return ALIGN(mbX * mbY, S5P_FIMV_DEC_BUF_ALIGN);
54 calc_uvplane(int width, int height)
58 mbX = ALIGN(width + 16, S5P_FIMV_NV12MT_HALIGN);
59 mbY = ALIGN(height + 4, S5P_FIMV_NV12MT_VALIGN);
61 return ALIGN((mbX * mbY)>>1, S5P_FIMV_DEC_BUF_ALIGN);
65 gst_calculate_y_size(int width, int height)
67 return CHOOSE_MAX_SIZE(calc_yplane(width,height),new_calc_yplane(width,height));
71 gst_calculate_uv_size(int width, int height)
73 return CHOOSE_MAX_SIZE(calc_uvplane(width,height),new_calc_uvplane(width,height));
77 gst_mm_memory_allocator_alloc_dummy (GstAllocator * allocator, gsize size,
78 GstAllocationParams * params)
80 g_assert_not_reached ();
85 gst_mm_memory_allocator_free (GstAllocator * allocator, GstMemory * mem)
87 GstMMVideoMemory *omem = (GstMMVideoMemory *) mem;
89 /* TODO: We need to remember which memories are still used
90 * so we can wait until everything is released before allocating
94 g_slice_free (GstMMVideoMemory, omem);
98 gst_mm_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
100 GstMMVideoMemory *omem = (GstMMVideoMemory *) mem;
102 return omem->mm_video_buffer;
106 gst_mm_memory_unmap (GstMemory * mem)
111 gst_mm_memory_share (GstMemory * mem, gssize offset, gssize size)
113 g_assert_not_reached ();
117 GType gst_mm_memory_allocator_get_type (void);
118 G_DEFINE_TYPE (GstMMVideoMemoryAllocator, gst_mm_memory_allocator,
121 #define GST_TYPE_MM_MEMORY_ALLOCATOR (gst_mm_memory_allocator_get_type())
122 #define GST_IS_MM_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MM_MEMORY_ALLOCATOR))
125 gst_mm_memory_allocator_class_init (GstMMVideoMemoryAllocatorClass * klass)
127 GstAllocatorClass *allocator_class;
129 allocator_class = (GstAllocatorClass *) klass;
131 allocator_class->alloc = gst_mm_memory_allocator_alloc_dummy;
132 allocator_class->free = gst_mm_memory_allocator_free;
136 gst_mm_memory_allocator_init (GstMMVideoMemoryAllocator * allocator)
138 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
140 alloc->mem_type = GST_MM_VIDEO_MEMORY_TYPE;
141 alloc->mem_map = gst_mm_memory_map;
142 alloc->mem_unmap = gst_mm_memory_unmap;
143 alloc->mem_share = gst_mm_memory_share;
145 /* default copy & is_span */
147 GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
151 gst_mm_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
154 GstMMVideoMemory *mem;
156 /* FIXME: We don't allow sharing because we need to know
157 * when the memory becomes unused and can only then put
158 * it back to the pool. Which is done in the pool's release
161 flags |= GST_MEMORY_FLAG_NO_SHARE;
163 mem = g_slice_new (GstMMVideoMemory);
164 /* the shared memory is always readonly */
165 gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL,
166 sizeof(MMVideoBuffer), 1, 0, sizeof(MMVideoBuffer));
168 mem->mm_video_buffer = buf;
170 return GST_MEMORY_CAST (mem);
173 /* Subclassing GstBufferPool */
177 GType gst_mm_buffer_pool_get_type (void);
179 G_DEFINE_TYPE (GstMMBufferPool, gst_mm_buffer_pool, GST_TYPE_BUFFER_POOL);
182 gst_mm_buffer_pool_start (GstBufferPool * bpool)
185 GST_BUFFER_POOL_CLASS (gst_mm_buffer_pool_parent_class)->start (bpool);
189 gst_mm_buffer_pool_stop (GstBufferPool * bpool)
191 GstMMBufferPool *pool = GST_MM_BUFFER_POOL (bpool);
193 if(gst_buffer_pool_is_active (pool) == TRUE)
195 /* Remove any buffers that are there */
196 if(pool->buffers != NULL){
197 g_ptr_array_set_size (pool->buffers, 0);
198 pool->buffers = NULL;
202 gst_caps_unref (pool->caps);
205 pool->add_videometa = FALSE;
207 return GST_BUFFER_POOL_CLASS (gst_mm_buffer_pool_parent_class)->stop (bpool);
210 static const gchar **
211 gst_mm_buffer_pool_get_options (GstBufferPool * bpool)
213 static const gchar *raw_video_options[] =
214 { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL };
215 static const gchar *options[] = { NULL };
220 gst_mm_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
222 GstMMBufferPool *pool = GST_MM_BUFFER_POOL (bpool);
225 GST_OBJECT_LOCK (pool);
227 if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
234 gst_caps_unref (pool->caps);
235 pool->caps = gst_caps_ref (caps);
237 GST_OBJECT_UNLOCK (pool);
239 return GST_BUFFER_POOL_CLASS (gst_mm_buffer_pool_parent_class)->set_config
245 GST_OBJECT_UNLOCK (pool);
246 GST_WARNING_OBJECT (pool, "invalid config");
251 GST_OBJECT_UNLOCK (pool);
252 GST_WARNING_OBJECT (pool, "no caps in config");
258 gst_mm_buffer_pool_alloc_buffer (GstBufferPool * bpool,
259 GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
261 GstMMBufferPool *pool = GST_MM_BUFFER_POOL (bpool);
262 GstBuffer *buf = NULL;
263 GstMMBuffer *mm_buf = NULL;
265 void *mm_data = NULL;
266 MMVideoBuffer *mm_video_buf = NULL;
267 gsize offset[4] = { 0, };
268 gint stride[4] = { 0, };
271 mm_buf = (GstMMBuffer*) malloc(sizeof(GstMMBuffer));
272 mem = gst_mm_memory_allocator_alloc (pool->allocator, 0, mm_buf);
273 buf = gst_buffer_new ();
275 mem->size = sizeof(GstMMBuffer);
277 gst_buffer_append_memory (buf, mem);
278 offset[0] = offset[1] = 0;
279 stride[0] = stride[1] = 0;
280 gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
281 GST_VIDEO_INFO_FORMAT (&pool->video_info),
282 GST_VIDEO_INFO_WIDTH (&pool->video_info),
283 GST_VIDEO_INFO_HEIGHT (&pool->video_info),
284 GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride);
286 g_ptr_array_add (pool->buffers, buf);
287 GST_ERROR(" buffer:[%p], mm_buffer:[%p], mem:[%p] width:[%d] height:[%d]",buf, mm_buf, mem, GST_VIDEO_INFO_WIDTH (&pool->video_info),GST_VIDEO_INFO_HEIGHT (&pool->video_info));
289 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf),
290 gst_mm_buffer_data_quark, mm_buf, NULL);
292 /* Allocating second GstMemory for buffer */
293 width = GST_VIDEO_INFO_WIDTH (&pool->video_info);
294 height = GST_VIDEO_INFO_HEIGHT (&pool->video_info);
295 mm_data = g_malloc0(sizeof(MMVideoBuffer));
296 mm_video_buf = (MMVideoBuffer*) mm_data;
297 mm_video_buf->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
298 mm_video_buf->plane_num = 2;
299 /* Setting Y plane size */
300 mm_video_buf->size[0] = gst_calculate_y_size(width, height);
301 /* Setting UV plane size */
302 mm_video_buf->size[1] = gst_calculate_uv_size(width, height);
303 mm_video_buf->handle.bo[0] = tbm_bo_alloc(pool->hTBMBufMgr, mm_video_buf->size[0], TBM_BO_WC);
304 mm_video_buf->handle.bo[1] = tbm_bo_alloc(pool->hTBMBufMgr, mm_video_buf->size[1], TBM_BO_WC);
306 mm_video_buf->handle.dmabuf_fd[0] = (tbm_bo_get_handle(mm_video_buf->handle.bo[0], TBM_DEVICE_MM)).u32;
307 mm_video_buf->handle.dmabuf_fd[1] = (tbm_bo_get_handle(mm_video_buf->handle.bo[1], TBM_DEVICE_MM)).u32;
308 mm_video_buf->data[0] = (tbm_bo_map(mm_video_buf->handle.bo[0], TBM_DEVICE_CPU,TBM_OPTION_WRITE)).ptr;
309 mm_video_buf->data[1] = (tbm_bo_map(mm_video_buf->handle.bo[1], TBM_DEVICE_CPU,TBM_OPTION_WRITE)).ptr;
310 /* Setting stride height & width for Y plane */
311 mm_video_buf->stride_height[0] = mm_video_buf->height[0] = height;
312 mm_video_buf->stride_width[0] = mm_video_buf->width[0] = width;
313 /* Setting stride height & width for UV plane */
314 mm_video_buf->stride_height[1] = mm_video_buf->height[1] = height >> 1;
315 mm_video_buf->stride_width[1] = mm_video_buf->width[1] = width;
317 mem = gst_memory_new_wrapped(0,
318 mm_data, sizeof(MMVideoBuffer), 0, sizeof(MMVideoBuffer), mm_data, g_free);
319 GST_DEBUG("[%s] Appending 2 memory to gst buffer.",__FUNCTION__);
320 gst_buffer_append_memory(buf, mem);
324 pool->current_buffer_index++;
331 gst_mm_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
333 MMVideoBuffer *mm_video_buf = NULL;
334 GstMemory *mem = NULL;
335 void *mm_data = NULL;
336 GstMMBufferPool *pool = GST_MM_BUFFER_POOL (bpool);
338 /* If the buffers belong to another pool, restore them now */
339 GST_OBJECT_LOCK (pool);
340 if (pool->other_pool) {
341 gst_object_replace ((GstObject **) & buffer->pool,
342 (GstObject *) pool->other_pool);
344 GST_OBJECT_UNLOCK (pool);
346 gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
347 gst_mm_buffer_data_quark, NULL, NULL);
349 #ifdef USE_TBM_BUFFER
351 GstMapInfo map_info = GST_MAP_INFO_INIT;
352 mem = gst_buffer_peek_memory (buffer, 1);
354 gst_memory_map(mem, &map_info, GST_MAP_READ);
355 mm_data = map_info.data;
356 gst_memory_unmap(mem, &map_info);
357 mm_video_buf = (MMVideoBuffer*) mm_data;
358 if(mm_video_buf != NULL && mm_video_buf->handle.bo[0] != NULL) {
359 tbm_bo_unmap(mm_video_buf->handle.bo[0]);
360 tbm_bo_unref(mm_video_buf->handle.bo[0]);
362 if(mm_video_buf != NULL && mm_video_buf->handle.bo[1] != NULL) {
363 tbm_bo_unmap(mm_video_buf->handle.bo[1]);
364 tbm_bo_unref(mm_video_buf->handle.bo[1]);
369 GST_BUFFER_POOL_CLASS (gst_mm_buffer_pool_parent_class)->free_buffer (bpool,
374 gst_mm_buffer_pool_acquire_buffer (GstBufferPool * bpool,
375 GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
378 GstMMBuffer *temp = NULL;
379 GstMMVideoMemory *temp_video_memory = NULL;
380 GstMMBufferPool *pool = GST_MM_BUFFER_POOL (bpool);
385 n = pool->buffers->len;
386 if(g_queue_is_empty(pool->mm_buffers)) {
387 GST_ERROR(" mm_buffers is queue is empty.");
388 return GST_FLOW_ERROR;
390 temp = g_queue_pop_head(pool->mm_buffers);
391 for(i = 0; i < n; i++) {
392 temp_video_memory = g_ptr_array_index(pool->buffers,i);
393 temp_video_memory->mm_video_buffer = gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (temp_video_memory),
394 gst_mm_buffer_data_quark);
395 if(temp_video_memory->mm_video_buffer == temp)
399 GST_ERROR(": mm_buffer is not found in buffers list.");
400 return GST_FLOW_ERROR;
403 pool->current_buffer_index = i;
404 g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR);
405 GST_DEBUG(" Acquiring buffer at index:[%d]",pool->current_buffer_index);
406 buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index);
407 GST_DEBUG("\ buffer:[%p]",buf);
408 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
416 gst_mm_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
418 GstMMBufferPool *pool = GST_MM_BUFFER_POOL (bpool);
421 if (!pool->allocating && !pool->deactivated) {
423 gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
424 gst_mm_buffer_data_quark);
426 g_queue_push_tail(pool->mm_buffers, mm_buf);
432 gst_mm_buffer_pool_finalize (GObject * object)
434 GstMMBufferPool *pool = GST_MM_BUFFER_POOL (object);
437 gst_object_unref (pool->element);
438 pool->element = NULL;
441 g_ptr_array_unref (pool->buffers);
442 pool->buffers = NULL;
444 if (pool->other_pool)
445 gst_object_unref (pool->other_pool);
446 pool->other_pool = NULL;
449 gst_object_unref (pool->allocator);
450 pool->allocator = NULL;
453 gst_caps_unref (pool->caps);
456 G_OBJECT_CLASS (gst_mm_buffer_pool_parent_class)->finalize (object);
460 gst_mm_buffer_pool_class_init (GstMMBufferPoolClass * klass)
462 GObjectClass *gobject_class = (GObjectClass *) klass;
463 GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
465 gst_mm_buffer_data_quark = g_quark_from_static_string ("GstMMBufferData");
467 gobject_class->finalize = gst_mm_buffer_pool_finalize;
468 gstbufferpool_class->start = gst_mm_buffer_pool_start;
469 gstbufferpool_class->stop = gst_mm_buffer_pool_stop;
470 gstbufferpool_class->get_options = gst_mm_buffer_pool_get_options;
471 gstbufferpool_class->set_config = gst_mm_buffer_pool_set_config;
472 gstbufferpool_class->alloc_buffer = gst_mm_buffer_pool_alloc_buffer;
473 gstbufferpool_class->free_buffer = gst_mm_buffer_pool_free_buffer;
474 gstbufferpool_class->acquire_buffer = gst_mm_buffer_pool_acquire_buffer;
475 gstbufferpool_class->release_buffer = gst_mm_buffer_pool_release_buffer;
479 gst_mm_buffer_pool_init (GstMMBufferPool * pool)
482 pool->buffers = g_ptr_array_new ();
483 pool->allocator = g_object_new (gst_mm_memory_allocator_get_type (), NULL);
484 pool->other_pool = NULL;
485 pool->mm_buffers = g_queue_new();
487 #ifdef USE_TBM_BUFFER
488 pool->hTBMBufMgr = tbm_bufmgr_init(-1);
489 if(pool->hTBMBufMgr == NULL) {
490 GST_ERROR ("TBM initialization failed.");
497 gst_mm_buffer_pool_new (GstElement * trans )
499 GstMMBufferPool *pool;
500 GstVideoFilter *filter = GST_VIDEO_FILTER_CAST (trans);
502 pool = g_object_new (gst_mm_buffer_pool_get_type (), NULL);
503 pool->video_info = filter->out_info;
505 pool->element = gst_object_ref (trans);
507 return GST_BUFFER_POOL (pool);