Implement tizen buffer support in shmsink/src
authorHyongtaek Lim <hyongtaek.lim@samsung.com>
Tue, 18 Aug 2015 06:58:13 +0000 (15:58 +0900)
committerHyongtaek Lim <hyongtaek.lim@samsung.com>
Tue, 18 Aug 2015 06:59:02 +0000 (15:59 +0900)
Signed-off-by: Hyongtaek Lim <hyongtaek.lim@samsung.com>
Change-Id: I2bb1df0c50157130d8bcb880aab9c51159f2d893

configure.ac
packaging/gst-plugins-bad.spec
sys/shm/Makefile.am
sys/shm/gstshmsink.c
sys/shm/gstshmsink.h
sys/shm/gstshmsrc.c
sys/shm/gstshmsrc.h

index a1b748c..71a8e4d 100644 (file)
@@ -1773,6 +1773,18 @@ AG_GST_CHECK_FEATURE(SHM, [POSIX shared memory source and sink], shm, [
     fi
 ])
 
+PKG_CHECK_MODULES(DRM, libdrm)
+AC_SUBST(DRM_CFLAGS)
+AC_SUBST(DRM_LIBS)
+
+PKG_CHECK_MODULES(TBM, libtbm)
+AC_SUBST(TBM_CFLAGS)
+AC_SUBST(TBM_LIBS)
+
+PKG_CHECK_MODULES(MMCOMMON, mm-common)
+AC_SUBST(MMCOMMON_CFLAGS)
+
+
 dnl check for Video CD
 translit(dnm, m, l) AM_CONDITIONAL(USE_VCD, true)
 AG_GST_CHECK_FEATURE(VCD, [Video CD], vcdsrc, [
index 739afc6..29d3b3b 100644 (file)
@@ -72,7 +72,7 @@ processing capabilities can be added simply by installing new plug-ins.
 %build
 export V=1
 NOCONFIGURE=1 ./autogen.sh
-export CFLAGS="-DGST_WLSINK_ENHANCEMENT"
+export CFLAGS="-DGST_WLSINK_ENHANCEMENT -DGST_TBM_SUPPORT"
 %configure\
     --disable-static\
     --disable-examples\
index 0031fa3..fd6b934 100644 (file)
@@ -1,9 +1,11 @@
 plugin_LTLIBRARIES = libgstshm.la
 
 libgstshm_la_SOURCES = shmpipe.c shmalloc.c gstshm.c gstshmsrc.c gstshmsink.c
-libgstshm_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS) -DSHM_PIPE_USE_GLIB
+libgstshm_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS) -DSHM_PIPE_USE_GLIB \
+                       $(DRM_CFLAGS) $(TBM_CFLAGS) $(MMCOMMON_CFLAGS)
 libgstshm_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstshm_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(SHM_LIBS)
+libgstshm_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(SHM_LIBS) \
+                       $(DRM_LIBS) $(TBM_LIBS)
 
 libgstshm_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
 
index bb700ca..44c7595 100644 (file)
 
 #include <string.h>
 
+#ifdef GST_TBM_SUPPORT
+#include <mm_types.h>
+#include <tbm_bufmgr.h>
+#endif
+
 /* signals */
 enum
 {
@@ -57,6 +62,9 @@ enum
   PROP_SHM_SIZE,
   PROP_WAIT_FOR_CONNECTION,
   PROP_BUFFER_TIME
+#ifdef GST_TBM_SUPPORT
+  ,PROP_USE_TBM
+#endif
 };
 
 struct GstShmClient
@@ -410,6 +418,14 @@ gst_shm_sink_class_init (GstShmSinkClass * klass)
           "Maximum Size of the shm buffer in nanoseconds (-1 to disable)",
           -1, G_MAXINT64, -1,
           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#ifdef GST_TBM_SUPPORT
