[v4l2videodecoder] Support TBM for output buffer
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / gstv4l2allocator.c
index 05bde3d..5f6f554 100644 (file)
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <unistd.h>
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
 
 #define GST_V4L2_MEMORY_TYPE "V4l2Memory"
 
@@ -235,6 +239,13 @@ gst_v4l2_memory_group_free (GstV4l2MemoryGroup * group)
     if (mem)
       gst_memory_unref (mem);
   }
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+  if (group->surface) {
+    GST_INFO ("unref surface[%p]", group->surface);
+    tbm_surface_destroy (group->surface);
+    group->surface = NULL;
+  }
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
 
   g_slice_free (GstV4l2MemoryGroup, group);
 }
@@ -428,6 +439,13 @@ gst_v4l2_allocator_finalize (GObject * obj)
   GstV4l2Allocator *allocator = (GstV4l2Allocator *) obj;
 
   GST_LOG_OBJECT (obj, "called");
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+  if (allocator->bufmgr) {
+    GST_INFO_OBJECT (obj, "deinit tbm bufmgr %p", allocator->bufmgr);
+    tbm_bufmgr_deinit (allocator->bufmgr);
+    allocator->bufmgr = NULL;
+  }
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
 
   gst_atomic_queue_unref (allocator->free_queue);
   gst_object_unref (allocator->obj->element);
@@ -620,7 +638,20 @@ _cleanup_failed_alloc (GstV4l2Allocator * allocator, GstV4l2MemoryGroup * group)
   }
 }
 
-
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+static tbm_format __get_tbm_format (GstVideoFormat gst_format)
+{
+  switch (gst_format) {
+  case GST_VIDEO_FORMAT_NV12:
+  case GST_VIDEO_FORMAT_SN12:
+    return TBM_FORMAT_NV12;
+  case GST_VIDEO_FORMAT_I420:
+  case GST_VIDEO_FORMAT_S420:
+  default:
+    return TBM_FORMAT_YUV420;
+  }
+}
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
 
 GstV4l2Allocator *
 gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object)
@@ -660,6 +691,32 @@ gst_v4l2_allocator_new (GstObject * parent, GstV4l2Object * v4l2object)
 
   GST_OBJECT_FLAG_SET (allocator, flags);
 
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+  if (!V4L2_TYPE_IS_OUTPUT (v4l2object->type) &&
+      v4l2object->mode == GST_V4L2_IO_DMABUF) {
+    tbm_surface_h tmp_surface = NULL;
+    int width = GST_VIDEO_INFO_WIDTH (&v4l2object->info);
+    int height = GST_VIDEO_INFO_HEIGHT (&v4l2object->info);
+
+    tmp_surface = tbm_surface_create (width, height,
+        __get_tbm_format (GST_VIDEO_INFO_FORMAT (&v4l2object->info)));
+    if (tmp_surface) {
+      tbm_surface_get_info (tmp_surface, &allocator->s_info);
+      GST_INFO_OBJECT (allocator, "[%dx%d] -> tbm surface info[%dx%d]",
+          width, height, allocator->s_info.width, allocator->s_info.height);
+      tbm_surface_destroy (tmp_surface);
+    } else {
+      GST_ERROR_OBJECT (allocator, "[%dx%d] surface failed", width, height);
+    }
+
+    allocator->bufmgr = tbm_bufmgr_init (-1);
+    if (!allocator->bufmgr) {
+      GST_ERROR_OBJECT (allocator, "tbm bufmgr failed");
+      gst_object_unref (allocator);
+      return NULL;
+    }
+  }
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
   return allocator;
 }
 
@@ -883,6 +940,9 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
   GstV4l2Object *obj = allocator->obj;
   GstV4l2MemoryGroup *group;
   gint i;
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+  tbm_bo bos[VIDEO_MAX_PLANES] = {NULL, };
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
 
   g_return_val_if_fail (allocator->memory == V4L2_MEMORY_MMAP, NULL);
 
@@ -913,6 +973,11 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
           NULL, group->planes[i].length, 0, group->planes[i].data_offset,
           group->planes[i].length - group->planes[i].data_offset, i, NULL,
           expbuf.fd, group);
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+      bos[i] = tbm_bo_import_fd (allocator->bufmgr, expbuf.fd);
+      GST_INFO_OBJECT (allocator, "obj[%p,i:%d]: fd[%d] -> bo[%p]",
+        obj, expbuf.index, expbuf.fd, bos[i]);
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
     } else {
       /* Take back the allocator reference */
       gst_object_ref (allocator);
@@ -934,6 +999,16 @@ gst_v4l2_allocator_alloc_dmabuf (GstV4l2Allocator * allocator,
     group->mem[i] = dma_mem;
   }
 
+#ifdef TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER
+  if (!group->surface) {
+    group->surface = tbm_surface_internal_create_with_bos (&allocator->s_info, bos, group->n_mem);
+    GST_INFO_OBJECT (allocator, "new surface[%p] in memory group[%p]", group->surface, group);
+  }
+  /* release bos - they will be kept in surface. */
+  for (i = 0 ; i < VIDEO_MAX_PLANES && bos[i] ; i++)
+    tbm_bo_unref (bos[i]);
+#endif /* TIZEN_FEATURE_TBM_SUPPORT_FOR_V4L2_DECODER */
+
   gst_v4l2_allocator_reset_size (allocator, group);
 
   return group;