2 * GStreamer tizen memory
3 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Author: Sejun Park <sejun79.park@samsung.com>
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.
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.
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.
27 #include "gstdmabuf.h"
28 #include "gsttizenmemory.h"
29 #include <tbm_surface_internal.h>
31 #define GST_TIZEN_ALLOCATOR_NAME "TizenVideoMemory"
33 GST_DEBUG_CATEGORY_STATIC (gst_tizenmemory_debug);
34 #define GST_CAT_DEFAULT gst_tizenmemory_debug
36 #define parent_class gst_tizen_allocator_parent_class
37 G_DEFINE_TYPE_WITH_CODE (GstTizenAllocator, gst_tizen_allocator, GST_TYPE_ALLOCATOR,
38 G_ADD_PRIVATE (GstTizenAllocator);
39 GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "tizenmemory", 0,
40 "GstTizenMemory and GstTizenAllocator"));
45 GstVideoFormat vformat; /* Gst video format */
46 GstVideoFormat nformat; /* Gst native video format */
47 } GstTizenBufferFormats;
49 static void cached_tizen_disposed_cb (GstTizenAllocator * allocator, GstMiniObject *obj);
51 GstTizenBufferFormats yuv_formats[] = {
52 {TBM_FORMAT_YUV420, GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_S420},
53 {TBM_FORMAT_NV21, GST_VIDEO_FORMAT_NV21, GST_VIDEO_FORMAT_SN21},
54 {TBM_FORMAT_NV12, GST_VIDEO_FORMAT_NV12, GST_VIDEO_FORMAT_SN12},
55 {TBM_FORMAT_YUYV, GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_SUYV},
56 {TBM_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY, GST_VIDEO_FORMAT_SYVY},
57 {TBM_FORMAT_ARGB8888, GST_VIDEO_FORMAT_ARGB, GST_VIDEO_FORMAT_SR32}
61 * gst_video_format_to_tbm_format: (skip)
62 * @format: a #GstVideoFormat to be converted
64 * Return: a #tbm_format which is converted from @format.
67 gst_video_format_to_tbm_format (GstVideoFormat format)
71 for (i = 0; i < G_N_ELEMENTS (yuv_formats); i++) {
72 if (yuv_formats[i].nformat == format)
73 return yuv_formats[i].format;
78 static GstTizenMemory *
79 _tizen_video_mem_new (GstAllocator * allocator, GstMemory * parent, GstVideoInfo * vinfo,
80 tbm_surface_h surface, gpointer user_data, GDestroyNotify notify)
87 tbm_surface_info_s sinfo;
91 GST_ERROR ("invalid vinfo");
95 tmem = g_slice_new0 (GstTizenMemory);
97 /* Creates the tbm_surface with buffer objects. */
99 tbm_surface_internal_ref (surface);
100 tmem->surface = surface;
102 width = GST_VIDEO_INFO_WIDTH (vinfo);
103 height = GST_VIDEO_INFO_HEIGHT (vinfo);
104 format = gst_video_format_to_tbm_format (GST_VIDEO_INFO_FORMAT (vinfo));
105 tmem->surface = tbm_surface_internal_create_with_flags (width, height, format, TBM_BO_NONCACHABLE);
108 if (!tbm_surface_internal_is_valid (tmem->surface)) {
109 GST_ERROR ("Invalid tbm surface");
110 g_slice_free (GstTizenMemory, tmem);
114 tbm_surface_get_info (tmem->surface, &sinfo);
116 for (i = 0; i < sinfo.num_planes; i++) {
117 GST_VIDEO_INFO_PLANE_STRIDE (vinfo, i) = sinfo.planes[i].stride;
118 GST_VIDEO_INFO_PLANE_OFFSET (vinfo, i) = sinfo.planes[i].offset;
119 GST_DEBUG ("tbm surface plane[%d][%p]", i, sinfo.planes[i].ptr);
122 GST_VIDEO_INFO_SIZE (vinfo) = sinfo.size;
124 num_bos = tbm_surface_internal_get_num_bos (tmem->surface);
126 for (i = 0 ; i < num_bos ; i++) {
127 tmem->fd[i] = tbm_bo_export_fd (tbm_surface_internal_get_bo (tmem->surface, i));
128 if (tmem->fd[i] < 0) {
129 GST_ERROR ("fd export failed for bo[%d] %p",
130 i, tbm_surface_internal_get_bo (tmem->surface, i));
132 for (j = i - 1 ; j >= 0 ; j--) {
133 GST_WARNING ("close exported fd[%d] %d", j, tmem->fd[j]);
137 tbm_surface_internal_unref (tmem->surface);
138 g_slice_free (GstTizenMemory, tmem);
142 GST_DEBUG ("exported fd[%d] %d", i, tmem->fd[i]);
145 gst_memory_init (GST_MEMORY_CAST (tmem), 0,
146 allocator, parent, GST_VIDEO_INFO_SIZE (vinfo), 0, 0,
147 GST_VIDEO_INFO_SIZE (vinfo));
149 tmem->info = gst_video_info_copy (vinfo);
150 tmem->notify = notify;
151 tmem->user_data = user_data;
152 tmem->fd_count = num_bos;
153 tmem->is_fd_exported = TRUE;
155 g_mutex_init (&tmem->lock);
157 GST_DEBUG ("mem[%p], surface[%p], size[%" G_GSIZE_FORMAT"]",
158 tmem, tmem->surface, tmem->mem.maxsize);
163 static GstTizenMemory *
164 _tizen_video_mem_new2 (GstAllocator * allocator, GstMemory * parent, GstVideoInfo * vinfo,
165 tbm_bo bo, gsize size, gpointer user_data, GDestroyNotify notify)
167 int bo_size = tbm_bo_size (bo);
169 GstTizenMemory *tmem;
172 GST_ERROR ("invalid vinfo");
176 if (size > bo_size) {
177 GST_ERROR ("size[%"G_GSIZE_FORMAT"] can not exceed bo size[%d]",
182 bo = tbm_bo_ref (bo);
184 GST_ERROR ("invalid bo");
188 fd = tbm_bo_export_fd (bo);
190 GST_ERROR ("export fd failed from bo[%p]", bo);
195 tmem = g_slice_new0 (GstTizenMemory);
197 gst_memory_init (GST_MEMORY_CAST (tmem), 0,
198 allocator, parent, bo_size, 0, 0, size);
201 tmem->info = gst_video_info_copy (vinfo);
202 tmem->notify = notify;
203 tmem->user_data = user_data;
206 tmem->is_fd_exported = TRUE;
207 GST_VIDEO_INFO_SIZE (tmem->info) = size;
209 g_mutex_init (&tmem->lock);
211 GST_DEBUG ("mem[%p], bo[%p], size[%" G_GSIZE_FORMAT"], max[%" G_GSIZE_FORMAT"]",
212 tmem, tmem->bo, tmem->mem.size, tmem->mem.maxsize);
217 static GstTizenMemory *
218 _tizen_video_mem_new3 (GstAllocator * allocator, GstMemory * parent, GstVideoInfo * vinfo,
219 tbm_surface_info_s * tsinfo, int fd[GST_TIZEN_MEMORY_MAX_FD], int fd_count,
220 gpointer user_data, GDestroyNotify notify)
223 tbm_bo bos[GST_TIZEN_MEMORY_MAX_FD] = {NULL, };
224 tbm_surface_h surface = NULL;
225 GstTizenMemory *tmem;
226 GstTizenAllocator *tallocator = GST_TIZEN_ALLOCATOR (allocator);
228 if (!vinfo || !tsinfo || fd_count < 1 || fd_count > GST_TIZEN_MEMORY_MAX_FD) {
229 GST_ERROR ("invalid param[vinfo:%p,tsinfo:%p, fd_count:%d]", vinfo, tsinfo, fd_count);
233 if (!tallocator->bufmgr) {
234 GST_ERROR ("No TBM bufmgr");
238 for (i = 0 ; i < fd_count ; i++) {
239 bos[i] = tbm_bo_import_fd (tallocator->bufmgr, fd[i]);
241 GST_ERROR ("failed to import fd[%d]", fd[i]);
242 goto _TIZEN_VIDEO_MEM_NEW3_FAILED;
246 surface = tbm_surface_internal_create_with_bos (tsinfo, bos, fd_count);
248 GST_ERROR ("failed to create surface");
249 goto _TIZEN_VIDEO_MEM_NEW3_FAILED;
252 tmem = g_slice_new0 (GstTizenMemory);
254 gst_memory_init (GST_MEMORY_CAST (tmem), 0,
255 allocator, parent, tsinfo->size, 0, 0, tsinfo->size);
257 /* bos[] will be kept in tbm surface and released when surface is released finally. */
258 for (i = 0 ; i < fd_count ; i++) {
259 tbm_bo_unref (bos[i]);
264 tmem->surface = surface;
265 tmem->fd_count = fd_count;
266 tmem->info = gst_video_info_copy (vinfo);
267 tmem->notify = notify;
268 tmem->user_data = user_data;
269 tmem->is_fd_exported = FALSE;
271 GST_VIDEO_INFO_SIZE (tmem->info) = tsinfo->size;
273 g_mutex_init (&tmem->lock);
275 GST_DEBUG ("mem[%p], fd[0][%d], fd_count[%d], size[%" G_GSIZE_FORMAT"], max[%" G_GSIZE_FORMAT"]",
276 tmem, tmem->fd[0], tmem->fd_count, tmem->mem.size, tmem->mem.maxsize);
280 _TIZEN_VIDEO_MEM_NEW3_FAILED:
281 for (i = 0 ; i < fd_count && bos[i] ; i++)
282 tbm_bo_unref (bos[i]);
288 gst_tizen_mem_free (GstAllocator * allocator, GstMemory * mem)
291 GstTizenMemory *tmem = (GstTizenMemory *) mem;
293 if (tmem->is_fd_exported) {
294 for (i = 0 ; i < tmem->fd_count && tmem->fd[i] >= 0 ; i++) {
295 GST_DEBUG ("close exported fd[%d] %d", i, tmem->fd[i]);
302 GST_DEBUG ("unref bo[%p] from mem[%p]", tmem->bo, tmem);
303 tbm_bo_unref (tmem->bo);
308 GST_DEBUG ("unref surface[%p] from mem[%p]", tmem->surface, tmem);
309 tbm_surface_internal_unref (tmem->surface);
310 tmem->surface = NULL;
314 tmem->notify (tmem->user_data);
316 gst_video_info_free (tmem->info);
317 g_mutex_clear (&tmem->lock);
318 g_slice_free (GstTizenMemory, tmem);
322 gst_tizen_mem_map (GstMemory * gmem, gsize maxsize, GstMapFlags flags)
326 gpointer data = NULL;
327 GstTizenMemory *tmem;
328 tbm_surface_info_s info = {0, };
329 tbm_bo_handle bo_handle = {NULL, };
331 tmem = (GstTizenMemory *)gmem;
333 g_mutex_lock (&tmem->lock);
336 GST_DEBUG ("map surface[%p] in mem[%p]", tmem->surface, tmem);
338 if (flags & GST_MAP_READ)
339 tbm_opt |= TBM_SURF_OPTION_READ;
340 if (flags & GST_MAP_WRITE)
341 tbm_opt |= TBM_SURF_OPTION_WRITE;
343 tbm_ret = tbm_surface_map (tmem->surface, tbm_opt, &info);
344 if (tbm_ret != TBM_SURFACE_ERROR_NONE) {
345 GST_ERROR ("tbm_surface_map failed[0x%x]", tbm_ret);
349 data = (gpointer) info.planes[0].ptr;
351 GST_DEBUG ("map bo[%p] in mem[%p]", tmem->bo, tmem);
353 if (flags & GST_MAP_READ)
354 tbm_opt |= TBM_OPTION_READ;
355 if (flags & GST_MAP_WRITE)
356 tbm_opt |= TBM_OPTION_WRITE;
358 bo_handle = tbm_bo_map (tmem->bo, TBM_DEVICE_CPU, tbm_opt);
359 if (!bo_handle.ptr) {
360 GST_ERROR ("tbm_bo_map failed for bo[%p]", tmem->bo);
364 data = (gpointer) bo_handle.ptr;
368 g_mutex_unlock (&tmem->lock);
374 gst_tizen_mem_unmap (GstMemory * gmem)
376 GstTizenMemory *tmem;
378 tmem = (GstTizenMemory *)gmem;
380 g_mutex_lock (&tmem->lock);
383 GST_DEBUG ("unmap surface[%p] in mem[%p]", tmem->surface, tmem);
384 tbm_surface_unmap (tmem->surface);
386 GST_DEBUG ("unmap bo[%p] in mem[%p]", tmem->bo, tmem);
387 tbm_bo_unmap (tmem->bo);
390 g_mutex_unlock (&tmem->lock);
394 gst_tizen_allocator_finalize (GObject *obj)
396 GstTizenAllocator *allocator;
399 allocator = GST_TIZEN_ALLOCATOR (obj);
401 iter = allocator->priv->mem_cache;
404 GstMiniObject *obj = iter->data;
405 gst_mini_object_weak_unref (obj,
406 (GstMiniObjectNotify) cached_tizen_disposed_cb, allocator);
408 gst_mini_object_set_qdata (obj,
409 g_quark_from_static_string ("tizenmem"), NULL, NULL);
413 g_list_free (allocator->priv->mem_cache);
414 allocator->priv->mem_cache = NULL;
416 tbm_bufmgr_deinit (allocator->bufmgr);
417 allocator->bufmgr = NULL;
419 G_OBJECT_CLASS (parent_class)->finalize (obj);
423 gst_tizen_mem_share (GstMemory * gmem, gssize offset, gssize size)
425 GST_WARNING ("not supported");
430 gst_tizen_mem_copy (GstMemory * gmem, gssize offset, gsize size)
433 GstMemory *copy = NULL;
434 GstTizenMemory *tmem = (GstTizenMemory *) gmem;
436 GST_DEBUG ("copy mem[%p], offset[%"G_GSSIZE_FORMAT"], size[%"G_GSIZE_FORMAT"]",
440 tbm_surface_h new_surface, old_surface;
442 tbm_surface_info_s old_surface_info;
443 tbm_surface_info_s new_surface_info;
445 old_surface = tmem->surface;
446 format = tbm_surface_get_format (old_surface);
448 copy = gst_tizen_allocator_alloc (gmem->allocator, tmem->info);
449 new_surface = gst_tizen_memory_get_surface (copy);
451 tbm_surface_get_info (old_surface, &old_surface_info);
452 tbm_surface_get_info (new_surface, &new_surface_info);
454 for (i = 0; i < tbm_surface_internal_get_num_planes (format); i++) {
455 memcpy (new_surface_info.planes[i].ptr,
456 old_surface_info.planes[i].ptr, new_surface_info.planes[i].size);
459 int old_size = tbm_bo_size (tmem->bo);
460 tbm_bo new_bo = NULL;
461 tbm_bo_handle old_handle = {NULL, };
462 tbm_bo_handle new_handle = {NULL, };
463 tbm_bufmgr bufmgr = NULL;
465 if (size > old_size - offset) {
466 GST_ERROR ("invalid size[%"G_GSIZE_FORMAT"] (offset[%"G_GSSIZE_FORMAT"],bo size[%d])",
467 size, offset, old_size);
471 bufmgr = tbm_bufmgr_init (-1);
473 GST_ERROR ("tbm bufmgr failed");
477 new_bo = tbm_bo_alloc (bufmgr, tbm_bo_size (tmem->bo), TBM_BO_DEFAULT);
479 GST_ERROR ("tbm_bo_alloc failed");
483 old_handle = tbm_bo_map (tmem->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
484 new_handle = tbm_bo_map (new_bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
486 if (!old_handle.ptr || !new_handle.ptr) {
487 GST_ERROR ("tbm bo map failed[old:%p,new:%p]",
488 old_handle.ptr, new_handle.ptr);
492 memcpy (new_handle.ptr, (char *) old_handle.ptr + offset, size);
494 copy = gst_tizen_allocator_alloc_bo (gmem->allocator,
495 tmem->info, new_bo, size, NULL, NULL);
499 tbm_bo_unmap (tmem->bo);
502 tbm_bo_unmap (new_bo);
505 tbm_bo_unref (new_bo);
508 tbm_bufmgr_deinit (bufmgr);
515 gst_tizen_allocator_class_init (GstTizenAllocatorClass * klass)
517 GObjectClass *object_class;
518 GstAllocatorClass *allocator_class;
520 allocator_class = GST_ALLOCATOR_CLASS (klass);
521 object_class = G_OBJECT_CLASS (klass);
523 allocator_class->alloc = NULL;
524 allocator_class->free = gst_tizen_mem_free;
526 object_class->finalize = gst_tizen_allocator_finalize;
530 gst_tizen_allocator_init (GstTizenAllocator * allocator)
532 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
534 allocator->priv = gst_tizen_allocator_get_instance_private (allocator);
535 alloc->mem_type = GST_TIZEN_MEMORY_TYPE;
536 alloc->mem_map = (GstMemoryMapFunction) gst_tizen_mem_map;
537 alloc->mem_unmap = (GstMemoryUnmapFunction) gst_tizen_mem_unmap;
538 alloc->mem_share = (GstMemoryShareFunction) gst_tizen_mem_share;
539 alloc->mem_copy = (GstMemoryCopyFunction) gst_tizen_mem_copy;
541 GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
543 allocator->bufmgr = tbm_bufmgr_init (-1);
544 if (!allocator->bufmgr)
545 GST_ERROR ("TBM bufmgr failed");
549 * gst_tizen_allocator_new:
551 * Return a new tizen allocator.
553 * Returns: (transfer full): a new fd allocator, or NULL if the allocator
554 * isn't available. Use gst_object_unref() to release the allocator after
559 gst_tizen_allocator_new (void)
561 return g_object_new (GST_TYPE_TIZEN_ALLOCATOR, NULL);
565 * gst_tizen_allocator_alloc:
566 * @allocator: a #GstAllocator to use
567 * @vinfo: a #GstVideoInfo to be referred for size and type of allocated memory
569 * Returns: (transfer full) (nullable): a new #GstMemory.
572 gst_tizen_allocator_alloc (GstAllocator * allocator, GstVideoInfo * vinfo)
574 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (allocator), NULL);
576 return (GstMemory *)_tizen_video_mem_new (allocator, NULL, vinfo, NULL, NULL, NULL);
580 * gst_tizen_allocator_alloc_surface: (skip)
581 * @allocator: a #GstAllocator to use
582 * @vinfo: a #GstVideoInfo to be referred for memory size and type
583 * @surface: a #tbm_surface_h to be used for allocated memory
584 * @user_data: (allow-none): user data pointer
585 * @notify: (allow-none) (closure user_data): called with @user_data when the memory is freed
587 * Returns: (transfer full) (nullable): a new #GstMemory.
590 gst_tizen_allocator_alloc_surface (GstAllocator * allocator, GstVideoInfo * vinfo,
591 tbm_surface_h surface, gpointer user_data, GDestroyNotify notify)
593 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (allocator), NULL);
595 return (GstMemory *)_tizen_video_mem_new (allocator, NULL, vinfo, surface, user_data, notify);
599 * gst_tizen_allocator_alloc_bo: (skip)
600 * @allocator: a #GstAllocator to use
601 * @vinfo: a #GstVideoInfo to be referred for memory size and type
602 * @bo: a #tbm_bo to be used for allocated memory
603 * @size: size of used memory in @bo, it should not be bigger than size of bo
604 * @user_data: (allow-none): user data pointer
605 * @notify: (allow-none) (closure user_data): called with @user_data when the memory is freed
607 * Returns: (transfer full) (nullable): a new #GstMemory.
610 gst_tizen_allocator_alloc_bo (GstAllocator * allocator, GstVideoInfo * vinfo,
611 tbm_bo bo, gsize size, gpointer user_data, GDestroyNotify notify)
613 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (allocator), NULL);
615 return (GstMemory *)_tizen_video_mem_new2 (allocator, NULL, vinfo, bo, size, user_data, notify);
619 * gst_tizen_allocator_alloc_fd: (skip)
620 * @allocator: a #GstAllocator to use
621 * @vinfo: a #GstVideoInfo to be referred for memory size and type
622 * @tsinfo: a #tbm_surface_info_s to be referred for information of TBM surface
623 * @fd: fd list to be used for allocated memory
624 * @fd_count: a count of fd in list
625 * @user_data: (allow-none): user data pointer
626 * @notify: (allow-none) (closure user_data): called with @user_data when the memory is freed
628 * Returns: (transfer full) (nullable): a new #GstMemory.
631 gst_tizen_allocator_alloc_fd (GstAllocator * allocator, GstVideoInfo * vinfo,
632 tbm_surface_info_s * tsinfo, int fd[GST_TIZEN_MEMORY_MAX_FD], int fd_count,
633 gpointer user_data, GDestroyNotify notify)
635 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (allocator), NULL);
637 return (GstMemory *)_tizen_video_mem_new3 (allocator, NULL, vinfo, tsinfo, fd, fd_count, user_data, notify);
641 gst_is_tizen_memory (GstMemory * mem)
643 g_return_val_if_fail (mem != NULL, FALSE);
645 return GST_IS_TIZEN_ALLOCATOR (mem->allocator);
649 gst_tizen_memory_get_num_bos (GstMemory *mem)
651 GstTizenMemory *tmem;
653 g_return_val_if_fail (mem != NULL, -1);
654 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (mem->allocator), -1);
656 tmem = (GstTizenMemory *)mem;
658 return (gint) tbm_surface_internal_get_num_bos (tmem->surface);
662 gst_tizen_memory_get_bos (GstMemory * mem, gint bo_idx)
665 GstTizenMemory *tmem;
667 g_return_val_if_fail (mem != NULL, NULL);
668 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (mem->allocator), NULL);
670 tmem = (GstTizenMemory *)mem;
673 bo_num = tbm_surface_internal_get_num_bos(tmem->surface);
674 if (bo_idx >= bo_num) {
675 GST_ERROR ("invalid idx[%d] for surface[bo_num:%d]", bo_idx, bo_num);
679 return tbm_surface_internal_get_bo(tmem->surface, bo_idx);
683 GST_ERROR ("invalid idx[%d] for bo", bo_idx);
691 gst_tizen_memory_get_surface (GstMemory * mem)
693 GstTizenMemory *tmem;
695 g_return_val_if_fail (mem != NULL, NULL);
696 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (mem->allocator), NULL);
698 tmem = (GstTizenMemory *)mem;
700 GST_DEBUG ("surface[%p] in mem[%p]", tmem->surface, tmem);
702 return tmem->surface;
706 gst_tizen_memory_get_num_fd (GstMemory * mem)
708 GstTizenMemory *tmem;
710 g_return_val_if_fail (mem != NULL, -1);
711 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (mem->allocator), -1);
713 tmem = (GstTizenMemory *)mem;
715 GST_DEBUG ("fd count[%d] in mem[%p]", tmem->fd_count, tmem);
717 return tmem->fd_count;
721 gst_tizen_memory_get_fd (GstMemory * mem, gint index)
723 GstTizenMemory *tmem = (GstTizenMemory *)mem;
725 g_return_val_if_fail (mem != NULL, -1);
726 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (mem->allocator), -1);
727 g_return_val_if_fail (index >= 0 && index < tmem->fd_count, -1);
729 GST_DEBUG ("fd[%d] %d in mem[%p]", index, tmem->fd[index], tmem);
731 return tmem->fd[index];
735 cached_tizen_disposed_cb (GstTizenAllocator * allocator, GstMiniObject *obj)
737 allocator->priv->mem_cache = g_list_remove (allocator->priv->mem_cache, obj);
741 gst_tizen_allocator_dmabuf_export (GstAllocator * allocator, GstMemory * _tmem, int bo_idx)
743 GstTizenMemory *tmem = (GstTizenMemory *) _tmem;
744 GstTizenAllocator *tallocator = GST_TIZEN_ALLOCATOR (allocator);
749 g_return_val_if_fail (tmem->surface != NULL, NULL);
751 bo = tbm_surface_internal_get_bo (tmem->surface, bo_idx);
752 fd = tbm_bo_export_fd (bo);
754 tallocator->priv->dmabuf_alloc = gst_dmabuf_allocator_new ();
756 mem = gst_dmabuf_allocator_alloc (tallocator->priv->dmabuf_alloc, fd,
757 gst_memory_get_sizes (_tmem, NULL, NULL));
760 gst_mini_object_weak_ref (GST_MINI_OBJECT (mem),
761 (GstMiniObjectNotify) cached_tizen_disposed_cb, tallocator);
763 tallocator->priv->mem_cache = g_list_prepend (tallocator->priv->mem_cache, mem);
765 gst_mini_object_set_qdata (GST_MINI_OBJECT (mem),
766 g_quark_from_static_string ("_tmem"), _tmem,
767 (GDestroyNotify) gst_memory_unref);
772 * gst_tizen_allocator_dmabuf_import: (skip)
773 * @allocator: a #GstAllocator to use
774 * @fds: fd array to be imported to #GstTizenMemory
775 * @planes: a number of planes
776 * @offsets: offset array
777 * @vinfo: a #GstVideoInfo to be refered
779 * Returns: (transfer full) (nullable): a new #GstTizenMemory.
782 gst_tizen_allocator_dmabuf_import (GstAllocator * allocator, gint * fds, gint planes, gsize offsets[4], GstVideoInfo * vinfo)
784 GstTizenMemory *tmem;
787 tmem = g_slice_new0 (GstTizenMemory);
789 mem = GST_MEMORY_CAST (tmem);
791 gst_memory_init (mem, 0, allocator, NULL,
792 GST_VIDEO_INFO_SIZE (vinfo), 0, 0, GST_VIDEO_INFO_SIZE (vinfo));
798 * gst_tizen_video_meta_map:
799 * @meta: a #GstVideoMeta
801 * @info: a #GstMapInfo
802 * @data: (out): the data of @plane
803 * @stride: (out): the stride of @plane
804 * @flags: @GstMapFlags
806 * Returns: TRUE if the map operation was successful.
809 gst_tizen_video_meta_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
810 gpointer * data, gint * stride, GstMapFlags flags)
812 int tbm_ret = TBM_SURFACE_ERROR_NONE;
814 gboolean mapped = FALSE;
815 GstBuffer *buffer = meta->buffer;
816 GstTizenMemory *tmem = (GstTizenMemory *) gst_buffer_get_memory (buffer, 0);
818 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (((GstMemory *) tmem)->allocator), FALSE);
820 if (!tmem->surface || plane >= GST_VIDEO_MAX_PLANES) {
821 GST_ERROR ("invalid param[surface:%p,plane:%u]", tmem->surface, plane);
825 g_mutex_lock (&tmem->lock);
827 if (tmem->video_memory_map[plane]) {
828 GST_ERROR ("buf[%p] plane[%d] is already mapped", buffer, plane);
829 goto _VIDEO_MEMORY_MAP_DONE;
832 if (tmem->video_memory_map_count == 0) {
833 if (flags & GST_MAP_READ)
834 tbm_opt |= TBM_SURF_OPTION_READ;
835 if (flags & GST_MAP_WRITE)
836 tbm_opt |= TBM_SURF_OPTION_WRITE;
838 tbm_ret = tbm_surface_map (tmem->surface, tbm_opt, &tmem->surface_info);
839 if (tbm_ret != TBM_SURFACE_ERROR_NONE) {
840 GST_ERROR ("buf[%p] tbm_surface_map[%p] failed[0x%x]",
841 buffer, tmem->surface, tbm_ret);
842 goto _VIDEO_MEMORY_MAP_DONE;
846 if (plane >= tmem->surface_info.num_planes) {
847 GST_ERROR ("buf[%p] invalid plane index[%d] (num plane[%d])",
848 buffer, plane, tmem->surface_info.num_planes);
850 if (tmem->video_memory_map_count == 0) {
851 GST_ERROR ("buf[%p] unmap surface[%p]", buffer, tmem->surface);
852 tbm_surface_unmap (tmem->surface);
855 goto _VIDEO_MEMORY_MAP_DONE;
858 *data = tmem->surface_info.planes[plane].ptr;
859 *stride = tmem->surface_info.planes[plane].stride;
861 tmem->video_memory_map[plane] = TRUE;
862 tmem->video_memory_map_count++;
867 GST_DEBUG ("buf[%p] plane[%d], data[%p], stride[%d], flags[0x%x]",
868 buffer, plane, *data, *stride, info->flags);
872 _VIDEO_MEMORY_MAP_DONE:
873 g_mutex_unlock (&tmem->lock);
879 * gst_tizen_video_meta_unmap:
880 * @meta: a #GstVideoMeta
882 * @info: a #GstMapInfo
884 * Returns: TRUE if the memory was successfully unmapped.
887 gst_tizen_video_meta_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
889 int tbm_ret = TBM_SURFACE_ERROR_NONE;
890 gboolean unmapped = FALSE;
891 GstBuffer *buffer = meta->buffer;
892 GstTizenMemory *tmem = (GstTizenMemory *) gst_buffer_get_memory (buffer, 0);
894 g_return_val_if_fail (GST_IS_TIZEN_ALLOCATOR (((GstMemory *) tmem)->allocator), FALSE);
896 if (!tmem->surface) {
897 GST_ERROR ("no surface");
901 g_mutex_lock (&tmem->lock);
903 if (tmem->video_memory_map[plane] == FALSE) {
904 GST_ERROR ("buf[%p] plane[%d] is already unmapped",
906 goto _VIDEO_MEMORY_UNMAP_DONE;
909 if (tmem->video_memory_map_count > 1) {
910 GST_DEBUG ("buf[%p] plane[%d] skip unmap surface[%p]",
911 buffer, plane, tmem->surface);
913 goto _VIDEO_MEMORY_UNMAP_DONE;
916 tbm_ret = tbm_surface_unmap (tmem->surface);
917 if (tbm_ret != TBM_SURFACE_ERROR_NONE) {
918 GST_ERROR ("buf[%p] tbm_surface_unmap[%p] failed[0x%x]",
919 buffer, tmem->surface, tbm_ret);
920 goto _VIDEO_MEMORY_UNMAP_DONE;
925 GST_DEBUG ("buf[%p] plane[%d] unmap surface[%p] done",
926 buffer, plane, tmem->surface);
928 _VIDEO_MEMORY_UNMAP_DONE:
929 if (unmapped == TRUE) {
930 tmem->video_memory_map[plane] = FALSE;
931 tmem->video_memory_map_count--;
934 g_mutex_unlock (&tmem->lock);