+  g_object_class_install_property (gobject_class, PROP_USE_TBM,
+      g_param_spec_boolean ("use-tbm",
+          "Use of not the tizen buffer",
+          "Flags of using tizen buffer",
+          FALSE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
 
   signals[SIGNAL_CLIENT_CONNECTED] = g_signal_new ("client-connected",
       GST_TYPE_SHM_SINK, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -500,6 +516,14 @@ gst_shm_sink_set_property (GObject * object, guint prop_id,
       GST_OBJECT_UNLOCK (object);
       g_cond_broadcast (&self->cond);
       break;
+#ifdef GST_TBM_SUPPORT
+    case PROP_USE_TBM:
+      GST_OBJECT_LOCK (object);
+      self->use_tbm = g_value_get_boolean (value);
+      GST_OBJECT_UNLOCK (object);
+      g_cond_broadcast (&self->cond);
+      break;
+#endif
     default:
       break;
   }
@@ -529,6 +553,11 @@ gst_shm_sink_get_property (GObject * object, guint prop_id,
     case PROP_BUFFER_TIME:
       g_value_set_int64 (value, self->buffer_time);
       break;
+#ifdef GST_TBM_SUPPORT
+    case PROP_USE_TBM:
+      g_value_set_boolean (value, self->use_tbm);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -663,6 +692,11 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
   GstFlowReturn ret = GST_FLOW_OK;
   GstMemory *memory = NULL;
   GstBuffer *sendbuf = NULL;
+  gsize buf_size = gst_buffer_get_size(buf);
+#ifdef GST_TBM_SUPPORT
+  unsigned key[MM_VIDEO_BUFFER_PLANE_MAX];
+  gsize key_size = sizeof(key);
+#endif
 
   GST_OBJECT_LOCK (self);
   while (self->wait_for_connection && !self->clients) {
@@ -678,6 +712,50 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
   }
 
 
+#ifdef GST_TBM_SUPPORT
+  memory = gst_buffer_peek_memory (buf, 0);
+
+  if (memory->allocator != GST_ALLOCATOR (self->allocator)) {
+    need_new_memory = TRUE;
+    GST_LOG_OBJECT (self, "Memory in buffer %p was not allocated by "
+        "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator);
+  }
+  GST_DEBUG_OBJECT(self, "use-tbm %d, #memory in buffer %d", self->use_tbm,
+      gst_buffer_n_memory (buf));
+  if(self->use_tbm && gst_buffer_n_memory (buf) > 1) {
+    /*in case of SN12 or ST12 video  format */
+    MMVideoBuffer *mm_video_buf = NULL;
+
+    memory = gst_buffer_peek_memory (buf, 1);
+    gst_memory_map (memory, &map, GST_MAP_READ);
+    mm_video_buf = (MMVideoBuffer *) map.data;
+
+    if (mm_video_buf == NULL) {
+      GST_ERROR_OBJECT (self, "mm_video_buf is NULL. Skip rendering");
+      gst_memory_unmap (memory, &map);
+      goto flushing;
+    }
+    /* export bo key */
+    if (mm_video_buf->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
+      int i;
+      GST_DEBUG_OBJECT (self, "GstBuffer size %d, tbm bo key size %d",
+          buf_size, key_size);
+      buf_size += key_size;
+      for(i = 0; i < MM_VIDEO_BUFFER_PLANE_MAX; i++) {
+        if(mm_video_buf->handle.bo[i]) {
+          key[i] = tbm_bo_export(mm_video_buf->handle.bo[i]);
+          GST_DEBUG_OBJECT (self, "key %d, bo %p", key[i], mm_video_buf->handle.bo[i]);
+        } else
+          key[i] = 0;
+      }
+      gst_memory_unmap (memory, &map);
+    } else {
+      GST_ERROR_OBJECT (self, "Buffer type is not TBM");
+        gst_memory_unmap (memory, &map);
+        goto flushing;
+    }
+  }
+#else
   if (gst_buffer_n_memory (buf) > 1) {
     GST_LOG_OBJECT (self, "Buffer %p has %d GstMemory, we only support a single"
         " one, need to do a memcpy", buf, gst_buffer_n_memory (buf));
@@ -691,22 +769,23 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
           "%" GST_PTR_FORMAT ", will memcpy", buf, memory->allocator);
     }
   }
+#endif
 
   if (need_new_memory) {
-    if (gst_buffer_get_size (buf) > sp_writer_get_max_buf_size (self->pipe)) {
+    if (buf_size > sp_writer_get_max_buf_size (self->pipe)) {
       gsize area_size = sp_writer_get_max_buf_size (self->pipe);
       GST_OBJECT_UNLOCK (self);
       GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT,
           ("Shared memory area is too small"),
           ("Shared memory area of size %" G_GSIZE_FORMAT " is smaller than"
               "buffer of size %" G_GSIZE_FORMAT, area_size,
-              gst_buffer_get_size (buf)));
+              buf_size));
       return GST_FLOW_ERROR;
     }
 
     while ((memory =
             gst_shm_sink_allocator_alloc_locked (self->allocator,
-                gst_buffer_get_size (buf), &self->params)) == NULL) {
+                buf_size, &self->params)) == NULL) {
       g_cond_wait (&self->cond, GST_OBJECT_GET_LOCK (self));
       if (self->unlock)
         goto flushing;
@@ -723,6 +802,10 @@ gst_shm_sink_render (GstBaseSink * bsink, GstBuffer * buf)
 
     gst_memory_map (memory, &map, GST_MAP_WRITE);
     gst_buffer_extract (buf, 0, map.data, map.size);
+#ifdef GST_TBM_SUPPORT
+    if(self->use_tbm && gst_buffer_n_memory (buf) > 1)
+      memcpy(map.data + map.size - key_size, key, key_size);
+#endif
     gst_memory_unmap (memory, &map);
 
     sendbuf = gst_buffer_new ();
index a514096..1247663 100644 (file)
@@ -69,6 +69,9 @@ struct _GstShmSink
   GstShmSinkAllocator *allocator;
 
   GstAllocationParams params;
+#ifdef GST_TBM_SUPPORT
+  gboolean use_tbm;
+#endif
 };
 
 struct _GstShmSinkClass
index 8af1f34..020cfbe 100644 (file)
@@ -43,6 +43,9 @@
 
 #include <string.h>
 
+#ifdef GST_TBM_SUPPORT
+#include <mm_types.h>
+#endif
 /* signals */
 enum
 {
@@ -55,6 +58,9 @@ enum
   PROP_0,
   PROP_SOCKET_PATH,
   PROP_IS_LIVE
+#ifdef GST_TBM_SUPPORT
+  ,PROP_USE_TBM
+#endif
 };
 
 struct GstShmBuffer
@@ -130,6 +136,14 @@ gst_shm_src_class_init (GstShmSrcClass * klass)
       g_param_spec_boolean ("is-live", "Is this a live source",
           "True if the element cannot produce data in PAUSED", FALSE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#ifdef GST_TBM_SUPPORT
+  g_object_class_install_property (gobject_class, PROP_USE_TBM,
+      g_param_spec_boolean ("use-tbm",
+          "Use of not the tizen buffer",
+          "Flags of using tizen buffer",
+          FALSE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
 
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&srctemplate));
@@ -148,6 +162,7 @@ gst_shm_src_init (GstShmSrc * self)
 {
   self->poll = gst_poll_new (TRUE);
   gst_poll_fd_init (&self->pollfd);
+  self->h_bufmgr = tbm_bufmgr_init(-1);
 }
 
 static void
@@ -157,6 +172,7 @@ gst_shm_src_finalize (GObject * object)
 
   gst_poll_free (self->poll);
   g_free (self->socket_path);
+  tbm_bufmgr_deinit(self->h_bufmgr);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -184,6 +200,13 @@ gst_shm_src_set_property (GObject * object, guint prop_id,
       gst_base_src_set_live (GST_BASE_SRC (object),
           g_value_get_boolean (value));
       break;
+#ifdef GST_TBM_SUPPORT
+    case PROP_USE_TBM:
+      GST_OBJECT_LOCK (object);
+      self->use_tbm = g_value_get_boolean (value);
+      GST_OBJECT_UNLOCK (object);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -205,6 +228,11 @@ gst_shm_src_get_property (GObject * object, guint prop_id,
     case PROP_IS_LIVE:
       g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (object)));
       break;
+#ifdef GST_TBM_SUPPORT
+    case PROP_USE_TBM:
+      g_value_set_boolean (value, self->use_tbm);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -286,7 +314,6 @@ gst_shm_src_stop (GstBaseSrc * bsrc)
   return TRUE;
 }
 
-
 static void
 free_buffer (gpointer data)
 {
@@ -305,6 +332,25 @@ free_buffer (gpointer data)
   g_slice_free (struct GstShmBuffer, gsb);
 }
 
+#ifdef GST_TBM_SUPPORT
+static void
+free_tbm_buffer (gpointer data)
+{
+  MMVideoBuffer * mm_video_buf = data;
+  int i;
+  GST_LOG ("Freeing tbm buffer %p", data);
+
+  for(i = 0; i < MM_VIDEO_BUFFER_PLANE_MAX; i++) {
+    if(mm_video_buf->handle.bo[i])
+      tbm_bo_unref(mm_video_buf->handle.bo[i]);
+    else
+      break;
+  }
+
+  g_free(mm_video_buf);
+}
+#endif
+
 static GstFlowReturn
 gst_shm_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
 {
@@ -360,6 +406,46 @@ gst_shm_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
 
   *outbuf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
       buf, rv, 0, rv, gsb, free_buffer);
+#ifdef GST_TBM_SUPPORT
+  GST_DEBUG_OBJECT(self, "use-tbm %d", self->use_tbm);
+  if (self->use_tbm) {
+    MMVideoBuffer *mm_video_buf = NULL;
+    GstMemory *mem_imgb = NULL;
+    unsigned key[MM_VIDEO_BUFFER_PLANE_MAX];
+    int offset = rv - sizeof(MMVideoBuffer) - sizeof(key);
+    if(offset < 0) {
+      GST_ERROR_OBJECT(self, "offset error %d", offset);
+      return GST_FLOW_ERROR;
+    }
+
+    mm_video_buf = g_malloc0(sizeof(MMVideoBuffer));
+    mem_imgb = gst_memory_new_wrapped(0, mm_video_buf, sizeof(MMVideoBuffer), 0,
+        sizeof(MMVideoBuffer), mm_video_buf, free_tbm_buffer);
+    gst_buffer_append_memory(*outbuf, mem_imgb);
+
+    memcpy(mm_video_buf, buf + offset, sizeof(MMVideoBuffer));
+    memcpy(key, buf + rv - sizeof(key), sizeof(key));
+    if (mm_video_buf->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
+      int i;
+      GST_DEBUG_OBJECT(self, "width %d, height %d", mm_video_buf->width[0],
+          mm_video_buf->height[0]);
+
+      memset(mm_video_buf->handle.bo, 0, sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
+      for(i = 0; i < MM_VIDEO_BUFFER_PLANE_MAX; i++) {
+        GST_DEBUG_OBJECT(self, "%d tbm bo key %d", i, key[i]);
+        if(key[i] > 0)
+          mm_video_buf->handle.bo[i] = tbm_bo_import(self->h_bufmgr, key[i]);
+        else
+          break;
+      }
+      GST_DEBUG_OBJECT (self, "TBM bo %p %p", mm_video_buf->handle.bo[0],
+          mm_video_buf->handle.bo[1]);
+    } else {
+      GST_WARNING_OBJECT(self, "invaild type %d", mm_video_buf->type);
+      return GST_FLOW_ERROR;
+    }
+  }
+#endif
 
   return GST_FLOW_OK;
 }
index 04797ab..8bbe1c4 100644 (file)
@@ -27,6 +27,9 @@
 #include <gst/base/gstbasesrc.h>
 
 #include "shmpipe.h"
+#ifdef GST_TBM_SUPPORT
+#include <tbm_bufmgr.h>
+#endif
 
 G_BEGIN_DECLS
 #define GST_TYPE_SHM_SRC \
@@ -56,6 +59,10 @@ struct _GstShmSrc
 
   GstFlowReturn flow_return;
   gboolean unlocked;
+#ifdef GST_TBM_SUPPORT
+  gboolean use_tbm;
+  tbm_bufmgr h_bufmgr;
+#endif
 };
 
 struct _GstShmSrcClass